RAG 评估:精度、召回、MRR、nDCG、忠实度与答案相关性 本节摘要:如果你不能同时给检索与答案打分,你就没法上线这套系统——两者不是同一个指标,同一个提示在不同轴上失败。本节在一份固定 qrels(查询 + 黄金文档 id + 黄金答案文本)之上实现六大指标:四个检索指标(精度@k、召回@k、MRR、nDCG@k)与两个答案级指标(忠实度 Faithfulness、答案相关性 Answer Relevance)。配套一个确定性 mock 评判器,让评估离线运行。读完本节,你能读懂指标值来诊断流水线卡在哪一段(分块、检索、重排、生成、接地),并把「recall@k 回归当测试失败对待」写入 CI。 对应原课程:Phase 19 · Lesson 68 · (原英文 )。
本节摘要:如果你不能同时给检索与答案打分,你就没法上线这套系统——两者不是同一个指标,同一个提示在不同轴上失败。本节在一份固定 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 赛道。
阅读完本节,你应当能够:
RAG 系统至少有四个活动部件:分块器、检索器、重排器、生成器。任何一个都可能是错答的成因。没有每段指标,你就是盲飞。
用户报一个错答。是分块器切断了答案区间?是检索器没把该块放进 top-k?是重排器把对的块挤出了第一位?是生成器无视了该块自己编了?光看答案分不出来。你需要:检索指标给检索器出什么打分;排序指标给对的块在序中何处打分;忠实度给生成器是否留在检索上下文内打分;答案相关性给答案是否切题打分。本节在一份固定 qrels 上构建全部六个,评估离线确定;生产里把 mock LLM-as-judge 换成真实模型。
检索器返回的 top-k 文档里,有多少比例在黄金集?黄金有三篇,top-3 返回其中两篇加一篇错的,precision@3 是 2/3。当无关检索块代价高时(生成器在其上浪费 token,或该块毒化答案)用精度。
黄金文档里,有多少比例在 top-k?黄金有三篇,top-5 含全部三篇,recall@5 是 1.0。当漏答代价高时(宁可多看一个错块也不要漏掉答案块)用召回。生产 RAG 里人们常引用的是 recall@k——生成器容易丢弃无关块,却无法从没见过的块里变出答案。
对每个查询,找到排名列表里第一个相关文档的位置,倒数排名是 1/位置,跨查询集求平均。MRR 是「检索器把最佳答案放得多靠前」的单数小结,重权重在位置一:rank-1 贡献 1.0,rank-2 贡献 0.5,rank-10 贡献 0.1,由列表顶部主导。
归一化折损累计增益。完整公式给每个检索文档赋一个增益(相关常为 1,不相关为 0),按位置的 log 折损,求和,再除以理想 DCG(完美排序会有的 DCG),范围 0~1。nDCG 容纳分级相关性:黄金可说「文档 A 是 3、B 是 2、C 是 1」。MRR 与 recall@k 把一切压成二值;语料里每查询有多个部分相关文档时用 nDCG。
对生成答案里的每条主张,检查它是否被检索上下文支持。标准实现用 LLM-as-judge 提示,接 (主张, 上下文) 返回是/否,指标是通过的主张比例。忠实度捕获生成器编造内容的失败模式:即便检索器返回了对的块,幻觉的生成器也是坏的。也叫接地性(groundedness)、支持度(support)、归因(attribution)。本节用一个确定性 mock 评判器(检查每条主张的 token 是否以阈值与检索上下文重叠)实现;生产换真实模型,指标形状不变。
答案真的切题吗?忠实度问「答案是否接地于上下文」,答案相关性问「答案是否接地于问题」。一个忠实但跑题的答案忠实度高、相关性低;一个简短切题却无视上下文的答案相关性高、忠实度低。标准实现也用 LLM-as-judge:接 (问题, 答案) 问答案是否切题。本节用一个 token 重叠 + 评判器的替身。
{ "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) —— 跑全部指标的编排器。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 必须用与生成器不同模型族的评判器(避免自我偏爱)。
LLM-as-judge 偏见。 模型把自己的输出判得更忠实。用与生成器不同模型族的评判器,或手标一个样本。
qrels 腐烂。 黄金答案随语料漂移:2024 年 1 月对 q1 是黄金的文档,到 10 月因团队重命名了函数就不再是正确答案。排一个季度 qrels 复审。
忠实度微查漏掉宏主张。 逐句忠实度能过,但整体答案结构误导。在自动指标之上加一道样本级定性复审。
recall@k 掩盖每查询失败。 90% 的平均召回能藏住某一类查询总是漏答。按查询类(字面、改写、多主题)切片 qrels,逐片报。
evaluate_pipeline 编排器:本节的评估是第 69 节端到端系统的验收门,也是前几节(64~67)调参的统一接口。生产模式:
下一节,我们将进入「端到端 RAG 系统」——把第 64~68 节的部件组装成一条流水线,用本节评估验收,证明分段构建在全指标上碾压单段。