Recuperação de informação é decisão de arquitetura, não funcionalidade

·13 min de leitura

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ãoPor que reverter dóiO que fazer cedo
Modelo de embeddingTodos os vetores precisam ser recalculados, e pontuações de modelos diferentes não se comparamGuardar o texto bruto e os IDs dos trechos, para que reindexar seja uma tarefa e não um projeto
Identidade do trechoCitações, feedback de usuários e rótulos de teste apontam para IDs de trechosDerivar os IDs da fonte e da posição, e manter um mapeamento quando o corte mudar
Esquema de metadadosFiltros por fonte, versão, data, idioma e permissão não podem ser acrescentados a vetores que não os têmDefinir os campos antes da primeira ingestão
Verificação de permissãoUm filtro aplicado depois do corte top-k remove resultados e deixa buracos, ou vazaFiltrar dentro da consulta de recuperação, pela identidade de quem pergunta
Caminho de exclusãoPedidos de proteção de dados (LGPD, GDPR) alcançam também os índices derivadosRegistrar de qual registro cada trecho veio
Conjunto de avaliaçãoSem ele, toda mudança é um palpiteMontá-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

  1. 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.
  2. Anthropic (19 de setembro de 2024). Introducing Contextual Retrieval. anthropic.com/news/contextual-retrieval.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.