O Retrieval define o teto de qualidade de qualquer RAG
Em 2026, é raro que trocar o modelo de geração de GPT-4 para Claude Opus 4.7 faça um projeto RAG "parecer de repente mais inteligente". A maioria dos problemas está no Retrieval: ou as informações necessárias não são recuperadas, ou ruído é recuperado e confunde o LLM. Olhando os projetos RAG que a KGA apoiou nos últimos 18 meses, melhorias apenas no Retrieval aumentaram o score de percepção do usuário entre 30% e 60%, enquanto trocar o modelo de LLM resultou em melhoria média de cerca de 8%.
Este artigo organiza as melhores práticas de Retrieval para RAG em 2026 em cinco camadas: (1) busca híbrida, (2) reranker, (3) reescrita de query, (4) estratégia de chunking e (5) métricas de avaliação.
Camada 1: Hybrid Search (BM25 + Dense)
A busca dense sozinha falha frequentemente com números de modelo ("ZX-450B"), siglas ("TLS1.3"), nomes próprios e condições numéricas específicas. O BM25, por outro lado, é fraco com paráfrases semânticas. Fundir os dois com Reciprocal Rank Fusion (RRF) se tornou o padrão do setor.
O RRF é simples: converte o rank de cada resultado de busca para `1 / (k + rank)` e soma os valores (k=60 como padrão). Como não depende da escala dos scores, funciona universalmente na combinação de modelos diferentes.
```python from collections import defaultdict
def rrf_fusion(ranked_lists: list[list[str]], k: int = 60) -> list[tuple[str, float]]: scores = defaultdict(float) for results in ranked_lists: for rank, doc_id in enumerate(results, start=1): scores[doc_id] += 1.0 / (k + rank) return sorted(scores.items(), key=lambda x: -x[1])
bm25_top = bm25_index.search(query, k=50) dense_top = vector_db.search(query_embed, k=50) fused = rrf_fusion([bm25_top, dense_top])[:20] ```
Num projeto de busca jurídica da KGA, BM25 sozinho deu nDCG@10=0,52; dense sozinho, 0,61; com RRF híbrido, chegamos a 0,73. É simples e poderoso.
Camada 2: Reranker (Cohere Rerank-3, Voyage Rerank-2)
Depois de recuperar o top 50 a 200 pela busca híbrida, o padrão de 2026 é um design de dois estágios com um reranker de cross-encoder para um scoring mais preciso. A busca dense usa uma arquitetura bi-encoder que vetoriza query e documento de forma independente, perdendo a interação entre eles. O reranker passa ambos juntos por um Transformer para gerar uma relevância real.
- Cohere Rerank-3 (lançado em setembro de 2025): 100 idiomas, contexto de 128k, USD 2/1k queries
- Voyage Rerank-2: contexto de 32k, top do MTEB Reranking, USD 0,50/1k queries
- Jina Reranker v2: opção mais próxima do OSS; desempenho em japonês ligeiramente inferior ao Cohere
- BGE-Reranker-v2-m3: OSS com licença MIT, primeira escolha para auto-hospedagem
```python import cohere
co = cohere.Client() results = co.rerank( model="rerank-3", query="Requisitos de transferência internacional sob a lei de proteção de dados", documents=[d.text for d in top50], top_n=10, ) reranked = [top50[r.index] for r in results.results] ```
O efeito do reranker é drástico: na média dos projetos da KGA, o nDCG@10 salta de 0,65 para cerca de 0,82. A latência adicional fica entre 200 e 400 ms para top 50, então são necessários designs de resposta assíncrona ou de resposta rápida apenas com o primeiro estágio.
Camada 3: Reescrita de Query (HyDE, Query2Doc, Multi-Query)
As queries dos usuários costumam ser curtas e vagas ("rescisão de contrato", "uso de memória"). A técnica de expandir a query com LLM antes de buscar foi incorporada ao design de Retrieval em 2026.
- HyDE (Hypothetical Document Embeddings): pede ao LLM que escreva um documento de resposta hipotético e usa seu embedding como chave de busca
- Query2Doc: combina a query com o documento hipotético para gerar o embedding (variante do HyDE, mais estável em muitos casos)
- Multi-Query: pede ao LLM que gere de 3 a 5 reformulações da mesma intenção, faz buscas em paralelo e funde com RRF
```python def hyde_search(query: str, vector_db, llm): hypothetical = llm.generate( f"Escreva uma resposta hipotética de 3 frases para a seguinte pergunta: {query}" ) combined = query + " " + hypothetical # tornando Query2Doc embed = embedding_model.encode(combined) return vector_db.search(embed, k=50) ```
O Multi-Query tem o melhor custo-benefício: no RAG de FAQ interno da KGA, o Recall@20 melhorou 12% em relação à busca com query única. O custo é uma chamada a mais ao LLM por query, mas com Claude Haiku ou GPT-4.1-mini fica abaixo de 0,10 centavos.
Camada 4: Estratégia de Chunking
RAGs que operam com divisão simples de 1.000 caracteres estão desatualizados em 2026. A estratégia de chunking define diretamente a qualidade do Retrieval.
- Fixed-size: divisão clássica em N caracteres, com sobreposição de 10% a 20%
- Recursive Character Splitting: divisão recursiva na ordem parágrafo → sentença → palavra. É o padrão do `RecursiveCharacterTextSplitter` do LangChain
- Semantic Chunking: gera embeddings de frases consecutivas e corta nos pontos de queda abrupta de similaridade por cosseno, criando chunks semanticamente coesos
- Late Chunking (Jina 2024/2025): passa o documento longo inteiro pelo modelo de embedding primeiro, obtém embeddings por token e depois os agrega por média para formar os chunks. Como o chunk preserva o contexto circundante, pronomes e referências anafóricas não se perdem
- Hierarchical / Parent-Child: busca nos chunks menores e passa os chunks pais para a geração. Equilibra precisão e quantidade de contexto
Implementação de Late Chunking:
```python from transformers import AutoModel, AutoTokenizer import torch
model = AutoModel.from_pretrained("jinaai/jina-embeddings-v3", trust_remote_code=True) tokenizer = AutoTokenizer.from_pretrained("jinaai/jina-embeddings-v3")
def late_chunking(long_text: str, chunk_boundaries: list[tuple[int, int]]): inputs = tokenizer(long_text, return_tensors="pt", truncation=True, max_length=8192) with torch.no_grad(): token_embeds = model(**inputs).last_hidden_state[0] chunk_embeds = [] for start, end in chunk_boundaries: chunk_embeds.append(token_embeds[start:end].mean(dim=0)) return torch.stack(chunk_embeds) ```
Ao implementar Late Chunking em RAG de contratos na KGA, o Recall@10 em documentos com muitas referências cruzadas — como "conforme definido no Artigo 3" — subiu de 71% para 88%.
Camada 5: Métricas de avaliação e testes offline
Retrieval não pode ser avaliado apenas por "funcionar". Métricas quantitativas e testes de regressão são obrigatórios.
- Recall@k: proporção de documentos corretos encontrados no top k. A métrica mais importante — define o teto do RAG
- nDCG@10 (Normalized Discounted Cumulative Gain): leva em conta a qualidade da ordenação. Padrão de fato em buscas comerciais
- MRR (Mean Reciprocal Rank): média dos inversos do rank do primeiro resultado correto. Próximo da percepção real do usuário
- Hit Rate@k: binário simples — "o resultado correto apareceu no top k?"
O conjunto de avaliação precisa de no mínimo 100 queries, idealmente 500, com pares de query e ID de documento correto em CSV, integrados ao CI como testes de regressão.
```python import numpy as np
def ndcg_at_k(ranked_ids: list[str], relevance: dict[str, int], k: int = 10) -> float: gains = [relevance.get(doc_id, 0) for doc_id in ranked_ids[:k]] dcg = sum((2 g - 1) / np.log2(idx + 2) for idx, g in enumerate(gains)) ideal_gains = sorted(relevance.values(), reverse=True)[:k] idcg = sum((2 g - 1) / np.log2(idx + 2) for idx, g in enumerate(ideal_gains)) return dcg / idcg if idcg > 0 else 0.0 ```
Frameworks como `RetrieverEvaluator` do LlamaIndex, RAGAS e Trulens já padronizam esses cálculos. Em vez de implementar do zero, o padrão de 2026 é começar com o RAGAS.
Arquitetura de referência para produção
A configuração padrão de RAG em produção que a KGA propõe em 2026:
- Ingestão: documento → Late Chunking (Jina v3) → armazenamento parent/child
- Indexação: pgvector ou Qdrant com dense e sparse armazenados juntos
- Query: Multi-Query (LLM gera 3 variações)
- Primeiro estágio: Hybrid BM25 + Dense → fusão RRF para top 100
- Segundo estágio: Cohere Rerank-3 comprimindo para top 10
- Geração: top 10 passado ao Claude Opus 4.7 para a resposta final
- Avaliação: testes de regressão com 500 queries rodando semanalmente no CI, bloqueando builds quando nDCG@10 / MRR / Recall@20 caem abaixo do limiar
Com essa arquitetura implementada com rigor, a experiência de "o RAG ficou mais inteligente sem trocar o LLM" de fato acontece. O Retrieval é o coração do RAG — e a camada onde o investimento do projeto deve ser prioritário em 2026.