Phase 05 - Lesson 22

Modelos de Embedding — O Mergulho Profundo de 2026

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

O Word2Vec dava a você um vetor por palavra. Os modelos de embedding modernos dão um vetor por trecho, cross-lingual, com visões esparsas, densas e multivetoriais, dimensionados para caber no seu índice. Escolha errado e seu RAG recupera a coisa errada.

Tipo: Aprender Linguagens: Python Pré-requisitos: Fase 5 · 03 (Word2Vec), Fase 5 · 14 (Recuperação de Informação) Tempo: ~60 minutos

O Problema

Seu sistema RAG recupera o trecho errado 40% das vezes. O culpado raramente é o banco de dados vetorial ou o prompt. É o modelo de embedding.

Escolher um embedding em 2026 significa decidir entre cinco eixos:

  1. Denso vs esparso vs multivetorial. Um vetor por trecho, ou um por token, ou um saco esparso e ponderado de palavras.
  2. Cobertura de idiomas. Modelos monolíngues em inglês ainda vencem em tarefas exclusivamente em inglês. Modelos multilíngues vencem quando os corpora são mistos.
  3. Comprimento de contexto. 512 tokens vs 8.192 vs 32.768 — e a capacidade efetiva real costuma ser 60-70% do máximo anunciado.
  4. Orçamento de dimensão. 3.072 floats em precisão total = 12 KB por vetor. Com 100M de vetores, o armazenamento custa US$ 1.300/mês. A truncagem Matryoshka corta isso em 4×.
  5. Aberto vs hospedado. Pesos abertos significam que você controla a stack e os dados. Hospedado significa trocar controle por estar sempre na versão mais recente.

Esta lição nomeia os tradeoffs para que você escolha com base em evidências, não no que estava popular no trimestre passado.

O Conceito

Embeddings densos, esparsos e multivetoriais

Embeddings densos. Um vetor por trecho (geralmente 384-3.072 dimensões). A similaridade de cosseno classifica os trechos por proximidade semântica. OpenAI text-embedding-3-large, modo denso do BGE-M3, Voyage-3. Escolha padrão.

Embeddings esparsos. Estilo SPLADE. Um transformer prevê um peso para cada token do vocabulário e depois zera a maioria deles. O resultado é um vetor esparso de tamanho |vocab|. Captura correspondência lexical (como o BM25), mas com pesos de termos aprendidos. Forte em consultas com muitas palavras-chave.

Multivetorial (interação tardia). ColBERTv2, Jina-ColBERT. Um vetor por token. Pontuação com MaxSim: para cada token da consulta, encontre o token do documento mais similar e some as pontuações. Mais caro de armazenar e pontuar, mas vence em consultas longas e corpora específicos de domínio.

BGE-M3: os três de uma vez. Um único modelo produz representações densas, esparsas e multivetoriais simultaneamente. Cada uma pode ser consultada de forma independente; as pontuações se fundem por soma ponderada. O padrão de 2026 quando você quer flexibilidade a partir de um único checkpoint.

Matryoshka Representation Learning. Treinado para que as primeiras N dimensões do vetor formem um embedding autônomo útil. Trunque um vetor de 1.536 dimensões para 256 e pague ~1% de acurácia por uma economia de 6× no armazenamento. Suportado por OpenAI text-3, Cohere v4, Voyage-4, Jina v5, Gemini Embedding 2, Nomic v1.5+.

O leaderboard MTEB conta uma história parcial

Massive Text Embedding Benchmark — 56 tarefas em 8 tipos de tarefa no lançamento (2022), expandido para mais de 100 tarefas no MTEB v2. No início de 2026, o Gemini Embedding 2 lidera em recuperação (67,71 MTEB-R). O Cohere embed-v4 lidera no geral (65,2 MTEB). O BGE-M3 lidera entre os multilíngues de pesos abertos (63,0). O leaderboard é necessário, mas não suficiente — sempre faça benchmark no seu domínio.

O padrão de três camadas

Caso de uso Padrão
Primeira passagem rápida Bi-encoder denso (BGE-M3, text-3-small)
Aumento de recall Esparso (SPLADE, BGE-M3 esparso) + fusão RRF
Precisão no top-50 Multivetorial (ColBERTv2) ou reranker cross-encoder

A maioria das stacks de produção usa as três.

Construa

Passo 1: baseline — embeddings densos com Sentence-BERT

from sentence_transformers import SentenceTransformer
import numpy as np

encoder = SentenceTransformer("BAAI/bge-small-en-v1.5")
corpus = [
    "The first iPhone launched in 2007.",
    "Apple released the iPod in 2001.",
    "Android is an operating system from Google.",
]
emb = encoder.encode(corpus, normalize_embeddings=True)

query = "When was the iPhone released?"
q_emb = encoder.encode([query], normalize_embeddings=True)[0]
scores = emb @ q_emb
print(sorted(enumerate(scores), key=lambda x: -x[1]))

normalize_embeddings=True faz com que o produto escalar seja igual à similaridade de cosseno. Sempre defina isso.

Passo 2: truncagem Matryoshka

def truncate(vectors, dim):
    out = vectors[:, :dim]
    return out / np.linalg.norm(out, axis=1, keepdims=True)

emb_256 = truncate(emb, 256)
emb_128 = truncate(emb, 128)

Renormalize após a truncagem. Nomic v1.5, OpenAI text-3 e Voyage-4 são treinados de modo que isso seja sem perdas nos primeiros níveis. Modelos não Matryoshka (Sentence-BERT original) degradam bruscamente quando truncados.

Passo 3: multifuncionalidade do BGE-M3

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)

