Lucas S. Vieira


Embeddings, Similaridade e RAG


Texto como números, busca e geração


Guilda de IA

Recap: Semana 08

  • create_agent encadeia chamadas automaticamente
  • Descrição específica = agente sabe qual ferramenta usar
  • MCP: ferramentas escritas por outras pessoas, via stdio ou HTTP
  • Múltiplos servidores com AsyncExitStack

"Semana passada ele ganhou ferramentas. Hoje aprende a ler."

🔴 O problema: LLMs não sabem tudo

LLMs não conhecem:

  • Seus documentos pessoais
  • PDFs da empresa
  • Notas privadas
  • Informações recentes (pós-treinamento)

E agora?

🔴 A solução: RAG

RAG = Retrieval Augmented Generation

Buscar informações relevantes antes de gerar a resposta.

"RAG = buscar antes de responder."

Analogia

  • Sem RAG: aluno fazendo prova de memória
  • Com RAG: aluno fazendo prova com livro aberto

Fluxo RAG

  1. Chunking → divide documentos em pedaços
  2. Embeddings → transforma texto em vetores
  3. Vector Store → guarda os vetores
  4. Retrieval → busca pedaços relevantes
  5. Generation → LLM responde com contexto

Mas como funciona a "busca"?

O retrieval é o coração do RAG.

E a busca tem duas abordagens que se complementam:

  • Busca lexical — encontra palavras exatas
  • Busca semântica — encontra significados

Vamos ver cada uma separadamente, e depois juntar.

🟡 Busca Lexical: BM25

"Como o Google buscava antes de IA."

BM25 (Best Matching 25) é o algoritmo de busca lexical mais usado.

Está no Elasticsearch, no Lucene, no Sphinx…

E é mais inteligente do que parece.

A fórmula (não se assuste!)

score(q,D) = Σi IDF(qi) · f(qi,D) · (k1+1) / [ f(qi,D) + k1 · (1 − b + b · fieldLen / avgFieldLen ) ]

Parece assustador? Calma. Cada parte é bom senso. Vamos decompor:

🟢 IDF = Inverse Document Frequency — termos raros valem mais. "elefante" em poucos docs → IDF alto → vale mais. "the" em quase todos → IDF baixo → vale menos.

🔵 f(q,D) = quantas vezes o termo aparece no documento. Mais aparições = provavelmente mais relevante.

🟠 k₁ = saturação — a 1ª menção vale muito, a 10ª vale quase nada extra. "gato" 100 vezes ≠ 100× mais relevante que 1 vez. Default: k₁ = 1.2

🟣 b = quanto o tamanho do doc afeta o score. b = 0 → tamanho não importa. b = 1 → importa muito. Default: 0.75. Tweet com "gato" > livro de 300 páginas com "gato" 1 vez.

🔴 fieldLen/avgFieldLen = tamanho relativo à média. Doc curto acima da média → score sobe. Doc longo acima da média → score cai.

BM25 é bom senso codificado em matemática. Bom pra: nomes, termos técnicos, códigos, IDs. Mas não entende sinônimos.

🟢 Busca Semântica: Embeddings

E se a pessoa busca por "animal que faz miau" mas o documento diz "gato"?

BM25 não acha. Mas embeddings sim.

Cada texto vira um vetor — uma lista de números que captura significado.

Exemplo visual

Texto Vetor (simplificado)
"gato" [0.2, 0.8, 0.1]
"cachorro" [0.3, 0.7, 0.2]
"carro" [0.9, 0.1, 0.3]
Visualização 3D de embeddings

"gato" e "cachorro" são mais próximos! "carro" está longe.

Espaço vetorial

  • Textos com significado parecido = setas na mesma direção
  • Textos com significado diferente = setas em direções diferentes

"Mesma direção" = ângulo pequeno entre elas.

Similaridade por Cosseno

Conexão com Geometria Analítica!

\[\cos(\theta) = \frac{\vec{A} \cdot \vec{B}}{|\vec{A}| \cdot |\vec{B}|}\]

  • ângulo = 0° → cosseno = 1 → idênticos
  • ângulo = 90° → cosseno = 0 → independentes
  • ângulo = 180° → cosseno = -1 → opostos

🟣 Busca Híbrida: o melhor dos dois mundos

  • BM25 acha termos exatos (nomes, códigos, IDs)
  • Embeddings acham significados (paráfrases, conceitos)

Por que não usar os dois?

RRF (Reciprocal Rank Fusion) — junta os rankings das duas buscas.

\[\text{RRF}(d) = \sum_{m \in \text{métodos}} \frac{1}{k + \text{rank}_m(d)}\]

Cada método ordena os documentos. O RRF combina as posições.

Cada método vê um lado. Juntos, veem mais.

E ainda existe um degrau a mais: reranking

  • RRF junta rankings baratos; reranking reordena os melhores com um modelo mais pesado
  • Cross-encoder: lê pergunta e documento juntos (embeddings pontuam cada um separado)
  • Open-source e roda local: bge-reranker, Qwen3-Reranker
  • Opcional: entra quando qualidade de busca > latência

Primeiro o funil rápido. Depois, quem decide é o especialista.

📓 Demo prática: FAISS

Vamos ver isso funcionando de verdade no Colab!

  • Modelo no Colab: embeddinggemma-2 — Google, 740M, multimodal (768 dim, MRL 256)
  • Vector store: FAISS (Facebook AI Similarity Search)
  • Agente: gemma4:e2b-it-qat com ferramenta de busca

📓 Colab

Para lembrar

  1. RAG = buscar antes de responder
  2. BM25 = busca lexical (IDF, frequência, saturação, tamanho)
  3. Embeddings = texto como vetores (similaridade por cosseno)
  4. Busca híbrida = BM25 + embeddings + RRF
  5. FAISS = vector store rápido e simples pra demo
  6. Na S10 (27/11): Fine-Tuning

"Embeddings transformam significado em geometria. RAG transforma geometria em respostas."

Perguntas?