A maioria das equipes de engenharia esbarra no mesmo obstáculo com a geração aumentada por recuperação (RAG). Elas seguem o manual de tutoriais: dividem documentos em blocos (chunks) fixos de quinhentos e doze ou mil e vinte e quatro tokens, passam por um único modelo de embedding e chamam um banco de dados vetorial com uma busca top-k simples. Em uma apresentação de slides, isso parece sólido. Em produção, isso desmorona.

Blocos fixos não se importam com o conteúdo. Eles dividirão alegremente um contrato jurídico no meio de uma frase, deixando cláusulas de responsabilidade penduradas em duas partes de texto não relacionadas. Eles despejarão a descrição de um endpoint de API inteiro em um bloco inflado, tão grande que o parâmetro específico sobre o qual seu usuário perguntou será afogado no ruído. E quando a recuperação é lenta, cada milissegundo de latência impacta diretamente a experiência do usuário. Aprendemos isso da maneira mais difícil. Então, destruímos nossa camada de recuperação e a reconstruímos. Nosso recall em 10 saltou de setenta e oito por cento para noventa e cinco por cento. A latência não aumentou. Ela despencou.

O Problema do RAG de "Copiar e Colar"

A stack de RAG padrão tornou-se uma espécie de configuração padrão. Blocos pequenos, um modelo de embedding, busca vetorial, pronto. Essa abordagem sobrevive a uma demonstração porque demos usam perguntas limpas e documentos organizados. Dados de produção nunca são organizados.

Documentos jurídicos têm estrutura hierárquica. Seções contêm subseções. Subseções contêm cláusulas. Se você cortá-los com um contador de tokens rudimentar, destruirá as próprias relações sobre as quais o modelo precisa raciocinar. A documentação de API também tem estrutura, mas é diferente. Uma assinatura de função, seus parâmetros, seu valor de retorno e um exemplo de uso formam uma unidade lógica. Force isso em uma janela de tokens fixa e você acabará truncando o exemplo ou preenchendo o bloco com funções não relacionadas. Tickets de suporte são bagunçados, conversacionais e cheios de mudanças repentinas de tópico. Wikis são extensas e possuem referências cruzadas. Uma única estratégia de chunking não pode atender a todos eles, mas as equipes rotineiramente implementam exatamente isso. Nós paramos de fingir que era possível.

Chunking Estratégico: Combine o Método ao Material

Mudamos para o chunking consciente do conteúdo. Para documentos jurídicos, usamos chunking recursivo que respeita a hierarquia do documento. Isso mantém as cláusulas intactas e preserva as relações pai-filho entre as seções. Para documentação de API, construímos um chunking consciente de funções que trata cada função ou endpoint como um limite. Se a descrição de um parâmetro for longa, o bloco se expande em torno dessa função, não em torno de um limite de tokens. Para tickets de suporte, usamos chunking semântico que detecta limites naturais de tópicos. Quando um cliente muda repentinamente de uma reclamação de faturamento para um erro técnico, a divisão ocorre nessa transição. Para wikis e bases de conhecimento não estruturadas, usamos chunking agêntico, onde um LLM leve avalia o texto e decide onde deve haver um limite significativo. Isso é mais lento de configurar do que uma divisão por caracteres, mas é a diferença entre uma recuperação que funciona e uma recuperação que apenas adivinha.

Recuperação Híbrida: Por que a Busca Vetorial Sozinha Não é Suficiente

A busca vetorial entende o significado, mas pode perder correspondências exatas. Se um usuário colar um código de erro como ERR_CONNECTION_RESET_0x5F3, a similaridade semântica pode classificá-lo abaixo de parágrafos que apenas discutem erros de rede em geral. O BM25, por outro lado, encontra strings exatas, mas perde o relacionamento conceitual. Você precisa de ambos.

Executamos a busca vetorial e o BM25 em paralelo. Em seguida, combinamos os resultados com o Reciprocal Rank Fusion, ou RRF, que normaliza as pontuações dos dois espaços de busca diferentes sem forçá-los para a mesma escala. Após a fusão, enviamos os principais candidatos através de um reranker cross-encoder. Isso adiciona uma pequena quantidade de latência, mas o ganho em precisão é significativo. O reranker lê a consulta e cada candidato juntos e atribui uma pontuação de relevância que é muito mais precisa do que a similaridade de cosseno do embedding inicial. Na prática, essa combinação captura códigos de erro exatos que a busca vetorial pura perde, ao mesmo tempo em que traz à tona etapas de solução de problemas conceitualmente relacionadas que a busca por palavra-chave ignoraria.

Expansão de Consulta: Corrigindo a Entrada do Usuário Antes de Atingir o Índice

Os usuários não escrevem consultas de busca perfeitas. Eles fazem perguntas de múltiplos saltos (multi-hop), como "por que meu último deploy falhou e como eu faço o rollback dele?", o que requer encontrar dois corpos de conhecimento separados e conectá-los. Ou fazem perguntas vagas que mapeiam mal para o índice.

Nós transformamos as consultas antes da busca. Uma pergunta de múltiplos saltos (multi-hop) é dividida em subperguntas. Uma intenção vaga é expandida em múltiplas consultas de busca específicas. Descobrimos que expandir uma consulta de usuário em cinco consultas de busca distintas pode elevar o recall de setenta e oito por cento para noventa e seis por cento. Não se trata de forçar o LLM com prompts mais intensos. Trata-se de dar ao sistema de recuperação mais chances de encontrar o contexto correto. Cada consulta gerada captura um ângulo ou terminologia diferente, e os resultados mesclados pintam um quadro completo.

Otimização Bayesiana: Pare de Adivinhar

Uma vez que você tenha múltiplas estratégias de chunking, recuperação híbrida e expansão de consultas, você enfrentará um novo problema. Há muitos parâmetros de ajuste. Tamanho do chunk, porcentagem de sobreposição, peso vetorial versus peso BM25, limiares de reranking e valores top-k interagem de formas não lineares. O ajuste manual torna-se um jogo de adivinhação.

Paramos de adivinhar. Nós tratamos o