跳转到内容

8.1.8 RAG 评估

RAG 评估三角图

完成本节后,你将能够:

  • 理解为什么 RAG 不能只凭单次演示判断好坏
  • 分清检索评估和回答评估的不同目标
  • 使用一个小型样例计算简单指标
  • 建立“先做评估,再做优化”的工程习惯

RAG 不是单个模型,而是至少包含:

  1. 文档处理
  2. 检索
  3. 上下文拼装
  4. 生成回答

任何一环出错,最终答案都可能变差。

你还得问:

  • 是没检索到?
  • 还是检索到了但没用好?
  • 还是回答语言组织不好?

这就是为什么 RAG 评估必须分层看。


Hit@k 的意思很简单:

正确证据有没有出现在前 k 个检索结果里?

如果用户问题的正确证据在 top-3 里,就算 hit。

因为如果正确资料根本没召回,后面的生成几乎不可能稳定答对。

所以:

检索评估是 RAG 评估的地基。


回答评估至少要关注:

  • 答案对不对
  • 有没有依据
  • 有没有胡编
维度关注点
正确性答案事实是否正确
忠实性是否基于给定资料
相关性是否回答了用户问题
完整性关键信息是否答全

在业务里,不同维度的重要性不一样。

RAG 分层评估仪表盘图

RAG 评估闭环图

好的评估不是做一次就完,而是一个循环:测试集 -> 检索 -> 回答 -> 引用 -> 分析失败 -> 修正 -> 再评估。


下面我们手工构造一份迷你评估集。

dataset = [
{
"question": "多久内可以退款?",
"gold_doc": "退款政策",
"gold_answer": "课程购买后 7 天内可申请退款"
},
{
"question": "怎么获得证书?",
"gold_doc": "证书说明",
"gold_answer": "完成项目并通过测试后可获得证书"
}
]
predictions = [
{
"retrieved_docs": ["退款政策", "学习顺序"],
"answer": "课程购买后 7 天内可申请退款"
},
{
"retrieved_docs": ["学习顺序", "证书说明"],
"answer": "完成项目并通过测试后可获得证书"
}
]
print(dataset)
print(predictions)

预期输出:

Terminal window
[{'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 系统产出的结果。


dataset = [
{
"question": "多久内可以退款?",
"gold_doc": "退款政策"
},
{
"question": "怎么获得证书?",
"gold_doc": "证书说明"
}
]
predictions = [
{
"retrieved_docs": ["退款政策", "学习顺序"]
},
{
"retrieved_docs": ["学习顺序", "证书说明"]
}
]
hits = 0
for 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))

预期输出:

Terminal window
Hit@2 = 1.0

如果正确文档都在前 2 个结果里,这个值就是 1.0

它只能告诉你“有没有召回到”,却不能告诉你:

  • 排在第几
  • 回答是否真的正确

所以它只是第一步。


六、计算一个简单的答案正确率

Section titled “六、计算一个简单的答案正确率”

最简单的精确匹配(Exact Match)思路

Section titled “最简单的精确匹配(Exact Match)思路”

在结构化短答案场景里,可以先用最朴素的方法:

dataset = [
{
"gold_answer": "课程购买后 7 天内可申请退款"
},
{
"gold_answer": "完成项目并通过测试后可获得证书"
}
]
predictions = [
{
"answer": "课程购买后 7 天内可申请退款"
},
{
"answer": "完成项目并通过测试后可获得证书"
}
]
correct = 0
for 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))

预期输出:

Terminal window
Exact Match = 1.0

因为同一个正确答案可能有很多不同表述方式。 所以线上系统常常还会引入:

  • 语义匹配
  • LLM-as-a-judge
  • 人工抽检

七、忠实性:回答有没有根据?

Section titled “七、忠实性:回答有没有根据?”

一个回答可能写得很流畅,但如果它不是基于检索资料得出的,风险就很高。

下面这个示例很粗糙,但能帮助你理解“回答是否被证据支持”的概念。

evidence = "课程购买后 7 天内可申请退款"
answer = "课程购买后 7 天内可申请退款"
faithful = answer in evidence or evidence in answer
print("是否被证据支持:", faithful)

预期输出:

Terminal window
是否被证据支持: True

RAG 评估实验结果图

真实系统里当然不会只用这种字符串判断,但思路是对的:

回答应该尽量能在检索证据里找到支撑。

忠实度 与引用真实性检查图


至少包含:

  • 用户问题
  • 标准答案
  • 正确证据文档或证据片段

