Embeddings de busca: BGE-M3, e5, Voyage, Cohere v3
- ⬜🎯 Hybrid search + reranking: BM25 + dense + cross-encoder(Search & Information Retrieval Profundo)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
O ecossistema de embeddings em 2026
Em 2026 o mercado de embeddings de busca consolidou em ~6 players principais: BGE-M3 (BAAI, open source), e5 (Microsoft, open source), Voyage AI (proprietário, API), Cohere embed v3 (proprietário), OpenAI text-embedding-3 (proprietário), e Jina Embeddings v3 (open source). Cada um com trade-offs distintos.
Este módulo mapeia o ecossistema, explica diferenças arquiteturais (bi-encoder vs multi-vector vs sparse), conceitos como Matryoshka, e dá um framework de decisão concreto.
Referências: BGE-M3 paper (Chen et al. 2024, arXiv:2402.03216); E5 paper (Wang et al. 2022, "Text Embeddings by Weakly-Supervised Contrastive Pre-training"); Matryoshka Representation Learning (Kusupati et al. NeurIPS 2022); MTEB Leaderboard em huggingface.co/spaces/mteb/leaderboard.
Linha do tempo dos embeddings de retrieval
Bi-encoder vs Multi-vector vs Sparse
| Aspecto | Bi-encoder (dense) | Multi-vector (ColBERT) | Sparse aprendida (SPLADE) |
|---|---|---|---|
| Como representa | 1 vetor denso por doc/query | N vetores (1 por token) por doc/query | Vetor esparso com pesos por vocabulário |
| Similaridade | Produto escalar (cosseno) | Sum of max similarities (MaxSim) | Produto escalar sobre vocab |
| Indexação | HNSW/IVF | Especial (PLAID, etc) | Inverted index (como BM25) |
| Tamanho índice (1M docs) | ~1.5 GB (1024-d fp16) | ~30 GB (200 tokens × 128-d) | ~2 GB (esparso comprimido) |
| Precisão típica | Boa | Excelente (top em benchmarks) | Boa-excelente |
| Latência query | <10ms (ANN) | 20-100ms (mais complexa) | <20ms (inverted index) |
| Exemplos | BGE-M3 (dense mode), e5, Voyage | BGE-M3 (multi-vector mode), ColBERTv2 | BGE-M3 (sparse mode), SPLADE++ |
Em 2026, BGE-M3 é uma das poucas opções que oferece os três modos no mesmo modelo. Você pode indexar dense para retrieval barato e usar sparse ou multi-vector para reranker, sem dependências adicionais.
Matryoshka Representation Learning (MRL)
MRL (Kusupati et al., NeurIPS 2022) treina o modelo de modo que truncar o vetor para K dimensões iniciais ainda produza uma representação útil. Em produção, isso permite trade-off custo × precisão sem retreinar.
# OpenAI text-embedding-3-large suporta MRL nativo
from openai import OpenAI
client = OpenAI()
resp_full = client.embeddings.create(
model="text-embedding-3-large",
input=["semântica de busca em produção"],
dimensions=3072, # default
)
resp_small = client.embeddings.create(
model="text-embedding-3-large",
input=["semântica de busca em produção"],
dimensions=256, # MRL truncado — ainda útil!
)
# Vantagem: 256-d ocupa 12× menos memória que 3072-d
# - Vector DB: 1B vetores × 3072-d × 4 bytes = 12 TB
# - Vector DB: 1B vetores × 256-d × 4 bytes = 1 TB
# Ou com int8 quantização: 256 bytes → 250 GB
# Trade-off: NDCG@10 cai ~2-3 pontos em 256-dPadrão em produção: dual indexing. Indexe 256-d (ou 384-d) para retrieval rápido (top-100), re-pontue top-K com 1024-d (ou 3072-d) para precisão final. Cohere v3, OpenAI v3, BGE-M3 e Voyage 3 suportam.
Comparativo dos top 6 embeddings de busca em 2026
| Modelo | Origem | Open? | Dim | Max tokens | MTEB-R médio | Custo |
|---|---|---|---|---|---|---|
| BGE-M3 | BAAI (China, 2024) | Sim (MIT) | 1024 | 8192 | ~0.59 | Self-host (GPU) |
| e5-large-v2 | Microsoft (2023) | Sim (MIT) | 1024 | 512 | ~0.57 | Self-host (GPU) |
| multilingual-e5-large | Microsoft (2023) | Sim (MIT) | 1024 | 512 | ~0.56 | Self-host |
| Voyage-3-large | Voyage AI (2024) | Não (API) | 1024 (MRL) | 32k | ~0.62 | $0.12/1M tokens |
| Cohere embed-v3 | Cohere (2023) | Não (API) | 1024 (MRL) | 512 | ~0.58 | $0.10/1M tokens |
| OpenAI text-embedding-3-large | OpenAI (2024) | Não (API) | 3072 (MRL) | 8191 | ~0.55 | $0.13/1M tokens |
| Jina v3 | Jina AI (2024) | Sim (CC-BY-NC) | 1024 (MRL) | 8192 | ~0.56 | Self-host |
MTEB-R médio é uma média global em BEIR. Performance varia muito por domínio. Para PT-BR especificamente, BGE-M3 e Cohere multilingual lideram em benchmarks da comunidade brasileira.
Como escolher na prática
📋 RAG corporativo, dados sensíveis, on-prem obrigatório
Open source MIT, sem licenciamento; Multilingual nativo (excelente PT-BR); Multi-functionality (dense + sparse + multi-vec no mesmo modelo); Roda em GPU L4/A10 com throughput decente (~500 docs/s)
Alt: multilingual-e5-large — mais antigo, dimensão menor, mas estável e testado
Alt: Jina v3 — boa qualidade, mas licença não-comercial restritiva
📋 Startup com pouco volume, prioridade DX, sem ops de GPU
API simples, zero ops; Estado-da-arte em benchmark (Voyage); Variantes especializadas (code, finance, multilingual); Pricing previsível por tokens
Alt: OpenAI text-embedding-3 — competitivo, integração trivial com stack OpenAI
📋 Volume massivo (>10B tokens/mês), custo crítico
Custo por 1M tokens via API: $0.10-0.15 = $10-15 por bilhão de tokens; 10B tokens via Voyage = $1k-1.5k por mês; GPU A10/L4 dedicada amortizada: $300-500/mês, processa muito mais que isso; Economia escala com volume
Qual é a diferença entre um codificador único e um codificador cruzado?
Código: BGE-M3 com sentence-transformers e FlagEmbedding
# Opção 1: FlagEmbedding (oficial BAAI, suporta os 3 modos)
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)
output = model.encode(
["query: como ajustar autovacuum em postgres",
"passage: O autovacuum do Postgres elimina tuplas mortas..."],
return_dense=True,
return_sparse=True,
return_colbert_vecs=True,
)
# output["dense_vecs"]: matriz (N, 1024)
# output["lexical_weights"]: lista de dicts {token_id: peso} (sparse)
# output["colbert_vecs"]: lista de matrizes (tokens_doc, 128)
# Opção 2: sentence-transformers (dense only, mas integração trivial)
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("BAAI/bge-m3")
embeddings = model.encode(
["docs aqui..."],
normalize_embeddings=True,
batch_size=32,
show_progress_bar=False,
)
# Throughput típico em A10 (24GB):
# - BGE-M3 dense: ~500 docs/s (batch 32, sequência média 256)
# - Custo por bilhão de docs: ~$0.30 amortizado (24h × $13/h)
# - Equivalente via Voyage API: ~$120 (1B docs × 200 tokens × $0.12/1M / 200)Tarefas de instrução e prompt prefixing
Modelos modernos (e5, BGE, Voyage, Cohere) foram treinados com prefixes específicos para indicar tipo de input. Ignorar isso degrada performance em 2-5 pontos NDCG.
Sempre leia o model card antes de usar. Trocar prefixos errados ou esquecê-los é o erro #1 em projetos de RAG amador. Pode fazer NDCG cair pela metade.
Fine-tuning para domínio
Embeddings genéricos atingem ~0.55-0.62 NDCG@10 em benchmarks como BEIR. Para seu domínio específico, fine-tuning com 1-10k pares (query, doc_relevante, doc_irrelevante) pode subir esse número para 0.70-0.80.
# Fine-tuning de BGE-M3 com contrastive loss (didático)
from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader
model = SentenceTransformer("BAAI/bge-m3")
# Triplets: (query, doc_relevante, doc_irrelevante)
triplets = [
InputExample(texts=["como tunar autovacuum", "postgres autovacuum settings...", "react state management..."]),
# ... 1k-10k triplets do seu domínio
]
loader = DataLoader(triplets, shuffle=True, batch_size=16)
loss = losses.TripletLoss(model=model)
model.fit(
train_objectives=[(loader, loss)],
epochs=3,
warmup_steps=100,
output_path="./bge-m3-postgres-domain",
)
# Hard negative mining (recomendado):
# - Para cada query relevante, busque top-50 com modelo base
# - Pegue exemplos top que NÃO são relevantes (anotação manual ou heurística)
# - Esses são "hard negatives" — força o modelo a aprender distinções finasPerguntas frequentes
❓ Embedding de tamanho menor é sempre pior?
❓ Posso misturar embeddings de modelos diferentes no mesmo índice?
❓ Quantização int8 ou binário compromete muito?
❓ E para código fonte, qual embedding?
Resumo executivo
Em 2026, BGE-M3 é a escolha default para times pragmáticos: open source, multilingual, multi-funcional. Voyage e Cohere lideram em benchmarks mas custam por API. OpenAI v3 é "competitivo" — não líder, mas integração trivial.
Próximo: semantic search em produção — ingest pipelines, sharding, freshness, blue-green reindex, custo de embedding em escala bilhão.
Fixando
O que a representação com dimensões aninhadas permite na prática?
Por que representações esparsas voltaram a ser relevantes?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…