O problema de sempre: o RAG está de pé, alguém pergunta se está bom, e a resposta honesta é "parece". Você não tem dataset anotado, porque anotar dataset é caro e chato e ninguém faz isso antes de precisar.
As métricas sem referência prometem resolver isso — um LLM avalia a resposta olhando só pergunta, contexto e saída, sem gabarito. A pergunta que a gente queria responder é se dá pra confiar nelas. Então fizemos o inverso do normal: anotamos 180 respostas à mão depois, e conferimos quais métricas tinham acertado.
As três métricas
Fidelidade — quanto da resposta é sustentado pelo contexto recuperado. Quebra a resposta em afirmações e pergunta, uma a uma, se o contexto suporta aquilo:
Relevância da resposta — gera perguntas a partir da resposta e mede a similaridade delas com a pergunta original. Se a resposta responde outra coisa, as perguntas geradas divergem.
Relevância do contexto — que fração dos chunks recuperados era realmente necessária pra responder.
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_relevancy
resultado = evaluate(
dataset, # pergunta, contexto, resposta — sem ground_truth
metrics=[faithfulness, answer_relevancy, context_relevancy],
llm=juiz_local, # qwen3:8b via Ollama
)Contra o julgamento humano
Dois revisores classificaram as mesmas 180 respostas de 1 a 5, resolvendo divergência por discussão. Depois medimos a correlação de Spearman entre cada métrica e a nota humana média.
Correlação com o julgamento humano
ρ de Spearman · n=180 respostas
ver como tabela
| ρ de Spearman | ρ |
|---|---|
| fidelidade | 0.71 |
| relevância da resposta | 0.44 |
| relevância do contexto | 0.19 |
Fidelidade se sustenta. Relevância da resposta é fraca mas útil como alarme. Relevância do contexto, com esse juiz e esse corpus, não mede nada que a gente reconheça — ρ = 0.19 é ruído.
O tamanho do juiz importa menos do que parece
Rodamos a fidelidade com três modelos de juiz diferentes na mesma amostra:
| juiz | ρ com humano | tempo por resposta | custo |
|---|---|---|---|
| qwen3:8b (local) | 0.71 | 4.2 s | 0 |
| qwen3:14b (local) | 0.74 | 11.8 s | 0 |
| modelo de API grande | 0.78 | 1.1 s | US$ 0,004 |
Sete pontos de correlação separam o 8B local do modelo de API. Pra ranquear duas versões do seu pipeline, o 8B local resolve. Pra publicar um número, não.
Como estamos usando isso
Fidelidade virou portão de CI: toda mudança no pipeline roda contra 60 perguntas fixas, e queda maior que 0,05 barra o merge. Não é uma medida de qualidade — é um detector de regressão, e é isso que a gente precisava.
As outras duas ficaram no painel, sem portão. Relevância da resposta pega o caso em que o retriever traz lixo e o gerador inventa por cima; relevância do contexto ficou porque dá trabalho tirar do painel, e a gente não olha.
Em aberto
Falta a parte difícil: essas métricas concordam com humano em média, mas a gente não sabe se erram junto. Se fidelidade e nota humana discordam sempre nas mesmas 15 perguntas, isso é uma classe inteira de falha invisível pro portão de CI.
Estamos anotando mais 300 respostas pra olhar a distribuição do erro em vez da média. Quando terminar, esse paper ganha uma seção — ou uma retratação.