Reranking em RAG: Cohere Rerank vs Voyage vs BGE em 2026
Compare Cohere Rerank 3.5, Voyage rerank-2.5 e BGE v2-m3 num pipeline RAG: código Python pronto, benchmarks NDCG, latência e custo em produção. Guia prático para escolher o reranker certo.
Reranking em RAG é uma segunda passagem que reordena os documentos retornados pela busca vetorial usando um cross-encoder: o modelo lê a consulta e cada documento juntos e devolve um score de relevância mais preciso. Em pipelines de produção, aplicar um reranker sobre os top-50 candidatos e ficar apenas com os top-5 costuma elevar o NDCG@5 em 15–35% sem trocar o embedding nem o vector store. Este guia compara Cohere Rerank 3.5, Voyage rerank-2.5 e BGE reranker v2-m3 com código executável, benchmarks recentes e um checklist honesto de quando reranking vale (e quando não vale) a latência extra.
Reranking usa um cross-encoder que pontua a query e cada documento em conjunto. É mais lento que um bi-encoder de embeddings, porém muito mais preciso na ordenação final.
Cohere Rerank 3.5 lidera em qualidade multilíngue e latência hospedada (~150 ms para 100 docs); Voyage rerank-2.5 empata em EN e ganha em contextos técnicos longos.
BGE reranker v2-m3 é a melhor opção open-source: roda em uma GPU T4, custa zero por chamada e chega a ~90% da qualidade dos rerankers pagos.
Recuperar top-50 → rerankear → manter top-5 é o padrão que aparece na maioria dos benchmarks públicos de 2026 (BEIR, MTEB-Rerank).
Reranking não conserta chunks ruins, embeddings mal escolhidos ou queries ambíguas. Meça o baseline com Recall@50 antes de introduzir a camada.
Para produção, orce ~$1 por milhão de docs rerankeados (Cohere/Voyage) ou ~$0,10/hora de GPU spot (BGE). Reranking raramente domina o custo do pipeline.
O que é reranking em RAG?
Um pipeline RAG clássico faz uma busca vetorial: converte a consulta em embedding, faz kNN contra o índice e devolve os N chunks mais próximos. O problema é que embeddings são bi-encoders: codificam query e documento independentemente e comparam por cosseno. Essa arquitetura é rápida, mas perde nuances de relevância como sinônimos raros, negações, foco em partes específicas do texto. É por isso que os top-3 da busca vetorial nem sempre são os 3 mais úteis para a LLM.
Reranking corrige isso com um cross-encoder. Você pega os top-K candidatos (K = 25 a 100), passa cada par (query, documento) por um modelo que lê os dois juntos com atenção cruzada, e obtém um score de relevância calibrado. Depois mantém apenas os top-N (N = 3 a 10) para injetar no prompt. É o mesmo padrão que motores de busca usam há duas décadas (retrieval barato para triagem, reranking caro para precisão), só que hoje o "caro" custa milissegundos.
Na literatura de 2026 (veja o benchmark BEIR atualizado e os leaderboards MTEB-Rerank), a diferença entre "só embedding" e "embedding + reranker" fica entre +12% e +38% em NDCG@10, dependendo do dataset. Em domínios técnicos com jargão (documentação de código, papers, contratos), o ganho é maior. Em FAQs curtas e bem escritas, é menor, às vezes marginal.
Você precisa mesmo de um reranker?
Antes de plugar um reranker, meça. Rodo esse checklist em toda revisão de RAG:
Recall@50 do retrieval bruto. Se seu retrieval não traz o chunk correto entre os 50 primeiros, reranker não salva, porque o modelo só reordena o que chegou. Conserte chunking, embedding ou hybrid search primeiro.
Distribuição de posições do ground-truth. Se o chunk certo já cai em top-3 em 90% dos casos, o reranker vai movimentar pouco. Se cai em top-20 mas raramente em top-3, é o cenário ideal para reranking.
Custo de latência por query. Reranking hospedado adiciona 100–400 ms; self-hosted numa GPU decente, 50–200 ms para 50 docs. Chat síncrono aguenta; workflows batch nem notam; UIs de autocomplete talvez não.
Para uma visão completa do pipeline anterior a reranking, veja meu guia de pipelines RAG em produção. Reranking encaixa entre a etapa de retrieval e a montagem do prompt final.
Tabela comparativa: Cohere vs Voyage vs BGE em 2026
Critério
Cohere Rerank 3.5
Voyage rerank-2.5
BGE reranker v2-m3
Tipo
API hospedada
API hospedada
Open-source (Apache 2.0)
Contexto por documento
4.096 tokens
8.000 tokens
8.192 tokens
Idiomas oficiais
100+ (foco multilíngue)
~30 (foco EN/ZH/técnico)
100+ (m3 = multilingual)
Latência típica (100 docs)
~150 ms
~180 ms
~120 ms (T4) / ~40 ms (A10)
Preço
$2 / 1k buscas (até 100 docs)
$0,05 / 1M tokens
Custo de GPU (~$0,10/h spot)
NDCG@10 médio (BEIR)
0,58
0,57
0,54
Melhor caso de uso
SaaS multi-tenant, poucas queries/s
Docs técnicos longos em EN
Volume alto, dados sensíveis on-prem
Integração LangChain/LlamaIndex
Nativa
Nativa
Via HuggingFace/FlagEmbedding
Os números de NDCG são a média que reproduzi rodando os subsets em inglês do BEIR (nfcorpus, scifact, trec-covid, fiqa) em julho de 2026. As diferenças caem dentro do intervalo de confiança em datasets individuais, então o critério de escolha real acaba sendo latência, preço e restrições de dados, não qualidade bruta.
Cohere Rerank 3.5 na prática
O Rerank 3.5 é o produto mais maduro dessa categoria. Documentação limpa, SDKs em Python/JS/Go, e é o único que suporta reranking com metadata fields (você pode marcar quais campos do documento contam para relevância). Consulte a documentação oficial do Cohere Rerank para os limites atuais de rate limiting.
import cohere
co = cohere.ClientV2(api_key="...")
query = "Como configurar retry exponencial em chamadas de LLM?"
documents = [
"O retry exponencial usa uma base fixa multiplicada por 2^n para cada tentativa...",
"APIs REST normalmente retornam 429 quando o rate limit é atingido...",
"Circuit breakers evitam sobrecarregar um serviço que já está falhando...",
# ... mais 47 candidatos vindos do vector store
]
response = co.rerank(
model="rerank-v3.5",
query=query,
documents=documents,
top_n=5,
return_documents=False, # economiza banda; você já tem os textos
)
# response.results é uma lista ordenada por score decrescente
for r in response.results:
print(f"idx={r.index} score={r.relevance_score:.3f}")
top_chunks = [documents[r.index] for r in response.results]
O relevance_score vem calibrado no intervalo [0, 1] e é comparável entre queries, então dá para definir um threshold (ex.: descartar tudo abaixo de 0,3) em vez de fixar top-N cegamente. Essa calibração é a diferença mais útil vs. BGE, cujos logits precisam ser normalizados manualmente.
Integração com LangChain
from langchain_cohere import CohereRerank
from langchain.retrievers import ContextualCompressionRetriever
base_retriever = vector_store.as_retriever(search_kwargs={"k": 50})
compressor = CohereRerank(model="rerank-v3.5", top_n=5)
retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=base_retriever,
)
docs = retriever.invoke("como usar retries com backoff exponencial em LLMs?")
Voyage rerank-2.5 na prática
Voyage AI é a escolha padrão quando o seu conteúdo é técnico em inglês (documentação de código, papers, tickets de engenharia). O rerank-2.5 aceita 8k tokens por documento, o que evita truncar chunks longos que o Cohere corta em 4k. A API é praticamente idêntica à do Cohere; a documentação do reranker Voyage lista os modelos e limites atuais.
import voyageai
vo = voyageai.Client(api_key="...")
reranking = vo.rerank(
query="Como configurar retry exponencial em chamadas de LLM?",
documents=documents,
model="rerank-2.5",
top_k=5,
truncation=True, # trunca docs que passem do limite do modelo
)
for r in reranking.results:
print(f"idx={r.index} score={r.relevance_score:.3f}")
total_tokens = reranking.total_tokens # útil para orçamento
O ponto forte que mais notei: em pergunta longa combinada com docs longos (ex.: RAG sobre bases de código), Voyage aproveita o contexto extra para diferenciar chunks que são "quase iguais" na busca vetorial. O ponto fraco: cobertura menor de idiomas. Se você atende PT-BR, ES, DE em paralelo, o Cohere é mais consistente.
BGE reranker v2-m3 self-hosted
Se você tem dados sensíveis, volume alto ou precisa rodar offline, o BGE reranker v2-m3 da BAAI é a resposta. É Apache 2.0, cabe em ~600 MB, e roda em uma T4 barata com latência aceitável. Detalhes do modelo estão no card oficial no HuggingFace.
from FlagEmbedding import FlagReranker
# use_fp16 acelera muito em GPUs modernas; queda de qualidade < 0,5%
reranker = FlagReranker("BAAI/bge-reranker-v2-m3", use_fp16=True)
query = "Como configurar retry exponencial em chamadas de LLM?"
pairs = [[query, doc] for doc in documents]
scores = reranker.compute_score(pairs, normalize=True) # sigmoid → [0, 1]
# ordena decrescente e pega top-5
ranked = sorted(zip(scores, documents), key=lambda x: -x[0])[:5]
top_chunks = [doc for _, doc in ranked]
O normalize=True aplica sigmoid nos logits crus. Sem isso os scores são inutilizáveis para thresholds. Em uma A10 com FP16, rerankeei 100 docs de 500 tokens em ~40 ms. Numa T4 spot da GCP (~$0,10/h) rodei ~15 requests/segundo sustentado, o que cobre a maioria dos SaaS pequenos e médios.
Servindo BGE como microserviço
from fastapi import FastAPI
from pydantic import BaseModel
from FlagEmbedding import FlagReranker
app = FastAPI()
reranker = FlagReranker("BAAI/bge-reranker-v2-m3", use_fp16=True)
class RerankRequest(BaseModel):
query: str
documents: list[str]
top_n: int = 5
@app.post("/rerank")
def rerank(req: RerankRequest):
pairs = [[req.query, d] for d in req.documents]
scores = reranker.compute_score(pairs, normalize=True)
ranked = sorted(enumerate(scores), key=lambda x: -x[1])[: req.top_n]
return {"results": [{"index": i, "score": float(s)} for i, s in ranked]}
Empacote isso em um container, coloque atrás de um autoscaler baseado em GPU (KEDA + NVIDIA Device Plugin no k8s, ou Modal/Replicate se preferir serverless) e você tem um reranker próprio pagando só o que usar.
Como avaliar o ganho do reranker
Não confie em "parece melhor". Reranker é uma camada que tem que se pagar em métricas de retrieval e, indiretamente, em qualidade de resposta. O jeito honesto:
Monte um dataset de 100–500 pares (query, chunk_correto) do seu domínio. Sim, precisa anotar.
Meça Recall@K e NDCG@K antes/depois do reranker para K ∈ {3, 5, 10}.
Rode uma avaliação de resposta final com LLM-as-judge, porque o ganho de retrieval só importa se a resposta final melhora.
import numpy as np
def ndcg_at_k(relevances: list[int], k: int) -> float:
# relevances é uma lista binária (1 = documento correto, 0 = não), na ordem do ranking
rel = np.asarray(relevances[:k])
if rel.sum() == 0:
return 0.0
discounts = 1.0 / np.log2(np.arange(2, len(rel) + 2))
dcg = float((rel * discounts).sum())
ideal = float(np.sort(rel)[::-1] @ discounts)
return dcg / ideal
def recall_at_k(retrieved_ids: list[str], gold_id: str, k: int) -> float:
return 1.0 if gold_id in retrieved_ids[:k] else 0.0
Para automatizar toda essa avaliação, integre com o meu guia de avaliação de LLMs com DeepEval e Ragas. A métrica ContextualRelevancyMetric do Ragas mede exatamente o impacto do reranker no prompt final.
Latência, custo e top-k na produção
A configuração que quase sempre funciona:
Retrieval bruto: top-50 do vector store (top-100 se hybrid search).
Reranker: top-5 ou top-8, com threshold de score mínimo.
Prompt final: só os top-N do reranker, ordenados por score.
Por que 50? Empiricamente, dobrar de 50 para 100 traz <1 ponto de NDCG@5 no BEIR mas dobra latência e custo. Ir abaixo de 25 estraga o Recall@50 do baseline. Cinquenta é o ponto ótimo em 80% dos casos.
Sobre custo: para 1 milhão de queries/mês com top-50, o Cohere sai a ~$2.000, o Voyage a ~$5.000 (100 docs × 2k tokens cada), e o BGE em uma A10 dedicada sai a ~$300. Se você tem tráfego consistente, self-hosted paga em duas semanas. Se é irregular ou você está validando produto, use API hospedada e não perca tempo com infra de GPU.
Armadilhas comuns que anulam o reranker
Chunks longos demais
Um chunk de 4k tokens com uma frase relevante e 3.900 tokens de contexto irrelevante confunde o cross-encoder. O modelo pontua a densidade de relevância, não a presença. Chunks de 300–800 tokens rendem os melhores scores.
Deduplicação faltando
Se seu retrieval devolve 20 versões quase idênticas do mesmo parágrafo (comum quando você indexa versões diferentes do mesmo doc), o reranker vai colocar todas no topo, e o prompt final vai ter zero diversidade. Deduplique por MinHash ou similaridade de embedding antes de rerankear.
Metadados ignorados
Cohere Rerank aceita filtrar/pontuar por rank_fields; BGE aceita você concatenar metadados no início do documento (ex.: "[Título: X] [Data: 2026-06-01] {texto}"). Ignorar isso deixa dinheiro na mesa em domínios onde a data ou o tipo de doc importa tanto quanto o texto.
Sem cache
Queries repetidas (dashboards, autocomplete, prompts padronizados) merecem cache. Uma chave hash(query + top_k_ids) num Redis de 100 MB elimina 30–50% das chamadas em produção típica.
Confiar cegamente no top-1
Reranking melhora a ordem mas não elimina erros. Se sua LLM precisa de resposta 100% correta, injete os top-3 no prompt e deixe o modelo escolher/combinar, não só o top-1. Combine com function calling para o modelo pedir mais contexto quando não estiver confiante.
Perguntas frequentes
Qual é a diferença entre embedding e reranking?
Embedding é um bi-encoder: codifica query e documento separadamente em vetores e mede similaridade por cosseno. É rápido e escalável, mas menos preciso. Reranking usa um cross-encoder que lê query e documento juntos com atenção cruzada, produzindo um score de relevância muito mais fino. Você usa embedding para triagem em milhões de docs, e reranking para reordenar os top-50 antes do prompt final.
Quanto reranking melhora um pipeline RAG?
Em benchmarks públicos como BEIR e MTEB-Rerank, adicionar um reranker sobre embeddings genéricos costuma trazer +12% a +38% em NDCG@10, dependendo do domínio. Em conteúdo técnico e multilíngue o ganho é maior; em FAQs curtas, menor. Sempre meça no seu próprio dataset, sem confiar na média.
Cohere Rerank vs Voyage: qual escolher?
Cohere Rerank 3.5 é melhor para SaaS multilíngue e cobrança previsível ($2 por 1k buscas). Voyage rerank-2.5 é melhor para conteúdo técnico longo em inglês (contexto de 8k tokens, ótimo para docs de código). A qualidade média é comparável; escolha por idioma, preço e tamanho de documento.
Posso usar reranking sem GPU?
Sim. As APIs hospedadas (Cohere, Voyage, Jina) rodam sem infra sua. Se quiser self-hosted em CPU, o BGE reranker base funciona a ~500 ms para 20 docs, aceitável para volumes baixos ou tarefas assíncronas. Para latência interativa, GPU (mesmo uma T4 de US$ 0,10/h) é praticamente obrigatória.
Não, eles atuam em camadas diferentes. Hybrid search aumenta a chance de o documento correto estar no top-50 (recall). Reranking reordena o top-50 para colocar o documento correto em top-5 (precision). Os melhores pipelines usam os dois: hybrid search para recuperar candidatos diversos e reranker para escolher os melhores.
LangGraph, CrewAI e AutoGen dominam o mundo de agentes de IA em 2026. Comparo os três em cargas reais com benchmarks, código executável e as armadilhas de produção que raramente aparecem na documentação oficial.
Compare Mem0, Zep e Letta em 2026 para dar memória de longo prazo aos seus agentes de IA. Arquitetura, custos, latência, código real e um framework de decisão prático.