8.1.8 RAG 评估

完成本节后,你将能够:
- 理解为什么 RAG 不能只凭单次演示判断好坏
- 分清检索评估和回答评估的不同目标
- 使用一个小型样例计算简单指标
- 建立“先做评估,再做优化”的工程习惯
一、为什么 RAG 特别需要评估?
Section titled “一、为什么 RAG 特别需要评估?”因为它不是单一模块
Section titled “因为它不是单一模块”RAG 不是单个模型,而是至少包含:
- 文档处理
- 检索
- 上下文拼装
- 生成回答
任何一环出错,最终答案都可能变差。
所以不能只问“答对了吗”
Section titled “所以不能只问“答对了吗””你还得问:
- 是没检索到?
- 还是检索到了但没用好?
- 还是回答语言组织不好?
这就是为什么 RAG 评估必须分层看。
二、第一层:检索评估
Section titled “二、第一层:检索评估”最常见的直觉指标:Hit@k
Section titled “最常见的直觉指标:Hit@k”Hit@k 的意思很简单:
正确证据有没有出现在前 k 个检索结果里?
如果用户问题的正确证据在 top-3 里,就算 hit。
为什么这个指标很重要?
Section titled “为什么这个指标很重要?”因为如果正确资料根本没召回,后面的生成几乎不可能稳定答对。
所以:
检索评估是 RAG 评估的地基。
三、第二层:回答评估
Section titled “三、第二层:回答评估”只看“语句通顺”远远不够
Section titled “只看“语句通顺”远远不够”回答评估至少要关注:
- 答案对不对
- 有没有依据
- 有没有胡编
| 维度 | 关注点 |
|---|---|
| 正确性 | 答案事实是否正确 |
| 忠实性 | 是否基于给定资料 |
| 相关性 | 是否回答了用户问题 |
| 完整性 | 关键信息是否答全 |
在业务里,不同维度的重要性不一样。


好的评估不是做一次就完,而是一个循环:测试集 -> 检索 -> 回答 -> 引用 -> 分析失败 -> 修正 -> 再评估。
四、一个最小评估数据集
Section titled “四、一个最小评估数据集”下面我们手工构造一份迷你评估集。
dataset = [ { "question": "多久内可以退款?", "gold_doc": "退款政策", "gold_answer": "课程购买后 7 天内可申请退款" }, { "question": "怎么获得证书?", "gold_doc": "证书说明", "gold_answer": "完成项目并通过测试后可获得证书" }]
predictions = [ { "retrieved_docs": ["退款政策", "学习顺序"], "answer": "课程购买后 7 天内可申请退款" }, { "retrieved_docs": ["学习顺序", "证书说明"], "answer": "完成项目并通过测试后可获得证书" }]
print(dataset)print(predictions)预期输出:
[{'question': '多久内可以退款?', 'gold_doc': '退款政策', 'gold_answer': '课程购买后 7 天内可申请退款'}, {'question': '怎么获得证书?', 'gold_doc': '证书说明', 'gold_answer': '完成项目并通过测试后可获得证书'}][{'retrieved_docs': ['退款政策', '学习顺序'], 'answer': '课程购买后 7 天内可申请退款'}, {'retrieved_docs': ['学习顺序', '证书说明'], 'answer': '完成项目并通过测试后可获得证书'}]读这份数据时,把它分成“标准答案”和“系统预测”两列:gold_doc / gold_answer 是参考标准,retrieved_docs / answer 是 RAG 系统产出的结果。
五、计算一个简单的 Hit@k
Section titled “五、计算一个简单的 Hit@k”dataset = [ { "question": "多久内可以退款?", "gold_doc": "退款政策" }, { "question": "怎么获得证书?", "gold_doc": "证书说明" }]
predictions = [ { "retrieved_docs": ["退款政策", "学习顺序"] }, { "retrieved_docs": ["学习顺序", "证书说明"] }]
hits = 0for item, pred in zip(dataset, predictions): if item["gold_doc"] in pred["retrieved_docs"]: hits += 1
hit_at_2 = hits / len(dataset)print("Hit@2 =", round(hit_at_2, 4))预期输出:
Hit@2 = 1.0如果正确文档都在前 2 个结果里,这个值就是 1.0。
这个指标的局限
Section titled “这个指标的局限”它只能告诉你“有没有召回到”,却不能告诉你:
- 排在第几
- 回答是否真的正确
所以它只是第一步。
六、计算一个简单的答案正确率
Section titled “六、计算一个简单的答案正确率”最简单的精确匹配(Exact Match)思路
Section titled “最简单的精确匹配(Exact Match)思路”在结构化短答案场景里,可以先用最朴素的方法:
dataset = [ { "gold_answer": "课程购买后 7 天内可申请退款" }, { "gold_answer": "完成项目并通过测试后可获得证书" }]
predictions = [ { "answer": "课程购买后 7 天内可申请退款" }, { "answer": "完成项目并通过测试后可获得证书" }]
correct = 0for item, pred in zip(dataset, predictions): if item["gold_answer"] == pred["answer"]: correct += 1
exact_match = correct / len(dataset)print("Exact Match =", round(exact_match, 4))预期输出:
Exact Match = 1.0但真实场景往往没这么简单
Section titled “但真实场景往往没这么简单”因为同一个正确答案可能有很多不同表述方式。 所以线上系统常常还会引入:
- 语义匹配
- LLM-as-a-judge
- 人工抽检
七、忠实性:回答有没有根据?
Section titled “七、忠实性:回答有没有根据?”这比“答得像不像”更重要
Section titled “这比“答得像不像”更重要”一个回答可能写得很流畅,但如果它不是基于检索资料得出的,风险就很高。
一个简化版检查思路
Section titled “一个简化版检查思路”下面这个示例很粗糙,但能帮助你理解“回答是否被证据支持”的概念。
evidence = "课程购买后 7 天内可申请退款"answer = "课程购买后 7 天内可申请退款"
faithful = answer in evidence or evidence in answerprint("是否被证据支持:", faithful)预期输出:
是否被证据支持: True
真实系统里当然不会只用这种字符串判断,但思路是对的:
回答应该尽量能在检索证据里找到支撑。

