RAG 评估:精度、召回、MRR、nDCG、忠实度与答案相关性


文档摘要

RAG 评估:精度、召回、MRR、nDCG、忠实度与答案相关性 本节摘要:如果你不能同时给检索与答案打分,你就没法上线这套系统——两者不是同一个指标,同一个提示在不同轴上失败。本节在一份固定 qrels(查询 + 黄金文档 id + 黄金答案文本)之上实现六大指标:四个检索指标(精度@k、召回@k、MRR、nDCG@k)与两个答案级指标(忠实度 Faithfulness、答案相关性 Answer Relevance)。配套一个确定性 mock 评判器,让评估离线运行。读完本节,你能读懂指标值来诊断流水线卡在哪一段(分块、检索、重排、生成、接地),并把「recall@k 回归当测试失败对待」写入 CI。 对应原课程:Phase 19 · Lesson 68 · (原英文 )。

RAG 评估:精度、召回、MRR、nDCG、忠实度与答案相关性

本节摘要:如果你不能同时给检索与答案打分,你就没法上线这套系统——两者不是同一个指标,同一个提示在不同轴上失败。本节在一份固定 qrels(查询 + 黄金文档 id + 黄金答案文本)之上实现六大指标:四个检索指标(精度@k、召回@k、MRR、nDCG@k)与两个答案级指标(忠实度 Faithfulness、答案相关性 Answer Relevance)。配套一个确定性 mock 评判器,让评估离线运行。读完本节,你能读懂指标值来诊断流水线卡在哪一段(分块、检索、重排、生成、接地),并把「recall@k 回归当测试失败对待」写入 CI。

对应原课程:Phase 19 · Lesson 68 · rag-eval-precision-recall(原英文 phases/19-capstone-projects/68-rag-eval-precision-recall/docs/en.md)。本节属第 20 章「毕业项目」的进阶 RAG 赛道。

学习目标

阅读完本节,你应当能够:

  1. 从黄金 qrels 计算四个检索指标:precision@k、recall@k、MRR(平均倒数排名)、nDCG@k。
  2. 计算两个答案级指标:faithfulness(每条主张都被检索上下文支持)、answer relevance(答案切题)。
  3. 构建一份固定 qrels 文件(查询、黄金文档 id、黄金答案文本),让评估端到端读取。
  4. 读懂指标值,诊断流水线卡在哪:检索、排序、生成还是接地

一、问题与直觉

RAG 系统至少有四个活动部件:分块器、检索器、重排器、生成器。任何一个都可能是错答的成因。没有每段指标,你就是盲飞。

用户报一个错答。是分块器切断了答案区间?是检索器没把该块放进 top-k?是重排器把对的块挤出了第一位?是生成器无视了该块自己编了?光看答案分不出来。你需要:检索指标给检索器出什么打分;排序指标给对的块在序中何处打分;忠实度给生成器是否留在检索上下文内打分;答案相关性给答案是否切题打分。本节在一份固定 qrels 上构建全部六个,评估离线确定;生产里把 mock LLM-as-judge 换成真实模型。

精度@k(Precision@k)

检索器返回的 top-k 文档里,有多少比例在黄金集?黄金有三篇,top-3 返回其中两篇加一篇错的,precision@3 是 2/3。当无关检索块代价高时(生成器在其上浪费 token,或该块毒化答案)用精度。

召回@k(Recall@k)

黄金文档里,有多少比例在 top-k?黄金有三篇,top-5 含全部三篇,recall@5 是 1.0。当漏答代价高时(宁可多看一个错块也不要漏掉答案块)用召回。生产 RAG 里人们常引用的是 recall@k——生成器容易丢弃无关块,却无法从没见过的块里变出答案。

MRR(平均倒数排名)

对每个查询,找到排名列表里第一个相关文档的位置,倒数排名是 1/位置,跨查询集求平均。MRR 是「检索器把最佳答案放得多靠前」的单数小结,重权重在位置一:rank-1 贡献 1.0,rank-2 贡献 0.5,rank-10 贡献 0.1,由列表顶部主导。

nDCG@k

