Artigo · Blog
RAG não falhou por causa da busca. Falhou por causa do contexto que você não deu para o modelo.
A maioria dos problemas com RAG em produção não é de recuperação de documentos. É de contexto mal construído passado para o modelo. Esse artigo explica por que a pipeline funciona no teste e quebra na vida real, e o que eu mudaria hoje.
RAG não falhou por causa da busca. Falhou por causa do contexto que você não deu para o modelo.
Eu coloquei um sistema RAG em produção achando que o problema difícil era a busca vetorial.
Configurei o embedding, ajustei a similaridade de cosseno, testei com perguntas diretas, os chunks certos voltavam no top-3. Parecia sólido. Em produção, o modelo começou a alucinar de um jeito específico: ele misturava informações de documentos diferentes como se fossem o mesmo, e respondia com confiança sobre coisas que nenhum chunk dizia explicitamente.
O retrieval estava correto. O problema era o que eu fazia com o resultado dele.
O que a maioria assume sobre RAG
Existe uma ideia implícita de que RAG resolve o problema de conhecimento do modelo. Você indexa seus documentos, busca os mais relevantes, joga no prompt e o modelo responde com base neles.
Essa ideia está certa na teoria e incompleta na prática.
O modelo não lê os chunks como um humano lê um parágrafo. Ele recebe um bloco de texto concatenado, sem hierarquia clara, sem relação explícita entre os pedaços, e tenta inferir o que importa. Quando os chunks são parecidos mas contraditórios entre si, ou quando o contexto está fragmentado demais, o modelo preenche os buracos. E preenche com confiança.
Isso não é bug do modelo. É o comportamento esperado de um sistema de linguagem diante de contexto ambíguo.
O problema real: você está montando contexto, não só buscando documentos
Num sistema que construí para consulta de documentação técnica, a busca vetorial retornava os cinco chunks mais similares à pergunta do usuário. Eu os concatenava em ordem de score e passava pro modelo.
O que eu não percebia: dois chunks podiam vir do mesmo documento com versões diferentes. Ou de documentos que tratavam do mesmo assunto com conclusões opostas. Sem nenhuma âncora estrutural no prompt dizendo "esses são três fontes distintas", o modelo os tratava como um contexto coeso.
A falha não aparecia em perguntas simples. Aparecia quando o usuário fazia perguntas que cruzavam conceitos, quando a resposta certa dependia de entender que existiam múltiplas fontes, quando o tom certo era "depende do contexto X ou Y" mas o modelo respondia com certeza falsa.
O retrieval estava perfeito. O contexto era lixo.
O que mudou quando parei de tratar o contexto como string
A primeira mudança foi estrutural. Em vez de concatenar chunks como texto puro, passei a montar o contexto com metadados explícitos:
[Fonte 1 - Documento: autenticacao_v2.md | Relevância: 0.91]
...conteúdo do chunk...
[Fonte 2 - Documento: autenticacao_legacy.md | Relevância: 0.87]
...conteúdo do chunk...
Simples. Mas o efeito foi imediato. O modelo começou a referenciar fontes por nome, a contrastar versões quando eram diferentes, e a usar "de acordo com o documento X" em vez de responder como se a verdade fosse única.
A segunda mudança foi no system prompt. Parei de instruir o modelo a "responder com base nos documentos fornecidos" e passei a instruí-lo sobre a natureza do contexto: "Você receberá trechos de múltiplos documentos que podem conter informações complementares ou contraditórias. Quando houver conflito, indique explicitamente."
Isso não é engenharia de prompt sofisticada. É comunicar a estrutura do contexto para o modelo.
Onde o MCP entra nessa história
Quando comecei a trabalhar com MCP, o padrão que me chamou atenção não foi a capacidade de chamar ferramentas. Foi a separação explícita entre contexto, ferramentas e instrução.
O MCP força você a pensar em camadas. O que é dado de contexto. O que é ferramenta que o modelo pode invocar. O que é instrução sobre como agir.
Num sistema RAG ingênuo, tudo isso está misturado num prompt gigante. O modelo infere a estrutura. Às vezes acerta, às vezes não.
Quando separei essas camadas, até fora do MCP, o comportamento ficou mais previsível. O modelo sabia o que era fonte de verdade, o que era instrução operacional, e o que era ferramenta disponível.
O problema do RAG mal feito é que ele trata o modelo como um buscador melhorado. Você recupera, joga no modelo, espera a resposta. O modelo virou o passo final de um pipeline que não pensa nele como agente.
A armadilha do chunk certo no lugar errado
Existe um padrão que comecei a chamar de Problema do Chunk Orfão: o retrieval retorna um trecho tecnicamente relevante, mas que fora do documento original perde o sentido.
Exemplo real: um chunk que dizia "este comportamento foi depreciado na versão 3.0" era retornado para perguntas sobre uma funcionalidade específica. Sozinho, sem o parágrafo anterior que explicava qual comportamento era esse, o chunk era inútil ou confuso. O modelo tentava inferir o antecedente.
A solução não foi aumentar o tamanho do chunk. Foi adicionar contexto de janela: ao recuperar um chunk, incluir automaticamente o parágrafo anterior e o posterior quando o score de relevância fosse alto mas o chunk fosse pequeno.
Parece óbvio depois que você vê o problema. Antes de ver, não parece.
O que a avaliação em teste não captura
Todo sistema RAG parece funcionar em teste porque você testa com perguntas que têm respostas diretas nos seus documentos.
Em produção, os usuários perguntam de formas que você não antecipou. Eles perguntam sobre relações entre conceitos. Eles perguntam sobre exceções. Eles perguntam o que acontece quando dois cenários colidem.
Essas perguntas estressam a qualidade do contexto, não a qualidade da busca.
Eu levei mais tempo do que deveria para perceber que minha suíte de avaliação testava o retrieval e assumia que o contexto estava certo. A avaliação end-to-end com usuários reais revelou um tipo diferente de falha que nenhuma métrica de similaridade capturava.
Trade-offs que ninguém fala
Contexto estruturado tem custo. Mais tokens, mais latência, mais custo por requisição. Quando você começa a incluir metadados, contexto de janela e separação de fontes, o prompt cresce.
Existe um ponto onde adicionar contexto demais degrada a qualidade porque o modelo perde o fio dos chunks mais relevantes no meio do ruído. O problema não some, ele inverte.
A resposta que encontrei foi priorização ativa: em vez de passar os top-5 chunks sempre, passar os top-3 com contexto estruturado. Menos volume, mais clareza estrutural. Para o meu caso, foi a combinação que funcionou.
Não é a resposta universal. Depende do domínio, do tamanho dos documentos, do modelo.
O que eu faria diferente hoje
Começaria avaliando qualidade de contexto antes de qualidade de retrieval.
É mais fácil medir retrieval porque você tem métricas estabelecidas: precision@k, recall, MRR. Qualidade de contexto é mais difícil de medir e mais fácil de ignorar.
Mas é onde a maioria dos sistemas falha.
Retrieval perfeito com contexto mal montado produz respostas confiantes e erradas. Que é o pior tipo de falha num sistema que o usuário vai confiar.
O modelo não vai te avisar que o contexto está ambíguo. Ele vai responder mesmo assim.
Essa é a diferença entre um sistema RAG que funciona em demo e um que você confia em produção.