八、评估集应该怎么构建?
Section titled “八、评估集应该怎么构建?”最小可用评估集
Section titled “最小可用评估集”至少包含:
- 用户问题
- 标准答案
- 正确证据文档或证据片段
评估集最好覆盖不同难度
Section titled “评估集最好覆盖不同难度”比如:
- 简单事实问答
- 同义表达问法
- 跨段落问题
- 容易混淆的问题
如果评估集太单一,优化结果很容易失真。
九、线上评估也很重要
Section titled “九、线上评估也很重要”离线评估不能代表全部
Section titled “离线评估不能代表全部”线下数据集再好,也不可能完全覆盖真实用户问题。
常见线上信号
Section titled “常见线上信号”例如:
- 用户追问率
- 用户纠错率
- 点赞 / 点踩
- 人工质检抽样
一个成熟的 RAG 系统,通常是“离线评估 + 线上反馈”一起看。
十、如果你的目标是“知识库驱动的 SOP 文档助手”,评估集应该多看什么?
Section titled “十、如果你的目标是“知识库驱动的 SOP 文档助手”,评估集应该多看什么?”这类项目和普通问答系统不太一样。 你不只是关心“答案像不像”,还要关心:
- 政策资料有没有找对
- 处理案例有没有抽对
- 清单和最终栏目有没有放对位置
- 来源能不能回溯
所以更适合这类项目的评估表,通常至少要多一层:
| 维度 | 更像在看什么 |
|---|---|
| 政策命中 | 这个主题的官方政策资料有没有找到 |
| 案例召回 | 适合支撑 SOP 的处理案例有没有找到 |
| 结构正确性 | 政策、案例、清单有没有放进对的栏目 |
| 来源完整性 | 最终生成结果能不能回溯到原始资料 |
你可以先把它理解成:
SOP 文档项目的评估,不只是“答对”,而是“找对、放对、引对”。
十一、一个更像 SOP 文档项目的最小评估样例
Section titled “十一、一个更像 SOP 文档项目的最小评估样例”dataset = [ { "topic": "退款升级", "gold_policies": ["重复扣费退款必须带交易证据升级处理。"], "gold_cases": ["失败结账后的重复扣款案例,应带支付证据升级给 billing。"], }]
prediction = { "policies": ["重复扣费退款必须带交易证据升级处理。"], "cases": ["失败结账后的重复扣款案例,应带支付证据升级给 billing。"], "source_refs": [{"doc_id": "refund_policy_001", "page_or_slide": 3}],}
print(dataset[0])print(prediction)预期输出:
{'topic': '退款升级', 'gold_policies': ['重复扣费退款必须带交易证据升级处理。'], 'gold_cases': ['失败结账后的重复扣款案例,应带支付证据升级给 billing。']}{'policies': ['重复扣费退款必须带交易证据升级处理。'], 'cases': ['失败结账后的重复扣款案例,应带支付证据升级给 billing。'], 'source_refs': [{'doc_id': 'refund_policy_001', 'page_or_slide': 3}]}这个例子虽然很小,但会帮助新人先建立一个评估直觉:
- 这类系统最终评估对象往往不是“单句答案”
- 而是一整个结构化结果
十二、初学者常见误区
Section titled “十二、初学者常见误区”只看一两个成功案例
Section titled “只看一两个成功案例”演示可以激励人,但不能代替评估。
只评回答,不评检索
Section titled “只评回答,不评检索”这样你很难定位问题究竟出在哪一层。
一边改系统,一边没固定评估集
Section titled “一边改系统,一边没固定评估集”没有固定评估集,就很难判断到底是优化还是随机波动。
RAG 项目评估指标总表
Section titled “RAG 项目评估指标总表”做 RAG 项目时,不要只看“回答像不像”。更稳的做法是把评估拆成检索、生成、引用和系统四层。
| 层级 | 指标 | 说明 |
|---|---|---|
| 检索层 | 命中率、Recall@K、MRR | 正确资料有没有被找出来,排得靠不靠前 |
| 生成层 | 答案正确率、完整性、一致性 | 模型有没有基于资料回答,是否遗漏关键条件 |
| 引用层 | 引用覆盖率、引用真实性 | 答案中的关键结论是否能追溯到来源 |
| 系统层 | 延迟、成本、失败率 | 能否稳定、可承受地服务真实用户 |
最小评估集建议先准备 20~50 个问题,每个问题都写上标准答案、应命中文档和关键引用。这样你优化 chunk、embedding、rerank、query rewrite 时,才知道是系统真的变好,还是只是个别样例看起来更顺眼。
分层失败归因表
Section titled “分层失败归因表”评估的价值不只是算一个总分,而是帮助你知道下一步该改哪里。下面这张表可以放在实验记录里,每次失败都先归因到一层。
| 失败现象 | 归因层级 | 应该检查 | 下一步动作 |
|---|---|---|---|
| 正确文档没有进入 top-k | 检索层 | 查询、chunk、embedding、关键词匹配 | 调整切块、加混合检索或 查询改写 |
| 正确文档进了 top-k 但没进最终 上下文 | 上下文层 | 上下文组装、去重、长度限制 | 调整排序、压缩或打包策略 |
| 上下文 里有证据但回答漏掉关键条件 | 生成层 | prompt、答案格式、模型是否按证据回答 | 要求逐条基于证据回答并保留限制条件 |
| 答案结论正确但引用不支持 | 引用层 | source_refs、引用片段、答案句子 | 做引用真实性检查,禁止无证据引用 |
| 离线评估好但用户仍频繁追问 | 产品层 | 真实问题分布、评估集覆盖度 | 补充线上问题到评估集 |
评估的价值不只是给一个总分,还要帮你知道下一步修哪里。下面这份清单适合放进实验记录里:每次失败先归因到一个层级,再决定动作。
- 检索层:正确文档没有进入 top-k。检查 query、chunk、embedding 和关键词匹配,再调整切块、加混合检索或做查询改写。
- 上下文层:正确文档进了 top-k,但没进最终上下文。检查上下文组装、去重和长度限制,再调整排序、压缩或打包策略。
- 生成层:上下文里有证据,但回答漏掉关键条件。检查 prompt、答案格式和模型是否按证据回答,再要求逐条基于证据回答并保留限制条件。
- 引用层:答案结论正确,但引用不支持。检查
source_refs、引用片段和答案句子,再做引用真实性检查,禁止无证据引用。 - 产品层:离线评估好,但用户仍频繁追问。检查真实问题分布和评估集覆盖度,再把线上问题补进评估集。
如果你只看“最终答对率”,这些问题会被混在一起。分层归因能让优化动作更明确:检索错就不要先调 prompt,引用错就不要只看答案是否通顺。
一个可直接复制的评估记录模板
Section titled “一个可直接复制的评估记录模板”做 RAG 项目时,建议每次评估都保留一份固定格式。即使一开始只有十几条问题,也比只看单次演示稳定得多。
| 字段 | 示例 | 用途 |
|---|---|---|
question | 课程多久内可以退款? | 用户问题 |
gold_doc | 退款政策 | 应该命中的资料 |
gold_answer | 课程购买后 7 天内可申请退款 | 标准答案或关键事实 |
retrieved_docs | 退款政策, 学习顺序 | 实际命中的文档 |
answer | 7 天内可申请退款 | 系统回答 |
citation_ok | true | 引用是否支持答案 |
failure_type | none / retrieval / generation / citation | 失败归因 |
notes | 命中正确,回答完整 | 人工备注 |
最小 CSV 可以长这样:
question,gold_doc,gold_answer,retrieved_docs,answer,citation_ok,failure_type,notes课程多久内可以退款?,退款政策,课程购买后 7 天内可申请退款,"退款政策;学习顺序",课程购买后 7 天内可申请退款,true,none,命中正确且引用支持怎么获得证书?,证书说明,完成项目并通过测试后可获得证书,"学习顺序;证书说明",完成项目后可获得证书,false,generation,漏掉通过测试这个关键条件这个模板的重点不是字段多,而是每条样本都能回答三个问题:应该命中什么,实际命中了什么,最终答案有没有被证据支持。
SOP 文档 RAG 的验收 Rubric
Section titled “SOP 文档 RAG 的验收 Rubric”如果项目目标是生成 SOP 文档或内部操作文档,评估不能只停留在问答层。下面这个 rubric 可以作为作品集项目的验收表。
- 练习级:能命中主题相关资料,生成基本回答或片段,并显示来源文件名。
- 项目级:能按 topic 和 content_type 召回政策、案例、清单,按固定 SOP 栏目组织输出,并给关键栏目标来源。
- 作品集级:有固定评估集和失败样本,能解释失败来自检索、生成还是模板,并能把关键结论逐条追溯到原文。
- 面试级:能比较基线、混合检索和 rerank,说明质量、成本、延迟取舍,并做引用真实性抽检和改进记录。
这个表可以直接放进项目 README。它会让别人看到:你不是只做了一个“能回答问题”的演示,而是在用工程方式评估一个知识库驱动系统。
学完这一页,至少保留这张证据卡:
- 查询
- 一个用户问题或测试用例
- 已检索分块
- 分块 ID、分数和来源标题
- 答案
- 带引用或来源说明的最终回答
- 失败检查
- 缺少证据、切分错误、文档过时或论断无依据
- 下一步动作
- 分块、embedding、重排、Prompt 或评估改动
这一节最重要的认识是:
RAG 评估不是锦上添花,而是系统迭代的方向盘。
没有评估,你就只能凭感觉优化; 有了评估,你才能知道问题在哪、改动有没有真正带来收益。
- 给评估集再加 3 条问题,自己手工写出
gold_doc和gold_answer。 - 修改
predictions,故意让一条回答错误,重新计算 Hit@k 和 Exact Match。 - 想一想:如果 Hit@k 很高,但最终答案依然经常错,说明问题更可能出在哪一层?
参考实现与讲解
- 好的评估问题应包含直接查找、同义改写、权限敏感场景,以及至少一个容易混淆的近似匹配。
gold_doc和gold_answer应在看模型输出前先写好。 - Hit@k 衡量是否检索到正确证据;Exact Match 衡量最终答案是否符合预期。故意写错答案时,即使检索仍正确,回答指标也应下降。
- Hit@k 高但答案错,通常说明问题更可能在生成、context packing、引用或 answer verification 层,而不是第一阶段 retriever。