~ / tutoriais /reranker-rag $ _

Reranker: o passo que faz seu RAG parar de devolver lixo

Lucas Souza Lucas Souza 9 min de leitura Tutoriais
Reranker: o passo que faz seu RAG parar de devolver lixo

Seu RAG traz 20 trechos "parecidos" e o modelo responde com o errado. A culpa não é da busca. É a falta de um reranker.

Quem montou um RAG na raça conhece a cena: a busca vetorial devolve os 20 chunks mais "próximos" da pergunta, você joga tudo no contexto, e o modelo escolhe justamente o trecho que parecia certo mas não era. Parecido não é relevante. E é exatamente nessa brecha que o reranker entra: um segundo estágio que reordena os candidatos por relevância real antes de mandar pro LLM.

Neste tutorial você vai entender como um reranker funciona por dentro, ver código rodando com cross-encoder local e com a API da Cohere, e — o mais importante — decidir quando vale o cross-encoder e quando busca híbrida já resolve. Sem hype. É engenharia de recuperação, o degrau que separa demo de produto.

TL;DR

  • O que é: segundo estágio de recuperação que pega os top-N candidatos da busca e os reordena por relevância real query↔documento.
  • Stack/Modelos: cross-encoder local (sentence-transformers, BAAI/bge-reranker) ou API gerenciada (Cohere rerank-v3.5).
  • Custo/Acesso: open-source roda na sua máquina (controle e custo previsível); Cohere é pago por chamada e te dá ganho num fim de tarde de integração.
  • Quando importa: quando seu recall já está bom mas a resposta ainda erra — ordem ruim, não falta de candidato.
  • Leitura base: Guia de RAG para devs backend: do zero ao pgvector em Laravel.

O contexto: parecido não é relevante

A busca vetorial funciona com bi-encoder: ela transforma cada chunk em um vetor uma vez, na ingestão, e na hora da query transforma a pergunta em outro vetor e compara por similaridade de cosseno. Rápido, barato, escala pra milhões de documentos. É o que faz busca semântica ser viável.

O problema é o que essa similaridade mede. O bi-encoder codifica query e documento separadamente — os dois nunca se olham. O vetor do documento foi calculado sem saber qual pergunta ia chegar. Resultado: ele acerta o tema, mas não a intenção. "Como cancelar assinatura" e "política de cancelamento de assinatura" ficam coladas no espaço vetorial, mesmo que só uma responda a pergunta do usuário.

É por isso que seu RAG devolve lixo plausível. Os 20 chunks são todos sobre o assunto certo. Mas o chunk que realmente responde pode estar na posição 14 — e o modelo, afogado em contexto parecido, ancora no trecho errado que veio em primeiro.

O reranker resolve isso virando a chave de arquitetura: bi-encoder é uma rede que aprende a comparar vetores; o cross-encoder do reranker concatena query e documento numa única sequência e passa os dois juntos pelo transformer. Ele a pergunta e o trecho lado a lado e cospe um único score de relevância. Mais caro, muito mais preciso. Esse é o padrão retrieve-then-rerank que praticamente todo sistema de busca sério usa hoje.

A conta de eficiência fecha assim: cross-encoder é O(n) por query — uma passada completa do transformer pra cada par (query, documento). Rodar isso no corpus inteiro é inviável. Rodar nos 50 candidatos que a busca vetorial já filtrou é trivial. Você recupera barato e reordena com precisão.

Pré-requisitos

  • [ ] Python 3.10+ com um RAG que já faz busca vetorial (top-N saindo).
  • [ ] pip install sentence-transformers para o cross-encoder local.
  • [ ] Chave da Cohere (COHERE_API_KEY) se for testar a versão gerenciada.
  • [ ] Entender o básico de embeddings e busca semântica — se ainda não tem, comece pelo guia de RAG em Laravel.

A regra de ouro antes de qualquer código: não rerankeie busca ruim. O reranker só reordena o que você já recuperou. Se o chunk certo não está nos top-50, nenhum reranker vai inventar ele. Recall vem antes de precisão — sempre.

Mão na massa

Passo 1: cross-encoder local com sentence-transformers

O caminho com mais controle. Você pega os candidatos da busca, passa cada par (query, chunk) pelo cross-encoder e fica com os melhores.

from sentence_transformers import CrossEncoder

# modelo de reranking open-source, roda local
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")

query = "como cancelar minha assinatura?"

