A maioria dos protótipos de RAG parece igual por baixo do capô. Alguém alimenta um pipeline com um PDF, fatia o texto em pedaços organizados de 512 tokens, os despeja em um banco de dados vetorial e considera o trabalho feito. Para uma demonstração rápida, isso pode parecer impressionante. Em produção, o sistema colapsa.
Um chunk fixo não se importa com o que corta. Ele dividirá um contrato jurídico no meio de uma cláusula de indenização. Ele colocará cinco endpoints de API não relacionados na mesma janela de contexto e afogará o modelo em ruído. Ele forçará você a recuperar mais fragmentos do que o necessário, aumentando a latência e consumindo tokens. O resultado são respostas incompletas, alucinações e usuários frustrados.
Nós desmontamos nossa camada de recuperação até os alicerces e a reconstruímos. O resultado foi um sistema que atingiu 95% de recall, reduzindo a latência em 40%. Aqui está exatamente como fizemos isso.
Por que Chunks Fixos Morrem em Produção
O padrão de 512 tokens não é uma escolha de design. É um subproduto das janelas de contexto dos primeiros modelos de embedding e dos padrões organizados de bibliotecas. É fácil de implementar e catastrófico de se confiar.
Documentos não são uniformes. Uma cláusula jurídica pode ter setecentos tokens sem uma quebra clara. Se você a fatiar em quinhentos e doze, criará dois fragmentos órfãos. Quando um advogado ou oficial de conformidade pergunta sobre limites de responsabilidade, o sistema retorna apenas metade da obrigação. O modelo de linguagem alucina a metade que falta ou, pior, nega que o limite exista.
A documentação de API sofre do problema oposto. Um chunk de quinhentos tokens pode engolir um módulo inteiro: cabeçalhos de autenticação, códigos de erro, limites de taxa e esquemas de webhook. Quando um desenvolvedor pergunta como lidar com AUTH_4027, o recuperador traz uma mistura de funções não relacionadas. O modelo não tem escolha a não ser transformá-las em uma massa genérica.
Um chunking ruim também infla a latência. Fragmentos fracos significam que você precisa de um top-k maior para cobrir um tópico. Mais chunks significam prompts mais longos. Prompts mais longos significam geração mais lenta e contas mais altas. A experiência do usuário morre por mil cortes.
Combine o Chunk com o Documento
Paramos de contar tokens e começamos a ler o material. A estratégia de chunking correta depende da estrutura da fonte.
Documentos jurídicos precisam de recursive character chunking com limites conscientes de cláusulas. O divisor respeita a hierarquia: ele busca primeiro cabeçalhos de seção, depois parágrafos numerados e, em seguida, quebras naturais de frases. Ele nunca corta uma subcláusula ou divide uma frase obrigacional entre chunks. Quando você recupera um trecho sobre indenização, recebe a cláusula completa, o limite e as exceções.
Documentação de API exige structure-aware chunking. Fazemos o parse por definição de função, não por orçamento de tokens. Cada chunk contém uma assinatura de função completa, suas descrições de parâmetros e as notas de tratamento de erro imediatamente adjacentes. Se um desenvolvedor pesquisar por um método específico, receberá o contrato inteiro, não um fragmento preso em uma divisão arbitrária.
Tickets de suporte são ruidosos e não lineares. Uma thread pode começar com um relatório de bug, introduzir uma solução alternativa e terminar com uma nota de escalonamento interno. O semantic chunking detecta mudanças de tópico medindo a similaridade de embedding entre as frases. Permitimos quebras apenas em limites temáticos naturais, para que uma conversa sobre falhas de login permaneça separada de um acompanhamento sobre ciclos de faturamento.
Wikis foram as mais difíceis. Elas são extensas, interconectadas e organizadas de forma frouxa. Usamos agentic chunking, onde um LLM leve lê uma página e decide as quebras com base na coerência temática. Custa um pouco mais no momento da ingestão, mas os chunks resultantes são autossuficientes e prontos para recuperação. Uma página sobre melhores práticas de implantação é dividida em unidades lógicas: verificações pré-voo, procedimentos de rollback e configuração de monitoramento, em vez de blocos de texto arbitrários.
Recuperação Híbrida: Palavras-chave e Vetores Juntos
A busca vetorial densa entende o significado. Ela é terrível com strings exatas. Se um usuário pesquisar por um código de erro preciso como AUTH_4027 ou um nome de cliente como "Stark Industries", os embeddings vetoriais podem errar o alvo porque otimizam a proximidade conceitual, não a precisão ao nível de caractere.
A busca pura por palavras-chave através do BM25 tem a falha inversa. Ela encontrará AUTH_4027 perfeitamente, mas perderá a ponte conceitual entre "falha de autorização" e "login negado".
Executamos ambos em paralelo. BM25 e busca vetorial operam de forma independente sobre o mesmo corpus. Suas listas de resultados são mescladas usando Reciprocal Rank Fusion, que reordena os candidatos equilibrando seus rankings posicionais. Você não precisa de pesos calibrados. Você simplesmente obtém a precisão da correspondência exata e a intuição da busca semântica em uma única lista ranqueada.
Em seguida, adicionamos um reranker cross-encoder. Este é um modelo separado que pontua cada passagem em relação à consulta original, produzindo um sinal de relevância muito mais refinado do que qualquer um dos recuperadores isoladamente. Isso adiciona cerca de 50 milissegundos de latência. Aumenta o recall em 15 por cento. Se você se preocupa com a qualidade da resposta, essa troca é inegociável.
Expansão de Consulta: Corrija a Busca Antes que Ela Comece
Consultas ruins são o segredo sujo de todo sistema de recuperação. Os usuários não escrevem como o seu espaço de embedding. Eles digitam "quebrou". Eles colam stack traces truncados. Eles usam jargões internos que seu índice nunca viu.
Transformamos a consulta antes mesmo de ela tocar o índice. Primeiro, expandimos uma única consulta em três a cinco termos de busca diversos. Se a original for "pagamento falhou", também pesquisamos por "erro de transação", "faturamento recusado" e "cobrança sem sucesso"