归一化折损累计增益。完整公式给每个检索文档赋一个增益(相关常为 1,不相关为 0),按位置的 log 折损,求和,再除以理想 DCG(完美排序会有的 DCG),范围 0~1。nDCG 容纳分级相关性:黄金可说「文档 A 是 3、B 是 2、C 是 1」。MRR 与 recall@k 把一切压成二值;语料里每查询有多个部分相关文档时用 nDCG。

忠实度(Faithfulness)

对生成答案里的每条主张,检查它是否被检索上下文支持。标准实现用 LLM-as-judge 提示,接 (主张, 上下文) 返回是/否,指标是通过的主张比例。忠实度捕获生成器编造内容的失败模式:即便检索器返回了对的块,幻觉的生成器也是坏的。也叫接地性(groundedness)、支持度(support)、归因(attribution)。本节用一个确定性 mock 评判器(检查每条主张的 token 是否以阈值与检索上下文重叠)实现;生产换真实模型,指标形状不变。

答案相关性(Answer Relevance)

答案真的切题吗?忠实度问「答案是否接地于上下文」,答案相关性问「答案是否接地于问题」。一个忠实但跑题的答案忠实度高、相关性低;一个简短切题却无视上下文的答案相关性高、忠实度低。标准实现也用 LLM-as-judge:接 (问题, 答案) 问答案是否切题。本节用一个 token 重叠 + 评判器的替身。

二、固定 qrels

{ "qid": "q1", "query": "分片上传的中止阈值是多少", "gold_doc_ids": ["d1", "d3"], "gold_answer_substring": "三个失败分片", "graded_relevance": {"d1": 3, "d3": 2}, }

每条查询携带:查询串;黄金文档 id 集(给精度/召回/MRR);分级相关性字典(给 nDCG);黄金答案子串(作为每条 qrel 的参考元数据,本节忠实度是判定抽取出的主张对检索上下文,而非对子串)。生产里你来标注;本节随附手建固定集,开箱即跑。

三、从零实现

code/main.py 实现:

  • precision_at_k(retrieved, gold, k) —— 字面定义。
  • recall_at_k(retrieved, gold, k) —— 字面定义。
  • mean_reciprocal_rank(retrieved_list_of_lists, gold_list) —— 跨查询均值。
  • ndcg_at_k(retrieved, graded_relevance, k) —— DCG / IDCG,二值或分级增益。
  • extract_claims(answer) —— 把答案拆成句形主张。
  • faithfulness(claims, context_texts, judge) —— 被判支持的主张比例。
  • answer_relevance(question, answer, judge) —— 评判答案是否切题。
  • MockJudge —— 确定性 token 重叠评判器,离线运行。
  • evaluate_pipeline(pipeline_fn, qrels, ks) —— 跑全部指标的编排器。
  • 一个 demo,对 qrels 跑三种流水线变体(分块基线、混合检索、混合+重排),打印指标表。

四大检索指标的骨架

def precision_at_k(retrieved, gold, k): topk = retrieved[:k] return len(set(topk) & set(gold)) / k def recall_at_k(retrieved, gold, k): topk = retrieved[:k] return len(set(topk) & set(gold)) / len(gold) def reciprocal_rank(retrieved, gold): for i, doc in enumerate(retrieved, start=1): if doc in gold: return 1 / i return 0.0 def ndcg_at_k(retrieved, graded, k): dcg = sum((2**graded.get(d, 0) - 1) / math.log2(i + 1) for i, d in enumerate(retrieved[:k], start=1)) ideal = sorted(graded.values(), reverse=True)[:k] idcg = sum((2**g - 1) / math.log2(i + 1) for i, g in enumerate(ideal, start=1)) return dcg / idcg if idcg > 0 else 0.0

运行:

python3 code/main.py

输出在一张指标表里给出每个变体的 precision@k、recall@k、MRR、nDCG@k、忠实度、答案相关性。混合检索行在召回上击败分块基线;重排行在 MRR 上击败混合。

四、读指标诊断失败

