o problema
RAG resolveu o problema de escala e criou outro. Para caber numa base grande, o documento é picado em chunks de algumas centenas de tokens, cada chunk vira um vetor, e a busca acontece por similaridade semântica. O corte é cego: ele não sabe que a frase “a receita da empresa cresceu 3% sobre o trimestre anterior” só significa alguma coisa se você souber que o documento é um filing da ACME sobre o segundo trimestre de 2023. Isolado, esse chunk não casa com a pergunta “qual foi o crescimento de receita da ACME no Q2 de 2023” — não porque o dado não está lá, mas porque o texto indexado não carrega o referente.
O segundo problema é mais antigo. Embedding captura relação semântica e erra match literal. Quem procura “error code TS-999” quer aquela string, e o modelo de embedding devolve conteúdo sobre códigos de erro em geral. A resposta usual é rodar BM25 junto — lexical, com TF-IDF, saturação de frequência e normalização por tamanho de documento — e fundir os rankings. Só que BM25 indexa os mesmos chunks decapitados. Os dois canais herdam o mesmo defeito.
a ideia
Antes de indexar, pedir a um modelo que olhe o documento inteiro e escreva uma frase curta situando aquele chunk dentro dele. Esse texto é prepended ao chunk e vai junto para os dois índices: o vetorial e o BM25. O chunk do exemplo deixa de ser uma frase solta e vira “este trecho é de um filing da ACME sobre o Q2 de 2023; a receita do trimestre anterior foi de US$ 314 milhões” seguido do texto original.
Não é resumo de documento colado em todo chunk — os autores testaram isso e viram ganho muito limitado. O contexto é específico do chunk: ele responde “o que falta aqui para esta passagem se sustentar sozinha”, e a resposta é diferente para cada pedaço do mesmo documento.
como funciona
O pipeline é de pré-processamento. Para cada chunk, um prompt manda o documento inteiro entre tags, o chunk entre tags, e pede contexto sucinto para melhorar a recuperação, com a instrução de responder só o contexto e nada mais. O modelo usado foi o Claude 3 Haiku e a saída fica em 50 a 100 tokens. Esse texto é concatenado à frente do chunk, e só então o chunk é embeddado e entra no índice BM25.
O custo poderia inviabilizar tudo: reenviar um documento de 8.000 tokens para cada um dos seus chunks de 800 tokens é pagar dez vezes pelo mesmo documento. É onde entra prompt caching — o documento vai para o cache uma vez e os chunks seguintes referenciam o conteúdo cacheado. Com essas premissas, a conta fecha em US$ 1,02 por milhão de tokens de documento, custo único.
Em runtime nada muda em relação a um RAG híbrido comum: BM25 traz os top chunks por match exato, os embeddings trazem os top por similaridade, rank fusion junta e deduplica, e os top-20 vão para o prompt. Na configuração com reranking, a recuperação inicial pega 150 chunks, um reranker pontua todos em paralelo contra a query, e os 20 melhores seguem.
A métrica é 1 menos recall@20 — o percentual de documentos relevantes que não aparecem entre os 20 chunks recuperados. Com o melhor embedding testado (Gemini Text 004), a média entre os domínios avaliados foi: 5,7% de falha na linha de base, 3,7% com contextual embeddings, 2,9% somando contextual BM25, e 1,9% acrescentando o reranker da Cohere.
o que isso custou
O ganho de 67% é relativo sobre uma base que já acertava 94,3% das vezes: em valor absoluto são 3,8 pontos percentuais. Vale a conta em domínio onde a falha é cara, e o post é honesto ao ancorar tudo em números absolutos.
O reranking adiciona uma etapa em runtime e, portanto, latência e custo, com trade-off explícito entre reranquear mais chunks e responder rápido. O reranker da Voyage não foi testado. Os autores também não escondem que o resultado depende de decisões que continuam sendo suas: tamanho do chunk, fronteira, overlap, e qual modelo de embedding — a técnica ajudou em todas as combinações avaliadas, mas alguns modelos ganham mais que outros. Passar 20 chunks bateu 10 e 5, com a ressalva de que mais informação também distrai o modelo, então o número ótimo é empírico.
E há o limite de cima: se a base tem menos de 200.000 tokens, mais ou menos 500 páginas, a recomendação é não montar RAG nenhum e colocar tudo no prompt.
onde isso aparece hoje
O post é um dos textos que consolidaram a receita padrão de recuperação: busca híbrida em vez de só vetorial, contexto gerado por llm no momento da indexação, e reranker antes de entregar ao gerador. A observação de que os ganhos empilham é o que ficou — cada peça sozinha rende pouco, o conjunto rende.
O outro efeito é sobre prompt caching, que aqui deixa de ser otimização de latência e vira condição de viabilidade econômica: sem cache, contextualizar uma base grande custaria uma ordem de grandeza a mais. Chamar o modelo milhões de vezes em pré-processamento passou a ser uma linha de orçamento defensável.