# os 20 candidatos que a busca vetorial já trouxe (parecidos, não rankeados)
candidatos = [
    "Para cancelar, acesse Configurações > Assinatura > Cancelar.",
    "Nossa política de cobrança renova a assinatura automaticamente.",
    "Você pode atualizar o cartão na aba de pagamento.",
    # ... + 17 chunks
]

# o cross-encoder pontua cada par query<->documento
scores = reranker.predict([(query, doc) for doc in candidatos])

# reordena por score e fica com o top-3 que vai pro LLM
ranked = sorted(zip(candidatos, scores), key=lambda x: x[1], reverse=True)
for doc, score in ranked[:3]:
    print(f"{score:.3f}  {doc}")

O trecho que ensina a cancelar sobe pro topo mesmo que a busca vetorial o tivesse jogado pro meio da lista. O LLM recebe 3 chunks de verdade relevantes em vez de 20 parecidos.

Passo 2: a mesma lógica com a API da Cohere

Se você não quer hospedar modelo, a Cohere entrega o ganho com uma chamada. Mesmo padrão, zero infra.

import cohere

co = cohere.ClientV2()  # lê COHERE_API_KEY do ambiente

resp = co.rerank(
    model="rerank-v3.5",
    query="como cancelar minha assinatura?",
    documents=candidatos,
    top_n=3,
)

for r in resp.results:
    print(f"{r.relevance_score:.3f}  {candidatos[r.index]}")

O top_n corta a lista pra você; o relevance_score vem normalizado. Nos benchmarks da própria Cohere, o rerank-v3.5 melhora o nDCG sobre busca por embedding pura e sobre busca híbrida em datasets de finanças, e-commerce e gestão — até 25% de ganho em tarefas difíceis de recuperação. E há estudo apontando +33–40% de acurácia no RAG por apenas ~120ms de latência extra com cross-encoder reranking.

Passo 3: o número que importa — quantos recuperar, quantos rerankear

O erro mais comum é rerankear de menos ou de mais. O consenso prático: recupere 50–100, rerankeie pro top-5 a top-10. Recuperar pouco mata o recall (o reranker não vê o chunk certo). Recuperar demais joga latência e custo fora sem ganho. Cross-encoder local roda os 50 em dezenas de milissegundos; a API da Cohere fica na casa de 150–400ms mais rede. Meça com o seu dataset — recall@50 antes do reranker, recall@5 depois. Se o recall@50 já está baixo, o problema é a busca, não a ordenação.

Reranker cross-encoder vs busca híbrida: quando cada um vale

Aqui mora a decisão de arquitetura — e onde muita gente erra a ordem.

Busca híbrida (BM25 por palavra-chave + vetorial, fundidas com Reciprocal Rank Fusion) ataca o recall. Ela garante que o chunk certo apareça na lista — captura tanto o sentido (vetor) quanto o termo exato (BM25, ótimo pra código, SKU, nome próprio, número de erro). Custo de latência: quase zero.

Reranker cross-encoder ataca a precisão. Ele assume que o chunk certo já está na lista e o empurra pro topo. Custo: a passada do transformer por candidato.

A ordem certa não é "um ou outro", é híbrida primeiro, reranker depois:

  1. Comece com busca híbrida. É barata e resolve a maior parte dos casos de "a resposta nem estava no contexto".
  2. Meça recall@50. Se está baixo (< ~90%), conserte a recuperação — chunking, embeddings, BM25 — antes de pensar em reranker.
  3. Com recall sólido e a resposta ainda errando por ordem ruim, aí sim entra o reranker.

Quick-win honesto: se você está partindo do zero e quer o maior salto de qualidade com o menor esforço, busca híbrida + um reranker gerenciado por cima é o combo que entrega num fim de tarde. Não precisa de mestrado nem de GPU. Precisa de arquitetura na ordem certa.

Limitações e pontos de atenção

  • Reranker não cria contexto. Se o chunk certo não foi recuperado, o reranker não salva. Ele reordena, não inventa. Recall ruim continua ruim.
  • Latência soma. Cada candidato é uma inferência. 100 candidatos por um cross-encoder pesado podem estourar seu p95. Ajuste o N e considere modelo menor (FlashRank, bge-reranker-base) se latência é crítica.
  • Custo por chamada. API gerenciada cobra por documento rerankeado. Em alto volume, self-hosted fica mais previsível — é o trade-off clássico de controle vs. conveniência.
  • Chunking ainda manda. Reranker pontua o chunk que você deu. Chunk gigante e desfocado recebe score ruim mesmo sendo relevante. Lixo entra, lixo é rerankeado.
  • Avalie, não confie no feeling. Sem recall@k e nDCG antes/depois, você não sabe se o reranker ajudou ou só adicionou latência. Eval é o que separa achismo de engenharia.

