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: Cohere vs Voyage 2026

Atualizado: 10 de agosto de 2026

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:

  1. 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.
  2. 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.
  3. 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érioCohere Rerank 3.5Voyage rerank-2.5BGE reranker v2-m3
TipoAPI hospedadaAPI hospedadaOpen-source (Apache 2.0)
Contexto por documento4.096 tokens8.000 tokens8.192 tokens
Idiomas oficiais100+ (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 tokensCusto de GPU (~$0,10/h spot)
NDCG@10 médio (BEIR)0,580,570,54
Melhor caso de usoSaaS multi-tenant, poucas queries/sDocs técnicos longos em ENVolume alto, dados sensíveis on-prem
Integração LangChain/LlamaIndexNativaNativaVia 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:

  1. Monte um dataset de 100–500 pares (query, chunk_correto) do seu domínio. Sim, precisa anotar.
  2. Meça Recall@K e NDCG@K antes/depois do reranker para K ∈ {3, 5, 10}.
  3. 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.

Reranking substitui hybrid search (BM25 + vetorial)?

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.

Nikhil Verma
Sobre o Autor Nikhil Verma

AI automation engineer chaining LLMs into workflows that actually work. Bullish on tool use; bearish on prompt theatre.