No artigo anterior desta série, separei ETL, chunking e embedding como três camadas distintas de um pipeline de RAG. Mas ter as três bem implementadas não significa nada se você não consegue medir se o retrieval está funcionando.
E aqui mora um problema recorrente: a forma mais comum de "avaliar" RAG em produção ainda é abrir o chat, fazer três perguntas, olhar a resposta e dizer "ficou bom". Isso não é avaliação, é vibe check. E vibe check não escala, não é reprodutível, e não pega regressão.
Neste artigo eu quero destrinchar duas coisas: as métricas que realmente importam para retrieval, e como construir um harness de avaliação em camadas que eu uso em produção, sem depender só de "o LLM disse que tá bom".
Por que avaliar resposta final não é suficiente
Um erro comum é avaliar só a resposta final do LLM. O problema é que isso mistura dois tipos de falha completamente diferentes:
- Falha de retrieval: o chunk certo nem foi recuperado. O LLM está respondendo com o contexto errado, mas ele pode ainda assim "parecer" convincente.
- Falha de geração: o chunk certo foi recuperado, mas o LLM não usou bem, ignorou parte da informação, ou alucinou em cima do contexto correto.
Se você só olha a resposta final, não sabe qual das duas camadas quebrou. E sem saber isso, você fica ajustando prompt quando na verdade o problema é chunking, ou trocando de modelo de embedding quando o problema é o ETL.
Por isso, avaliação de RAG precisa ter uma camada específica para retrieval, separada da avaliação de geração.
As métricas de retrieval que importam
Antes de qualquer harness sofisticado, você precisa de um dataset de avaliação: pares de pergunta → chunks corretos esperados (ground truth), construído a partir de casos reais.
Com isso em mãos, as métricas clássicas de recuperação de informação se aplicam:
- Precision@k: dos k chunks retornados, quantos são realmente relevantes. Mede ruído.
- Recall@k: dos chunks relevantes que existem, quantos você conseguiu trazer dentro do top-k. Mede se você está perdendo informação.
- MRR (Mean Reciprocal Rank): o quão cedo o primeiro chunk relevante aparece no ranking. Importa porque LLM dá mais peso ao que vem primeiro no contexto.
- nDCG: parecido com MRR, mas considera relevância graduada (nem todo chunk relevante é igualmente útil) e pondera a posição de todos eles, não só do primeiro.
Na prática, recall@k costuma ser a métrica que mais expõe problema de chunking: se o recall está baixo, geralmente é porque a informação foi fragmentada errado antes de virar embedding, não porque o modelo de embedding é ruim.
Métrica sem contexto não decide nada sozinha. Um recall@5 de 70% pode ser ótimo para FAQ simples e péssimo para uma base jurídica onde perder um trecho muda a resposta. O threshold aceitável depende do domínio.
O harness em camadas
Métricas de retrieval resolvem uma parte do problema. Mas a resposta final do LLM também precisa ser avaliada, e aqui uma camada só de métrica não é suficiente, você não tem ground truth de texto livre pra comparar. É aqui que entra o harness em camadas, dividido em três estágios:
1. Checks determinísticos
A primeira linha de defesa, e a mais barata de rodar. Perguntas binárias e verificáveis por código, sem precisar de LLM:
- A resposta contém uma citação de fonte válida?
- O formato esperado foi respeitado (JSON, markdown, etc.)?
- Palavras-chave obrigatórias apareceram (ex: um número de ticket, um nome de campo)?
- A resposta não excedeu o limite de tokens/tamanho esperado?
Esses checks são rápidos, baratos, e pegam boa parte dos bugs óbvios antes de gastar uma chamada de LLM-as-judge.
2. LLM-as-judge
Para o que não dá pra verificar deterministicamente, correção semântica, completude, se a resposta realmente responde à pergunta, um segundo LLM avalia a resposta contra critérios explícitos (rubric), não só "essa resposta parece boa?".
Um ponto crítico aqui: o judge precisa ter acesso ao mesmo contexto recuperado, não só à pergunta e resposta. Sem isso, ele não consegue distinguir "o LLM respondeu mal" de "o LLM respondeu certo dado um contexto incompleto", que é exatamente a distinção que buscamos.
3. Calibration gate
Essa é a camada que mais gente pula, e a mais importante. LLM-as-judge sozinho tem um problema conhecido: ele pode ser inconsistente, enviesado a favor de respostas mais longas, ou simplesmente errar sistematicamente em certos tipos de pergunta.
O calibration gate é uma amostra do output do judge revisada por humano periodicamente, comparando o veredito do LLM contra o julgamento humano. Se a concordância cair abaixo de um threshold, isso é um sinal de que o judge não está confiável naquele momento — seja por mudança de prompt, mudança de modelo, ou deriva no dataset de avaliação.
Sem esse gate, é fácil cair numa armadilha perigosa: o harness reporta "95% de aprovação" e ninguém percebe que o próprio juiz está calibrado errado.
Um bug real que essa camada evita
Vale mencionar um tipo de falha que só um harness bem desenhado pega: sistemas com replanejamento automático (replanning) podem, silenciosamente, converter um bloqueio de guardrail em success: true, o sistema tenta de novo, contorna a trava de segurança, e reporta sucesso como se nada tivesse acontecido.
Sem uma camada de avaliação que audita especificamente os stop_reason e a trajetória completa da execução (não só o resultado final), esse tipo de bug passa despercebido indefinidamente. É o tipo de coisa que só aparece quando você trata avaliação como parte da arquitetura, não como um script que roda de vez em quando.
Conclusão
Avaliar RAG não é rodar uma métrica e comparar dois números. É separar onde a falha realmente aconteceu, retrieval ou geração, e construir camadas de verificação com custos e confiabilidades diferentes: determinístico primeiro (barato e binário), LLM-as-judge depois (semântico, mas falível), e um gate de calibração por cima de tudo (a garantia de que o próprio juiz ainda está confiável).
Sem isso, "meu RAG está funcionando bem" é só uma opinião. Com isso, é um número que você pode defender, e principalmente, que pega regressão antes que o usuário pegue.
Este artigo faz parte de uma série sobre implementações reais de RAG e engenharia de IA aplicada.
Top comments (0)