FAQ rápido

Preciso de reranker se já uso busca híbrida? Depende do que está quebrando. Se a resposta certa nem aparece no contexto, é recall — conserta a busca. Se ela aparece mas o modelo ancora no trecho errado, é precisão — aí o reranker resolve. Meça antes de decidir.

Cross-encoder local ou API da Cohere? API pra validar rápido e em baixo volume — ganho num fim de tarde, zero infra. Self-hosted (bge-reranker, FlashRank) pra volume alto, dados sensíveis ou custo previsível. Comece pela API, migre quando a conta justificar.

Quantos candidatos devo rerankear? Recupere 50–100, rerankeie pro top-5 ou top-10. Menos que isso arrisca o recall; muito mais é latência jogada fora. Calibre com o seu próprio dataset.

Reranker funciona em português? Sim. Modelos multilíngues como bge-reranker-v2-m3 e o rerank-v3.5 da Cohere cobrem 100+ idiomas. Para conteúdo só em PT-BR, valide com um dataset seu — score de relevância varia por domínio.

Conclusão

Recuperação boa é dois movimentos, não um. Busca híbrida garante que a resposta esteja na mesa (recall). O reranker garante que ela chegue no topo do prato do modelo (precisão). Vector search sozinho te dá "parecido" — e parecido é o que faz seu RAG soar confiante e responder errado.

O próximo passo é tratar recuperação como sistema: chunking, busca híbrida, reranker e eval medindo cada camada. É exatamente esse tipo de decisão de arquitetura — qual peça entra, em que ordem, com qual trade-off — que destrinchamos com código na mesa no Workshop Arquitetando Soluções de IA, focado em arquitetar soluções reais de software com agents de IA. Se você quer ver o pipeline inteiro além do reranker, o RAG não é só vector search mostra busca semântica, SQL e reranker convivendo como tools no mesmo agente.

Recupera barato. Rerankeia com precisão. Para de mandar lixo pro modelo.

Lucas Souza
Lucas Souza

{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.

Você também pode gostar

Cross-encoder reranker: o componente que mais eleva qualidade do seu agente por dólar
Tutoriais

Cross-encoder reranker: o componente que mais eleva qualidade do seu agente por dólar

Retrieval traz 100 candidatos, reranker escolhe os 10 certos. Entenda o trade-off latência x precisão, quando rerankar 50 vs. 200 documentos e por que cross-encoder é o investimento de melhor ROI antes de trocar para um LLM mais caro.

· 10 min
RAG do zero: chunking, embeddings e busca que funciona
Tutoriais

RAG do zero: chunking, embeddings e busca que funciona

RAG não é mágica: é quebrar texto, virar vetor e buscar bem. O passo a passo de um RAG do zero — chunking recursive com overlap, embeddings com text-embedding-3-small e busca por similaridade no Postgres com pgvector e índice HNSW. Errar o chunking é onde 80% dos RAGs nascem ruins.

· 10 min
Top-10 da busca não é top-10 do usuário: por que a SERP bruta sabota seu agente
Tutoriais

Top-10 da busca não é top-10 do usuário: por que a SERP bruta sabota seu agente

A primeira página do Google não foi feita pra alimentar agente de IA. Ela foi feita pra ranquear sites. E essas duas coisas, em 2026, não são mais a mesma coisa. Plugar a SERP bruta no seu agente é amplificar SEO spam, MFA e conteúdo gerado por IA na escala. Veja por que o top-10 da busca não é o top-10 do usuário e como montar um pipeline de filtros + rerank que devolve confiança ao seu agente.

· 7 min
RAG não é só vector search: combinando busca semântica, SQL e tools no mesmo agente
Tutoriais

RAG não é só vector search: combinando busca semântica, SQL e tools no mesmo agente

Vector-only, hybrid (BM25 + vetor + RRF) e o stack completo com SQL e reranker como tools separadas: comparação prática com benchmarks reais e código de produção.

· 11 min

VirguIA

beer & code assistant

conectando…

Não foi possível iniciar o chat agora.

tocando