Recuperação de informação é decisão de arquitetura, não funcionalidade
Em setembro de 2024, a Anthropic publicou um texto curto sobre uma técnica que chamou de contextual retrieval, e o dado mais interessante dele era uma tabela de taxas de falha. Em bases de código, ficção, artigos do arXiv e artigos científicos, uma busca por embeddings simples deixava de colocar o trecho relevante entre os 20 primeiros resultados em 5,7% dos casos. Quando cada trecho passou a receber uma frase de contexto antes de ser indexado, quando um índice de palavras-chave foi posto ao lado dos embeddings e os candidatos foram reordenados, a taxa de falha caiu para 1,9%. É uma redução de 67%. O modelo que escrevia as respostas finais foi o mesmo o tempo todo.
Tomo essa tabela como ponto de partida de um argumento. Um sistema de geração aumentada por recuperação (RAG) é um banco de dados que usa um modelo de linguagem como interface de consulta, e a metade que mais decide a qualidade é a do banco de dados. As escolhas que fixam o teto de um sistema (como os documentos são cortados, como são indexados, quem pode ver cada pedaço, como alguém vai saber se o sistema acerta) merecem a revisão que uma mudança de esquema receberia. Custam pouco no primeiro dia e muito no nonagésimo, e um projeto que escolhe o banco vetorial numa tarde e passa um mês lapidando prompts tomou todas elas por omissão.
O teto é definido antes de o modelo ler qualquer palavra
O termo vem de Patrick Lewis e colegas do Facebook AI Research, que em 2020 combinaram um gerador sequência-para-sequência com um índice denso da Wikipédia e batizaram o conjunto de retrieval-augmented generation. O enquadramento deles era o de memória: os pesos são a memória paramétrica, o índice é a memória não paramétrica, e a segunda pode ser inspecionada e atualizada sem retreinar a primeira. O enquadramento continua valendo e explica por que a metade de recuperação merece a atenção que se dá a uma camada de armazenamento.
Scott Barnett e coautores chegaram ao mesmo ponto pelo lado das falhas. O artigo deles, apresentado em 2024 na Conferência Internacional de Engenharia de IA, em Lisboa, partiu de três estudos de caso (pesquisa, educação, biomedicina) e listou sete lugares onde um sistema RAG quebra. Os três primeiros não envolvem o gerador. O corpus pode simplesmente não conter a resposta, e nesse caso o sistema tende a fabricar uma resposta plausível e errada em vez de admitir isso. A resposta pode existir, mas ficar abaixo do ponto de corte e nunca ser repassada. Ou pode ser recuperada e descartada na hora de juntar os resultados para caber no prompt. Só depois disso começam as falhas conhecidas do modelo: a resposta está no contexto e não é extraída, o formato pedido é ignorado, o nível de detalhe vem errado, a resposta sai incompleta.
Para toda pergunta cuja resposta está num único trecho, a conta é simples. Se o trecho certo chega ao contexto em 94,3% das perguntas, que é o que a linha de base da Anthropic implica, nenhuma escolha de gerador levará a acurácia além de 94,3% nessas perguntas. O gerador só pode perder terreno a partir daí. Levar a recuperação a 98,1% eleva o teto em quase quatro pontos, e um teto elevado desse jeito fica disponível, de graça, para toda troca futura de modelo.
Dividir documentos em trechos é afirmar algo sobre eles
A explicação da Anthropic para o funcionamento da técnica se apoia em um exemplo. Pegue o trecho "A receita da empresa cresceu 3% em relação ao trimestre anterior." Qual empresa? Qual trimestre? Sozinha, essa frase fica perto de milhares de outras iguais no espaço de embeddings. A correção foi pedir a um modelo que escrevesse uma ou duas frases situando cada trecho no documento de origem ("Este trecho vem de um documento da SEC sobre o desempenho da ACME corp no segundo trimestre de 2023; a receita do trimestre anterior foi de US$ 314 milhões") e anexá-las antes tanto do embedding quanto da indexação por palavras-chave. Sob as premissas do texto (trechos de 800 tokens, documentos de 8.000 tokens, cache de prompt), o custo único ficou em cerca de US$ 1,02 por milhão de tokens de documento. Um corpus de 100 milhões de tokens custaria uns US$ 102 para ser processado.
É uma pechincha, e é também um lembrete de que o trecho é uma decisão de modelagem. Cortar um documento a cada 500 tokens afirma que o sentido se distribui de modo uniforme ao longo da página, o que quase nunca é verdade. Um contrato enuncia a regra na cláusula 7 e a exceção na cláusula 12. Um runbook diz "repita o passo 3 com o nó secundário". Tabelas atravessam quebras de página, e uma entrada de changelog não significa nada sem o título de versão três telas acima. Cada um desses casos produz um trecho correto, recuperável e enganoso.
Há um segundo motivo para os limites dos trechos importarem, que não tem relação com busca. O trecho também é a evidência que o usuário enxerga. O que o sistema cita é a unidade que você cortou, e um limite traçado no meio de uma frase vira defeito visível do produto. Um chunker escrito uma vez, como script de pré-processamento, produz esse defeito em silêncio. Um cliente diz que o trecho citado "não diz isso", e o cliente tem razão, porque a frase que diz isso começa no trecho anterior.
Embeddings borram justamente aquilo que as pessoas procuram
Embeddings densos são treinados para que paráfrases fiquem próximas. É a propriedade certa para uma pergunta como "como faço para ter meu dinheiro de volta" e a errada para "erro E-4021", "cláusula 14.3(b)", o nome de um medicamento, um código de peça ou uma norma citada pelo número. São tokens cujo valor inteiro está em serem exatos.
O benchmark BEIR, publicado no NeurIPS em 2021 por Nandan Thakur e colegas, testou modelos de recuperação em 18 conjuntos de dados nos quais eles não tinham sido treinados. O método lexical BM25 se mostrou uma linha de base difícil de superar fora do domínio. Modelos de reordenação e de interação tardia tiveram a melhor média, a um custo computacional bem maior. Os modelos de embedding melhoraram muito desde 2021, mas o padrão reaparece nos números da Anthropic: embeddings contextuais sozinhos reduziram as falhas em 35%, e acrescentar um índice BM25 contextual levou a redução a 49%. O índice lexical valeu mais quatorze pontos de redução.
A forma usual de combinar os dois rankings é a fusão de ranks recíprocos (reciprocal rank fusion), proposta por Gordon Cormack, Charles Clarke e Stefan Büttcher em 2009. Cada documento recebe 1/(k + posição) de cada lista em que aparece, com k fixado por convenção em 60, e as pontuações são somadas. Suponha que o documento A seja o primeiro na lista de palavras-chave e o sétimo na de embeddings, enquanto o documento B é o segundo nas duas. A soma 1/61 + 1/67 dá cerca de 0,0313 para A. B recebe 2/62, cerca de 0,0323. B vence sem nunca ter sido o primeiro em lugar nenhum. O método premia a concordância entre dois ordenadores imperfeitos, o que faz sentido quando não se sabe qual deles erra em determinada consulta. Também dispensa dados de treino e calibração de pontuações, e o Elasticsearch e o Azure AI Search oferecem a técnica de fábrica para juntar resultados de palavras-chave e de vetores.
Reordenar custa latência
A última etapa do pipeline da Anthropic buscava 150 candidatos, passava todos por um modelo de reordenação e ficava com os 20 melhores. Nos testes com 5, 10 e 20 trechos no contexto final, 20 foi o que funcionou melhor. Um reordenador costuma ser um cross-encoder que lê a consulta e um candidato juntos, então o custo cresce com o número de candidatos, e cada chamada soma tempo até o usuário ver o primeiro token.
Reordenar, portanto, é uma linha de orçamento. Um job em lote que resume balanços durante a madrugada aguenta 150 candidatos. Um chat de suporte com meta de dois segundos provavelmente não aguenta, e talvez se saia melhor com 30 candidatos e um reordenador menor. O que uma equipe não deve fazer é incluir a etapa porque um post de blog mandou, ou deixá-la de fora porque ninguém mediu. Os dois erros nascem do mesmo lugar: a etapa é tratada como um recurso que se liga e desliga, e não como um componente com custo e efeito mensurável sobre a revocação.
A ordem e a quantidade dentro do contexto final também contam. Nelson Liu e colegas mostraram, no artigo "Lost in the Middle", que a acurácia em perguntas sobre vários documentos segue um U: é mais alta quando o trecho relevante está no começo ou no fim do contexto, e mais baixa quando está enterrado no meio, inclusive em modelos feitos para entradas longas. Isso dá trabalho de verdade à etapa de montagem do contexto. Colocar as melhores evidências nas pontas e parar no número de trechos que os dados indicam ser útil são parâmetros a ajustar contra um conjunto de testes. Encher o prompt com alguns trechos "só por garantia" não é proteção gratuita.
Uma janela maior não aposenta o índice
A objeção mais forte é que nada disso vai importar por muito tempo. As janelas de contexto já chegam a um milhão de tokens, e a arquitetura mais simples de todas é colar o corpus no prompt.
Para um corpus pequeno, a objeção está certa. O texto da Anthropic diz isso: se a base de conhecimento tem menos de 200.000 tokens, cerca de 500 páginas, ponha tudo no prompt e dispense a recuperação. Com cache de prompt, sai mais barato e muito mais simples do que um pipeline, e eu começaria assim com qualquer corpus estável desse tamanho.
Passando desse tamanho, os números viram contra a ideia. Tome um preço ilustrativo de US$ 3 por milhão de tokens de entrada (confira a sua tabela de preços; é só para mostrar a forma da conta). Um prompt de 500.000 tokens custa US$ 1,50 por consulta. Com 10.000 consultas por dia, são US$ 15.000 por dia. Um pipeline de recuperação que envia 20 trechos de 800 tokens, 16.000 tokens ao todo, custa cerca de US$ 0,048 por consulta, ou US$ 480 por dia, mais ou menos um trigésimo. Fazer cache do prefixo estático com o desconto de até 90% citado pela Anthropic leva a opção do prompt longo a uns US$ 1.500 por dia, o que reduz a diferença para cerca de três vezes sem eliminá-la. A latência também cresce com o tamanho do prompt, e os resultados de Liu sugerem que os tokens extras não são todos aproveitados com a mesma qualidade.
O outro problema são as permissões. Um corpus que todos os usuários podem ler cabe em um prompt compartilhado. A maioria dos corpora corporativos não é assim: a pasta de RH, a sala de dados de uma operação e a wiki de engenharia têm leitores diferentes. Pôr tudo na janela para um usuário que pode ver só uma fração entrega o controle de acesso à boa educação do modelo. Uma camada de recuperação pode filtrar por permissão antes de qualquer coisa chegar ao prompt, e esse é o único arranjo que um auditor aceita.
As decisões que não se desfazem barato
Algumas escolhas de um sistema RAG podem ser revistas numa tarde: o template do prompt, o número de trechos, o reordenador. Outras tocam o corpus inteiro ou o produto inteiro quando mudam. A tabela lista as que eu resolveria de propósito, cedo.
| Decisão | Por que reverter dói | O que fazer cedo |
|---|---|---|
| Modelo de embedding | Todos os vetores precisam ser recalculados, e pontuações de modelos diferentes não se comparam | Guardar o texto bruto e os IDs dos trechos, para que reindexar seja uma tarefa e não um projeto |
| Identidade do trecho | Citações, feedback de usuários e rótulos de teste apontam para IDs de trechos | Derivar os IDs da fonte e da posição, e manter um mapeamento quando o corte mudar |
| Esquema de metadados | Filtros por fonte, versão, data, idioma e permissão não podem ser acrescentados a vetores que não os têm | Definir os campos antes da primeira ingestão |
| Verificação de permissão | Um filtro aplicado depois do corte top-k remove resultados e deixa buracos, ou vaza | Filtrar dentro da consulta de recuperação, pela identidade de quem pergunta |
| Caminho de exclusão | Pedidos de proteção de dados (LGPD, GDPR) alcançam também os índices derivados | Registrar de qual registro cada trecho veio |
| Conjunto de avaliação | Sem ele, toda mudança é um palpite | Montá-lo antes de escolher o banco vetorial |
A última linha é a que torna testáveis todas as outras.
Evidência antes da infraestrutura
Um bom conjunto de avaliação para recuperação é modesto em tamanho. De cem a duzentas perguntas reais, cada uma rotulada com o trecho ou os trechos que a respondem, bastam para calcular a revocação em k, a fração das perguntas para as quais um trecho correto aparece entre os k primeiros resultados. Inclua algumas perguntas que o corpus não consegue responder, rotuladas como tal, para que o primeiro ponto de falha também ganhe um número. Avalie as respostas finais separadamente. Manter os dois números separados é o que indica qual metade do sistema consertar, e isso se encaixa na lista de Barnett: os três primeiros pontos de falha aparecem no número de recuperação e nas perguntas sem resposta, os quatro últimos na diferença entre esse número e a acurácia das respostas.
Se a revocação em 20 nas suas próprias perguntas é de 85%, lapidar o prompt é ajustar a parte do sistema que não está falhando. Se a revocação é de 98% e as respostas continuam erradas, vale o oposto: um formato de trecho melhor ou um gerador mais forte é o que deve ser examinado. Nenhuma das duas conclusões está ao alcance de uma equipe sem perguntas rotuladas.
A primeira entrega de um projeto RAG, então, é uma planilha e um script. A planilha guarda as perguntas e os trechos que as respondem. O script imprime a revocação em 5, 10 e 20 para o pipeline que estiver rodando no momento. A escolha do banco vetorial vem depois disso, e será uma decisão menor do que parecia.
Fontes
- Lewis, P., Perez, E., Piktus, A., et al. (2020). Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. Advances in Neural Information Processing Systems 33. arXiv:2005.11401.
- Anthropic (19 de setembro de 2024). Introducing Contextual Retrieval. anthropic.com/news/contextual-retrieval.
- Barnett, S., Kurniawan, S., Thudumu, S., Brannelly, Z., Abdelrazek, M. (2024). Seven Failure Points When Engineering a Retrieval Augmented Generation System. 3rd International Conference on AI Engineering (CAIN), Lisboa. arXiv:2401.05856.
- Thakur, N., Reimers, N., Rücklé, A., Srivastava, A., Gurevych, I. (2021). BEIR: A Heterogeneous Benchmark for Zero-shot Evaluation of Information Retrieval Models. NeurIPS 2021, Datasets and Benchmarks Track. arXiv:2104.08663.
- Cormack, G. V., Clarke, C. L. A., Büttcher, S. (2009). Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods. Proceedings of SIGIR 2009.
- Liu, N. F., Lin, K., Hewitt, J., et al. (2024). Lost in the Middle: How Language Models Use Long Contexts. Transactions of the Association for Computational Linguistics. arXiv:2307.03172.
- Elastic, Reciprocal rank fusion (RRF), documentação de referência; Microsoft Learn, Relevance scoring in hybrid search using Reciprocal Rank Fusion (Azure AI Search). Documentação de produto.