比如:

  • 简单事实问答
  • 同义表达问法
  • 跨段落问题
  • 容易混淆的问题

如果评估集太单一,优化结果很容易失真。


线下数据集再好,也不可能完全覆盖真实用户问题。

例如:

  • 用户追问率
  • 用户纠错率
  • 点赞 / 点踩
  • 人工质检抽样

一个成熟的 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)

预期输出:

Terminal window
{'topic': '退款升级', 'gold_policies': ['重复扣费退款必须带交易证据升级处理。'], 'gold_cases': ['失败结账后的重复扣款案例,应带支付证据升级给 billing。']}
{'policies': ['重复扣费退款必须带交易证据升级处理。'], 'cases': ['失败结账后的重复扣款案例,应带支付证据升级给 billing。'], 'source_refs': [{'doc_id': 'refund_policy_001', 'page_or_slide': 3}]}

这个例子虽然很小,但会帮助新人先建立一个评估直觉:

  • 这类系统最终评估对象往往不是“单句答案”
  • 而是一整个结构化结果

演示可以激励人,但不能代替评估。

这样你很难定位问题究竟出在哪一层。

一边改系统,一边没固定评估集

Section titled “一边改系统,一边没固定评估集”

没有固定评估集,就很难判断到底是优化还是随机波动。


做 RAG 项目时,不要只看“回答像不像”。更稳的做法是把评估拆成检索、生成、引用和系统四层。

层级指标说明
检索层命中率、Recall@K、MRR正确资料有没有被找出来,排得靠不靠前
生成层答案正确率、完整性、一致性模型有没有基于资料回答,是否遗漏关键条件
引用层引用覆盖率、引用真实性答案中的关键结论是否能追溯到来源
系统层延迟、成本、失败率能否稳定、可承受地服务真实用户

最小评估集建议先准备 20~50 个问题,每个问题都写上标准答案、应命中文档和关键引用。这样你优化 chunk、embedding、rerank、query rewrite 时,才知道是系统真的变好,还是只是个别样例看起来更顺眼。

评估的价值不只是算一个总分,而是帮助你知道下一步该改哪里。下面这张表可以放在实验记录里,每次失败都先归因到一层。

失败现象归因层级应该检查下一步动作
正确文档没有进入 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退款政策, 学习顺序实际命中的文档
answer7 天内可申请退款系统回答
citation_oktrue引用是否支持答案
failure_typenone / 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 文档或内部操作文档,评估不能只停留在问答层。下面这个 rubric 可以作为作品集项目的验收表。

  • 练习级:能命中主题相关资料,生成基本回答或片段,并显示来源文件名。
  • 项目级:能按 topic 和 content_type 召回政策、案例、清单,按固定 SOP 栏目组织输出,并给关键栏目标来源。
  • 作品集级:有固定评估集和失败样本,能解释失败来自检索、生成还是模板,并能把关键结论逐条追溯到原文。
  • 面试级:能比较基线、混合检索和 rerank,说明质量、成本、延迟取舍,并做引用真实性抽检和改进记录。

这个表可以直接放进项目 README。它会让别人看到:你不是只做了一个“能回答问题”的演示,而是在用工程方式评估一个知识库驱动系统。


学完这一页,至少保留这张证据卡:

查询
一个用户问题或测试用例
已检索分块
分块 ID、分数和来源标题
答案
带引用或来源说明的最终回答
失败检查
缺少证据、切分错误、文档过时或论断无依据
下一步动作
分块、embedding、重排、Prompt 或评估改动

这一节最重要的认识是:

RAG 评估不是锦上添花,而是系统迭代的方向盘。

没有评估,你就只能凭感觉优化; 有了评估,你才能知道问题在哪、改动有没有真正带来收益。


  1. 给评估集再加 3 条问题,自己手工写出 gold_docgold_answer
  2. 修改 predictions,故意让一条回答错误,重新计算 Hit@k 和 Exact Match。
  3. 想一想:如果 Hit@k 很高,但最终答案依然经常错,说明问题更可能出在哪一层?
参考实现与讲解
  1. 好的评估问题应包含直接查找、同义改写、权限敏感场景,以及至少一个容易混淆的近似匹配。gold_docgold_answer 应在看模型输出前先写好。
  2. Hit@k 衡量是否检索到正确证据;Exact Match 衡量最终答案是否符合预期。故意写错答案时,即使检索仍正确,回答指标也应下降。
  3. Hit@k 高但答案错,通常说明问题更可能在生成、context packing、引用或 answer verification 层,而不是第一阶段 retriever。