症状 可能成因 修哪里
召回@k 低、精度@k 低 分块切断了答案或检索器找不到 分块边界(第 64 节)或检索模态(第 65 节)
召回@k 尚可、MRR 低 对的块在 top-k 但不在位一 重排器(第 66 节)
MRR 高、忠实度低 生成器无视对上下文编造 生成提示;强制「引用或拒绝」
忠实度高、相关性低 答案接地但跑题 查询重写器(第 67 节)或生成提示
四项都高、用户仍抱怨 评估集不具代表性 用真实用户查询扩充 qrels

五、框架对比

指标 度量什么 何时用
precision@k top-k 里黄金占比 无关块代价高
recall@k 黄金在 top-k 占比 漏答代价高(生产首选)
MRR 首个相关文档的倒数排名均值 关心最佳答案多靠前
nDCG@k 分级折损排序质量 每查询多个部分相关文档
faithfulness 主张被上下文支持的比例 检测生成器幻觉
answer relevance 答案是否切题 检测跑题

业界对比:Ragas、TruLens、DeepEval、LangSmith 都实现这套指标,核心公式与本节一致。它们的共识:检索指标与答案指标分开报,recall@k 是生产 RAG 的首选,faithfulness 必须用与生成器不同模型族的评判器(避免自我偏爱)。

六、demo 会藏住的失败模式

LLM-as-judge 偏见。 模型把自己的输出判得更忠实。用与生成器不同模型族的评判器,或手标一个样本。

qrels 腐烂。 黄金答案随语料漂移:2024 年 1 月对 q1 是黄金的文档,到 10 月因团队重命名了函数就不再是正确答案。排一个季度 qrels 复审。

忠实度微查漏掉宏主张。 逐句忠实度能过,但整体答案结构误导。在自动指标之上加一道样本级定性复审。

recall@k 掩盖每查询失败。 90% 的平均召回能藏住某一类查询总是漏答。按查询类(字面、改写、多主题)切片 qrels,逐片报。

七、可复用产物

  • evaluate_pipeline 编排器:本节的评估是第 69 节端到端系统的验收门,也是前几节(64~67)调参的统一接口。
  • 诊断表:上表作为「症状-成因-修哪里」的排查起点。
  • qrels 三级分层模板:冒烟集 20 条(CI 跑)、回归集 200 条(每夜跑)、深度集 2000 条(每周跑)。

生产模式:

  • 每次检索器或生成器改动都跑评估,把 recall@k 回归当测试失败对待。
  • 每查询持久化指标轨迹;用户抱怨时查匹配的 qrels 条目,看是否本会被抓到。
  • qrels 三级分层:冒烟 20 条 < 30 秒;全回归每夜。

八、练习

  1. 加第五检索指标:hit-rate@k,对比 recall@k,解释何时不同。
  2. 分级忠实度:0(无支持)、1(部分支持)、2(全支持),据此更新指标。
  3. 换真实评判器:把 mock 换真实模型调用,测量 mock 与真实评判器在固定语料上的分歧。
  4. 加查询类切片:「字面、改写、多主题」,逐片报指标。
  5. 加答案长度指标:与忠实度相关,画曲线。

本节要点回顾

  1. 四大活动部件(分块/检索/重排/生成)任一都可能致错答,没有每段指标就是盲飞。
  2. 检索四指标:precision@k(top-k 黄金占比)、recall@k(黄金在 top-k 占比,生产首选)、MRR(首个相关倒数排名均值)、nDCG@k(分级折损排序质量)。
  3. 答案两指标:faithfulness(主张被上下文支持,查幻觉)、answer relevance(切题,查跑题)——两者独立,可一高一低。
  4. 诊断表读指标:低召回查分块/检索,低 MRR 查重排,低忠实查生成提示,低相关查重写。
  5. LLM-as-judge 必须跨模型族——避免自我偏爱;或手标样本。
  6. qrels 会腐烂——排季度复审;按查询类切片防平均掩盖。
  7. 工程化:三级 qrels(冒烟/回归/深度),recall@k 回归当测试失败。

下一节,我们将进入「端到端 RAG 系统」——把第 64~68 节的部件组装成一条流水线,用本节评估验收,证明分段构建在全指标上碾压单段。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U