跳到主要内容

RAG 评估

学习目标

完成本节后,你将能够:

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

一、为什么 RAG 特别需要评估?

1.1 因为它不是单一模块

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

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

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

1.2 所以不能只问“答对了吗”

你还得问:

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

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


二、第一层:检索评估

2.1 最常见的直觉指标:Hit@k

Hit@k 的意思很简单:

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

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

2.2 为什么这个指标很重要?

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

所以:

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


三、第二层:回答评估

3.1 只看“语句通顺”远远不够

回答评估至少要关注:

  • 答案对不对
  • 有没有依据
  • 有没有胡编

3.2 常见维度

维度关注点
Correctness答案事实是否正确
Faithfulness是否基于给定资料
Relevance是否回答了用户问题
Completeness关键信息是否答全

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


四、一个最小评估数据集

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

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

predictions = [
{
"retrieved_docs": ["退款政策", "学习顺序"],
"answer": "课程购买后 7 天内可申请退款"
},
{
"retrieved_docs": ["学习顺序", "证书说明"],
"answer": "完成项目并通过测试后可获得证书"
}
]

print(dataset)
print(predictions)

五、计算一个简单的 Hit@k

5.1 可运行示例

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))

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

5.2 这个指标的局限

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

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

所以它只是第一步。


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

6.1 最简单的 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))

6.2 但真实场景往往没这么简单

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

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

七、Faithfulness:回答有没有根据?

7.1 这比“答得像不像”更重要

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

7.2 一个简化版检查思路

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

evidence = "课程购买后 7 天内可申请退款"
answer = "课程购买后 7 天内可申请退款"

faithful = answer in evidence or evidence in answer
print("是否被证据支持:", faithful)

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

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


八、评估集应该怎么构建?

8.1 最小可用评估集

至少包含:

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

8.2 评估集最好覆盖不同难度

比如:

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

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


九、线上评估也很重要

9.1 离线评估不能代表全部

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

9.2 常见线上信号

例如:

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

一个成熟的 RAG 系统,通常是“离线评估 + 线上反馈”一起看。


十、初学者常见误区

10.1 只看一两个成功案例

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

10.2 只评回答,不评检索

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

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

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


小结

这一节最重要的认识是:

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

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


练习

  1. 给评估集再加 3 条问题,自己手工写出 gold_docgold_answer
  2. 修改 predictions,故意让一条回答错误,重新计算 Hit@k 和 Exact Match。
  3. 想一想:如果 Hit@k 很高,但最终答案依然经常错,说明问题更可能出在哪一层?