RAG评测从0到1:用Ragas搭一套能拦BUG的评测集,别再靠眼睛看回答
大多数团队的RAG上线流程是:改一版prompt、随手问三个问题、觉得还行就发。本文用Ragas拆出检索与生成的四个关键指标,讲清怎么构造测试集、怎么定阈值,以及为什么 faithfulness 高不等于好用。
RAG项目最危险的阶段不是开发,而是“看起来能跑”。用户问一句,模型答得挺像样,于是大家就信了。上线两周后发现:答案里混着不存在的条款、引用编号对不上、多跳问题全靠猜。
问题不在模型,在你根本没有度量。
先分清两件事:检索错还是生成错
RAG的BAD case只有两种来源:
- 检索没给到:正确片段不在召回结果里,模型再强也答不出。
- 生成没用上:片段在上下文里,模型还是编了。
不分清这两类,你的优化全是赌博。改prompt可能救不了检索漏召,换向量库也救不了模型不忠于原文。
Ragas的价值就是把这四件事分开算:
| 指标 | 回答什么问题 | 归因 |
|---|---|---|
context_recall | 标准答案的要点是否被召回 | 检索 |
context_precision | 召回内容里有多少是噪声 | 检索 |
faithfulness | 答案的每句陈述能否在上下文中找到依据 | 生成 |
answer_relevancy | 答案是否真的回应了问题 | 生成 |
构造测试集的正确姿势
不要让模型想问题——它会问得很规整、很像教科书,而真实用户不会。
正确做法是从真实查询日志里抽样。抽50~100条,按场景分层:
- 单跳事实题(占比应最高,这是及格线)
- 多跳组合题(“A产品在某地区的退货政策,和B产品有什么不同”)
- 拒答题(“你们支持比特币付款吗”,答案是不知道,应该明确说没有)
- 指代与错别字题(真实用户的输入从来不干净)
每道题标注 ground_truth 和 reference_contexts。这一步最费人力,但这100条质量决定你后面半年所有优化的可信度。
只想快速起步的话,可以用Ragas的 TestsetGenerator 从文档自动生成初版,然后人工筛掉“太像AI出的”题,再手工补10%的难例。自动生成负责广度,人工补的负责深度。
第一次跑,大概率是这样
faithfulness: 0.91 ← 看起来很棒
answer_relevancy: 0.86
context_precision: 0.42 ← 真实问题
context_recall: 0.58 ← 真实问题
这个组合非常典型:模型很乖,不乱编,但检索召回了一半都不到。 于是答案“忠于一个残缺的上下文”——听起来通顺,其实缺关键信息。
如果只看 faithfulness,你会得出“RAG效果不错”的错误结论,然后被用户打脸。
阈值怎么定
别抄别人的数字。用人工标注的20条好答案和20条坏答案反推:看模型打分在这两组上的分布,取能最大化区分度的切点。多数场景下 faithfulness 的可用阈值在0.85左右,context_recall 在0.7左右,但你的语料决定你的数字。
更关键的是:设定回归门禁。把评测脚本挂进CI,PR改动涉及prompt、切分策略、embedding模型时自动跑,任一核心指标跌超3个点就阻断合并。没有门禁的评测,三个月后一定没人跑。
别掉进去的三个坑
- 把LLM当裁判就完事:裁判模型也会偏爱长答案和啰嗦表述。写清评分rubric,并要求它先引用证据再打分。
- 测试集一成不变:语料库更新,测试集不更新,你测的就是一个不存在的系统。每季度从新日志补20条。
- 只测准确率不测成本:召回top-k从5调到20,recall涨了8个点,但token成本翻三倍、延迟涨一倍——这在评测报告里必须能看到。
RAG不是一个能“调好”的东西,它是一条需要持续度量的流水线。评测集就是你唯一的方向盘。