Métricas de recuperação: taxa de acerto, MRR e NDCG
Crie um conjunto de dados de referência com consultas e documentos relevantes e calcule a taxa de acerto, a classificação recíproca média e NDCG para medir com que frequência seu recuperador encontra as partes corretas.
Métricas de recuperação: taxa de acerto, MRR e NDCG é uma aula grátis de AI Engineering Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Engineering Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Engineering Academy inclui 4 aulas no total.
Por que usar métricas de recuperação diferentes?
A taxa de acerto informa se um trecho relevante apareceu em qualquer posição entre os K principais resultados, mas não informa onde ele apareceu na classificação. Um sistema que sempre coloca o melhor trecho na quinta posição é pior do que um que o coloca consistentemente na primeira posição, mesmo que ambos tenham a mesma taxa de acerto. Métricas mais detalhadas, como MRR e NDCG, capturam a qualidade da classificação e recompensam os sistemas que colocam os trechos mais relevantes no topo, onde o LLM e os usuários têm maior probabilidade de utilizá-los.
Taxa de acerto @K: revisão e implementação
A taxa de acerto@K é a métrica mais simples: para qual fração das consultas pelo menos um trecho relevante aparece entre os K principais resultados? Ela fornece um sinal binário por consulta e é fácil de interpretar. Calcule-a verificando a interseção entre os identificadores recuperados e os identificadores relevantes conhecidos. Use K=5 como padrão, pois a maioria dos sistemas RAG recupera 5 trechos. Compare a taxa de acerto@1, @3 e @5 para entender como a sensibilidade muda à medida que você amplia a janela de recuperação.
def hit_rate_at_k(golden_dataset, retriever, k=5):
hits = 0
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = [r['id'] for r in retrieved[:k]]
relevant_ids = set(item['relevant_chunk_ids'])
if any(rid in relevant_ids for rid in retrieved_ids):
hits += 1
return hits / len(golden_dataset)
for k in [1, 3, 5, 10]:
hr = hit_rate_at_k(golden_dataset, retriever, k=k)
print(f'Hit rate@{k}: {hr:.1%}')Classificação recíproca média (MRR)
MRR (Classificação recíproca média) mede a média do inverso da posição em que o primeiro trecho relevante aparece. Se o trecho relevante estiver na posição 1, a classificação recíproca será 1/1 = 1,0. Na posição 2, será 0,5; na posição 5, será 0,2. A MRR é calculada sobre todas as consultas. Uma MRR mais alta significa que o recuperador coloca consistentemente os trechos relevantes perto do topo, o que é importante porque o LLM presta mais atenção ao contexto posicionado no início do prompt.
def mean_reciprocal_rank(golden_dataset, retriever, top_k=10):
reciprocal_ranks = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=top_k)
retrieved_ids = [r['id'] for r in retrieved]
relevant_ids = set(item['relevant_chunk_ids'])
rr = 0.0
for rank, rid in enumerate(retrieved_ids, start=1):
if rid in relevant_ids:
rr = 1.0 / rank
break # only the first relevant result counts
reciprocal_ranks.append(rr)
mrr = sum(reciprocal_ranks) / len(reciprocal_ranks)
print(f'MRR@{top_k}: {mrr:.3f}')
return mrrInterpretação das pontuações de MRR
As pontuações de MRR têm interpretações intuitivas: MRR = 1,0 significa que o primeiro trecho relevante está sempre na posição 1 (perfeito). MRR = 0,5 significa que ele normalmente está na posição 2. MRR = 0,25 significa que ele normalmente está na posição 4 — a informação relevante aparece suficientemente abaixo para que possa ser truncada do contexto. Para RAG, a meta é MRR > 0,7, garantindo que seu trecho mais relevante esteja consistentemente entre as duas primeiras posições.
# MRR interpretation table
mrr_interpretations = {
1.0: 'Perfect — relevant chunk always at rank 1',
0.5: 'Good — typically at rank 2',
0.33: 'Acceptable — typically at rank 3',
0.25: 'Weak — typically at rank 4',
0.1: 'Poor — relevant chunk rarely near the top'
}
for score, description in mrr_interpretations.items():
print(f'MRR {score:.2f}: {description}')Precisão @K
Precisão@K mede qual fração dos K trechos recuperados é realmente relevante. Diferentemente da taxa de acerto (que é binária), a precisão@K mede a relação sinal-ruído nos resultados da sua recuperação. Uma precisão baixa significa que o LLM recebe contexto irrelevante junto com os trechos relevantes, aumentando o risco de confusão ou injeção de prompt. Para RAG, uma meta saudável é precisão@5 > 0,6.
def precision_at_k(golden_dataset, retriever, k=5):
precisions = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = [r['id'] for r in retrieved[:k]]
relevant_ids = set(item['relevant_chunk_ids'])
relevant_retrieved = sum(
1 for rid in retrieved_ids if rid in relevant_ids
)
precision = relevant_retrieved / k
precisions.append(precision)
mean_precision = sum(precisions) / len(precisions)
print(f'Precision@{k}: {mean_precision:.3f}')
return mean_precisionGanho cumulativo com desconto (DCG)
DCG é uma métrica de avaliação de listas classificadas que recompensa a colocação de trechos mais relevantes nas posições superiores. Ela soma as pontuações de relevância dos trechos recuperados, mas aplica um desconto logarítmico de acordo com a posição: a posição 1 recebe crédito integral, a posição 2 recebe o desconto de log(2), e assim por diante. Trechos mais relevantes no topo resultam em um DCG maior. A versão normalizada (NDCG) divide pelo DCG ideal (a melhor classificação possível) para produzir uma pontuação entre 0 e 1.
import math
def dcg_at_k(relevances, k):
'''relevances[i] = 1 if chunk at rank i+1 is relevant, else 0'''
dcg = 0.0
for i, rel in enumerate(relevances[:k]):
# rank is i+1, discount is log2(rank + 1)
dcg += rel / math.log2(i + 2)
return dcg
def ndcg_at_k(retrieved_ids, relevant_ids, k):
relevances = [1 if rid in relevant_ids else 0
for rid in retrieved_ids[:k]]
actual_dcg = dcg_at_k(relevances, k)
ideal_dcg = dcg_at_k([1] * min(len(relevant_ids), k), k)
return actual_dcg / ideal_dcg if ideal_dcg > 0 else 0.0Cálculo do NDCG em todo o conjunto de dados
NDCG@K é a métrica de referência para recuperação em sistemas de busca. Ela captura simultaneamente a relevância e a posição na classificação. Um NDCG@5 de 0,85 significa que seu recuperador alcança, em média, 85% da melhor classificação teórica. O NDCG lida com casos em que há vários trechos relevantes por consulta (cada um recebe uma pontuação de relevância) e penaliza sistemas que encontram os trechos relevantes, mas os classificam em posições muito baixas.
def mean_ndcg_at_k(golden_dataset, retriever, k=5):
ndcg_scores = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = [r['id'] for r in retrieved[:k]]
relevant_ids = set(item['relevant_chunk_ids'])
score = ndcg_at_k(retrieved_ids, relevant_ids, k)
ndcg_scores.append(score)
mean = sum(ndcg_scores) / len(ndcg_scores)
print(f'NDCG@{k}: {mean:.4f}')
return mean
# Compute all retrieval metrics together
hit_rate = hit_rate_at_k(golden_dataset, retriever, k=5)
mrr = mean_reciprocal_rank(golden_dataset, retriever, top_k=5)
ndcg = mean_ndcg_at_k(golden_dataset, retriever, k=5)Uso do RAGAS para métricas automatizadas
A biblioteca RAGAS fornece uma estrutura de avaliação pronta para produção para sistemas RAG. Ela implementa métricas de precisão do contexto, revocação do contexto, fidelidade e relevância da resposta usando uma abordagem de LLM como avaliador. Forneça suas perguntas, respostas, contextos recuperados e respostas de referência ao RAGAS e receba um relatório completo de avaliação com pontuações para cada métrica. Essa é a maneira mais rápida de configurar um pipeline abrangente de avaliação de RAG.
from ragas import evaluate
from ragas.metrics import (
context_precision,
context_recall,
faithfulness,
answer_relevancy
)
from datasets import Dataset
eval_data = Dataset.from_list([
{
'question': item['question'],
'answer': item['generated_answer'],
'contexts': item['retrieved_texts'],
'ground_truth': item['expected_answer']
}
for item in golden_dataset_with_answers
])
results = evaluate(
eval_data,
metrics=[context_precision, context_recall, faithfulness, answer_relevancy]
)
print(results)Divisão das métricas por categoria de consulta
As médias gerais das métricas ocultam padrões importantes. Divida seu conjunto de dados dourado em categorias — consultas factuais, comparações, perguntas procedurais do tipo “como fazer” e perguntas fora do escopo — e calcule as métricas separadamente para cada uma. Você pode descobrir que a taxa de acerto é de 95% para consultas factuais, mas de apenas 60% para comparações com várias etapas. As métricas por categoria revelam os modos de falha específicos que as pontuações agregadas ocultam.
from collections import defaultdict
def evaluate_by_category(golden_dataset, retriever):
by_category = defaultdict(list)
for item in golden_dataset:
category = item.get('category', 'unknown')
retrieved = retriever.retrieve(item['question'], top_k=5)
retrieved_ids = {r['id'] for r in retrieved}
hit = bool(retrieved_ids & set(item['relevant_chunk_ids']))
by_category[category].append(hit)
print('Hit rate by category:')
for cat, hits in sorted(by_category.items()):
hr = sum(hits) / len(hits)
print(f' {cat}: {hr:.1%} ({sum(hits)}/{len(hits)})')Quando as métricas divergem
Às vezes, as métricas enviam sinais conflitantes. Você pode melhorar o NDCG (melhor classificação) enquanto a taxa de acerto permanece estável (o mesmo número de falhas). Isso acontece quando a otimização move trechos relevantes da posição 6 para a posição 2 sem trazer para o top 5 consultas que antes não obtinham resultados relevantes. Nesses casos, verifique se sua otimização ajudou nas consultas que já estavam funcionando e negligenciou as que falhavam. Sempre examine exemplos individuais de falha junto com as métricas agregadas.
def analyze_failures(golden_dataset, retriever, top_k=5):
failures = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=top_k)
retrieved_ids = {r['id'] for r in retrieved}
relevant_ids = set(item['relevant_chunk_ids'])
if not (retrieved_ids & relevant_ids):
failures.append({
'question': item['question'],
'expected_chunks': list(relevant_ids),
'retrieved_chunks': [r['id'] for r in retrieved],
'top_score': retrieved[0]['score'] if retrieved else None
})
print(f'Failures: {len(failures)}/{len(golden_dataset)}')
return failuresRevocação @K: completude da recuperação
Revocação@K mede qual fração de todos os trechos relevantes foi recuperada entre os K principais resultados. Se uma pergunta tiver 3 trechos relevantes no índice e seu recuperador retornar 2 deles entre os 5 principais, a revocação@5 será 2/3 = 0,67. Uma revocação alta é importante quando o LLM precisa de várias evidências para sintetizar uma resposta completa — a ausência de um único trecho essencial pode tornar a resposta incompleta. Equilibre precisão e revocação ajustando K: um K maior melhora a revocação, mas reduz a precisão.
def recall_at_k(golden_dataset, retriever, k=5):
recalls = []
for item in golden_dataset:
retrieved = retriever.retrieve(item['question'], top_k=k)
retrieved_ids = set(r['id'] for r in retrieved[:k])
relevant_ids = set(item['relevant_chunk_ids'])
if not relevant_ids:
continue # skip items with no annotated relevant chunks
retrieved_relevant = retrieved_ids & relevant_ids
recall = len(retrieved_relevant) / len(relevant_ids)
recalls.append(recall)
mean_recall = sum(recalls) / len(recalls)
print(f'Recall@{k}: {mean_recall:.3f}')
return mean_recallVerificação rápida
Teste sua compreensão dos conceitos de Engenharia de IA desta lição.
Recapitulação da lição
Nesta lição, você aprendeu: a taxa de acerto@K como métrica binária de presença; MRR para medir a posição média do primeiro trecho relevante; precisão@K para medir a relação sinal-ruído da recuperação; NDCG@K como métrica de referência para listas classificadas; e a biblioteca RAGAS para automatizar a avaliação de RAG com precisão do contexto, revocação, fidelidade e relevância da resposta. Em seguida, aprofundaremos as métricas de geração e a medição da fidelidade.
Perguntas Frequentes
A aula “Métricas de recuperação: taxa de acerto, MRR e NDCG” é grátis?
Sim — o texto completo de “Métricas de recuperação: taxa de acerto, MRR e NDCG” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Engineering Academy, atualize para CoddyKit PRO. O curso de AI Engineering Academy inclui 4 aulas no total.
O que vou aprender em “Métricas de recuperação: taxa de acerto, MRR e NDCG”?
Crie um conjunto de dados de referência com consultas e documentos relevantes e calcule a taxa de acerto, a classificação recíproca média e NDCG para medir com que frequência seu recuperador encontra… Você pratica AI Engineering Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Engineering Academy?
Nenhuma experiência prévia é necessária. AI Engineering Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Métricas de recuperação: taxa de acerto, MRR e NDCG”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Engineering Academy?
Sim. Cada aula de AI Engineering Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que a avaliação é importante em RAG
- Métricas de recuperação: taxa de acerto, MRR e NDCG
- Métricas de geração: fidelidade e relevância da resposta
- Criando uma estrutura automatizada de avaliação