output = model.encode(
    corpus,
    return_dense=True,
    return_sparse=True,
    return_colbert_vecs=True,
)
# output["dense_vecs"]:    (n_docs, 1024)
# output["lexical_weights"]: list of dict {token_id: weight}
# output["colbert_vecs"]:  list of (n_tokens, 1024) arrays

Três índices, uma chamada de inferência. Fusão de pontuações:

dense_score = ... # cosine over dense_vecs
sparse_score = model.compute_lexical_matching_score(q_lex, d_lex)
colbert_score = model.colbert_score(q_col, d_col)
final = 0.4 * dense_score + 0.2 * sparse_score + 0.4 * colbert_score

Ajuste os pesos no seu domínio.

Passo 4: avaliação MTEB em uma tarefa customizada

from mteb import MTEB

tasks = ["ArguAna", "SciFact", "NFCorpus"]
evaluation = MTEB(tasks=tasks)
results = evaluation.run(encoder, output_folder="./mteb-results")

Rode seus modelos candidatos em um subconjunto representativo. Não confie apenas na posição do leaderboard — seu domínio importa.

Passo 5: cosseno feito à mão do zero

Veja code/main.py. Embeddings de Averaged Hashing Trick (somente stdlib). Não competitivo com embeddings de transformers, mas mostra o formato: tokenizar → vetor → normalizar → produto escalar.

Armadilhas

  • Mesmo modelo para consulta e documento. Alguns modelos (Voyage, Jina-ColBERT) usam codificação assimétrica — consulta e documento passam por caminhos diferentes. Sempre verifique o model card.
  • Prefixo ausente. Modelos bge-* precisam de "Represent this sentence for searching relevant passages: " prefixado às consultas. Lacuna de 3-5 pontos de recall se você esquecer.
  • Excesso de truncagem no Matryoshka. 1.536 → 256 costuma ser seguro. 1.536 → 64 não é. Valide no seu conjunto de avaliação.
  • Truncagem de contexto. A maioria dos modelos trunca silenciosamente entradas acima do comprimento máximo. Documentos longos precisam de chunking (veja a lição 23).
  • Ignorar a cauda de latência. As pontuações MTEB escondem a latência p99. Um modelo de 600M pode superar um de 335M por 2 pontos, mas custar 3× mais por consulta.

Use

A stack de 2026:

Situação Escolha
Só inglês, rápido, API text-embedding-3-large ou voyage-3-large
Pesos abertos, inglês BAAI/bge-large-en-v1.5
Pesos abertos, multilíngue BAAI/bge-m3 ou Qwen3-Embedding-8B
Contexto longo (32k+) Voyage-3-large, Cohere embed-v4, Qwen3-Embedding-8B
Deploy somente em CPU Nomic Embed v2 (137M params, MoE)
Restrito por armazenamento Truncado por Matryoshka + quantização int8
Consultas com muitas palavras-chave Adicione SPLADE esparso, fusão RRF com denso

Padrão de 2026: comece com BGE-M3 ou text-3-large, avalie no seu domínio com MTEB, troque se um modelo específico de domínio vencer por mais de 3 pontos.

Entregue

Salve como outputs/skill-embedding-picker.md:

---
name: embedding-picker
description: Pick embedding model, dimension, and retrieval mode for a given corpus and deployment.
version: 1.0.0
phase: 5
lesson: 22
tags: [nlp, embeddings, retrieval]
---

Given a corpus (size, languages, domain, avg length), deployment target (cloud / edge / on-prem), latency budget, and storage budget, output:

1. Model. Named checkpoint or API. One-sentence reason.
2. Dimension. Full / Matryoshka-truncated / int8-quantized. Reason tied to storage budget.
3. Mode. Dense / sparse / multi-vector / hybrid. Reason.
4. Query prefix / template if required by the model card.
5. Evaluation plan. MTEB tasks relevant to domain + held-out domain eval with nDCG@10.

Refuse recommendations that truncate Matryoshka to <64 dims without domain validation. Refuse ColBERTv2 for corpora under 10k passages (overhead not justified). Flag long-document corpora (>8k tokens) routed to models with 512-token windows.

Exercícios

  1. Fácil. Codifique 100 frases com bge-small-en-v1.5 em dimensão total (384) e depois em Matryoshka 128. Meça a queda de MRR em 10 consultas.
  2. Médio. Compare denso, esparso e colbert do BGE-M3 em 500 trechos do seu domínio. Qual vence em recall@10? A fusão RRF supera o melhor modo isolado?
  3. Difícil. Rode o MTEB em três modelos candidatos nas suas top-2 tarefas de domínio. Reporte a pontuação MTEB, a latência p99 em um lote de 100 consultas e o US$/1M de consultas. Escolha o Pareto-ótimo.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
Embedding denso O vetor Um vetor de tamanho fixo por texto. Similaridade de cosseno para classificação.
Embedding esparso BM25 aprendido Um peso por token do vocabulário; majoritariamente zeros; treinado de ponta a ponta.
Multivetorial Estilo ColBERT Um vetor por token; pontuação MaxSim; índice maior, melhor recall.
Matryoshka Truque da boneca russa As primeiras N dimensões são, por si só, um embedding menor válido.
MTEB O benchmark Massive Text Embedding Benchmark — 56 tarefas no lançamento, mais de 100 no v2.
BEIR O benchmark de recuperação 18 tarefas de recuperação zero-shot; frequentemente citado para robustez entre domínios.
Codificação assimétrica Consulta ≠ caminho do doc O modelo usa projeções diferentes para consultas e documentos.

Leitura Complementar

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).