RAG e Data Embedding

Danrley Morais
January 27, 2025

RAG e Data Embedding

Sempre pensamos em trabalhar nossos dados integrados com modelos de LLMs, e esbarrar em um conceito chamado Embedding

RAG e Data Embedding


Sempre que pensarmos em trabalhar com nossos dados integrados com modelos de LLMs, vamos esbarrar em um conceito chamado Embeddings, que em um primeiro momento, pode ser algo complexo de entender (em um segundo, terceiro e quarto também, rs) - mas vamos tentar simplificar.

O custo para treinar um modelo de LLM é alto, fazer fine-tuning também pode ser trabalhoso, aí entra o conceito de RAG, que vamos entender um pouco mais pra frente.

Modelos de embedding transformam textos em números, é como um tradutor realmente, ele foi treinado com uma quantidade significativa de dados e quando eu envio um texto, ele simplesmente executa esse código que faz essa tradução.

E é isso que permite que frases diferentes, mas com um mesmo significado sejam identificadas de forma similar. Por exemplo:

Note que as quatro primeiras frases, mesmo escritas de formas diferentes, geram embeddings similares porque têm a mesma intenção/significado. Já a última frase, sobre pudim, gera números bem diferentes.
O processo funciona assim:
  1. O texto é quebrado em tokens (pedaços que podem ser palavras ou sub-palavras)
  2. Cada token é processado considerando seu contexto
  3. O modelo gera uma lista de números que representa o significado do texto
  4. Textos similares geram números similares

E porque isso importa? Quando eu pego por exemplo uma base de conhecimento antiga, com chamados resolvidos, manuais, histórico de aulas e quero que um modelo de LLM responda com base nessas informações, eu preciso basicamente:

  1. Criar embeddings de todo esse conteúdo
    • Quebrar documentos em chunks (pedaços menores) - isso é importante, porque de forma parecida com um banco de dados, nós precisamos separar esses itens em “itens” de uma tabela, agrupado por registros,
    • Gerar embeddings para cada chunk
    • Armazenar em um banco de dados vetorial (como Pinecone, Qdrant, pgvector)
  2. Quando uma pergunta chega:
    • Gerar embedding da pergunta
    • Pesquisar por similaridade no banco de dados vetorial
    • Recuperar os chunks mais relevantes
  3. Enviar para o LLM:
    • A pergunta original
    • O conteúdo relevante encontrado
    • Um prompt que instrui como usar esse conteúdo
    • O LLM então gera uma resposta contextualizada

Este processo é o que chamamos de RAG (Retrieval Augmented Generation), porque:

  • Retrieval: recuperamos informação relevante do nosso banco de dados
  • Augmented: aumentamos/melhoramos o conhecimento do LLM
  • Generation: geramos uma resposta com base nesse contexto

E um ponto importante, quebrar documentos em chunks (pedaços menores) é uma etapa crucial no processo de RAG. Pense nisso como criar "unidades semânticas" do seu conteúdo - similar a um banco de dados, mas em vez de registros estruturados, queremos blocos de texto que mantenham significado coeso.

Por exemplo:

  • Um manual técnico pode ser dividido por seções ou procedimentos completos
  • Uma base de chamados pode ser dividida por problema/solução
  • Um material didático pode ser dividido por conceitos ou tópicos

O tamanho desses chunks geralmente varia entre 256 e 1024 tokens, com alguma sobreposição (overlap) de 10-20% para manter contexto entre eles. É um balanço entre:

  • Manter contexto suficiente para respostas precisas
  • Ter granularidade adequada para buscas eficientes
  • Otimizar o uso de recursos (custo, processamento)

Diferente de um banco de dados tradicional, onde os registros têm estrutura fixa, no RAG os chunks podem ter tamanhos variáveis para preservar a coerência do conteúdo. O importante é que cada chunk mantenha uma unidade lógica de informação completa o suficiente para ser útil em uma resposta.

E apenas para fixarmos nosso conteúdo, vejamos abaixo um exemplo de como isso funciona na prática com um exemplo extremamente simples.

Imagine que esse é o passo a passo para instalarmos o docker:

Como configurar o Docker

Passo 1: Instale o Docker
- Acesse docker.com
- Baixe a versão para seu SO
- Execute o instalador

Passo 2: Verifique a instalação
- Abra o terminal
- Digite docker --version
Dividido em Chunks

Chunk ID: chunk_1_1
Como configurar o Docker

Passo 1: Instale o Docker
- Acesse docker.com
- Baixe a versão para seu SO
- Execute o instalador

Metadados e Embedding
Embedding: [0.23, 0.45, -0.12, ...]
Metadata:
{
  "source": "manual_docker.pdf",
  "page": 1,
  "topic": "instalação"
} 
Chunk ID: chunk_1_2
Passo 2: Verifique a instalação
- Abra o terminal
- Digite docker --version
Metadados e Embedding
Embedding: [0.21, 0.48, -0.15, ...]
Metadata:
{
  "source": "manual_docker.pdf",
  "page": 1,
  "topic": "verificação"
}


Agora um exemplo de um chamado no suporte:

Documento Original: Ticket de Suporte
Problema: Docker não inicia no Windows
Erro: daemon não responde
Solução: Reinicie o Docker Desktop e verifique se o WSL2 está habilitado
Dividido em Chunks
Chunk ID: chunk_2_1
Problema: Docker não inicia no Windows
Erro: daemon não responde
Solução: Reinicie o Docker Desktop e verifique se o WSL2 está habilitado
Metadados e Embedding
Embedding: [0.31, 0.52, -0.18, ...]
Metadata:
{
  "source": "ticket_123",
  "date": "2024-01-10",
  "status": "resolved"
}

E para fecharmos, alguns pontos importantes:

  • Cada chunk mantém uma unidade lógica completa
  • Embeddings são vetores de números que representam o significado do texto
  • Metadados ajudam a rastrear a origem e contexto do chunk
  • A busca é feita comparando o embedding da pergunta com os embeddings armazenados

Então é assim que podemos salvar nossas informações para trabalharmos com modelos de LLM:

  1. Processo de Armazenamento:
    • Texto vira embedding (aquela "tradução" para números)
    • É armazenado em um banco de dados vetorial
    • Junto com metadados importantes sobre o conteúdo
  2. Quando uma pergunta chega, nós fazemos o processo de RAG (Retrieval Augmented Generation):
    • Retrieval (Busca): transformamos a pergunta em embedding e buscamos conteúdo similar no banco
    • Augmented (Aumento): pegamos esse conteúdo relevante encontrado
    • Generation (Geração): enviamos para o modelo a pergunta + conteúdo encontrado, e ele gera uma resposta que faz sentido

É como dar ao modelo uma "cola" personalizada para cada pergunta, usando nossa própria base de conhecimento.

Danrley Morais
January 27, 2025