RAGAS 评测:怎么知道 RAG 答得好不好
光看答案对不对,分不清是检索的问题还是模型的问题。RAGAS 的真正价值不是给一个分数,而是把这两层拆开——它要你提供检索片段,所以能定位是哪一环的锅。这篇讲透指标分类、四分支诊断、修法和工具的边界。
「RAG 效果好不好」这个问题,最容易得到的回答是「用户反馈还行」或者「感觉答得挺准的」。
但更麻烦的是另一种情况:真的去看了答案,发现有几个答错了,这时候你依然不知道该改哪里——是检索没召回,还是模型没用好?只看最终答案,这两个问题是混在一起的。
光看答案对不对,分不清是检索的问题还是模型的问题。
RAGAS 的价值恰好在这里:它要你提供检索到的片段,拿到这个中间产物之后,它就能把一条链路拆成两段分别打分。
一、指标分三类
RAGAS 的指标体系可以按「测哪一层」分成三组:
| 类别 | 指标 | 测什么 | 要不要标准答案 |
|---|---|---|---|
| 检索质量 | Context Precision | 相关的有没有排在前面(排序质量) | 不要 |
| Context Recall | 该召回的有没有全召回来 | 要 | |
| Noise Sensitivity | 会不会被无关片段带偏 | 不要 | |
| 生成质量 | Faithfulness | 答案是不是完全基于检索内容(不无中生有) | 不要 |
| Response Relevancy | 答案有没有答到点上 | 不要 | |
| Factual Correctness | 和参考答案的事实一致性 | 要 | |
| 自定义 | Aspect Critic | 自定义一个维度,让 LLM 判是/否 | 看定义 |
| Rubrics Based Scoring | 自定义评分标准 | 看定义 |
两个指标值得单独解释:
Faithfulness(忠实度) 是 RAG 最核心的生成侧指标。它的算法是:把答案拆成若干断言,逐条检查是否被 contexts 支持。所有断言都能在检索片段里找到依据,分数就高;出现片段里没有的信息,分数就掉。它衡量的不是「答案对不对」,而是「答案有没有超出给定资料」。
Context Precision / Recall 是一对。Precision 看排序——相关的片段有没有排在前面;Recall 看覆盖——回答所需的关键信息有没有被完整召回来。
一个实用前提:有参考 vs 无参考
上表最后一列很重要,它决定了哪些指标能全量跑线上数据:
| 无参考指标 | 有参考指标 | |
|---|---|---|
| 代表 | Faithfulness、Response Relevancy | Context Recall、Factual Correctness |
| 需要标准答案 | 不需要 | 需要 |
| 能跑什么数据 | 可以全量跑线上真实流量 | 只能跑有标注的评测集 |
| 建设成本 | 低 | 高(要人工写标准答案) |
这个区别直接决定了评测方案的成本结构:忠实度和答案相关性可以做成常态化的线上监控,而 Context Recall 这类只能定期在评测集上跑。 如果一上来就给所有指标都准备标准答案,评测集的维护成本会高到无法持续。
二、核心:它能定位是哪一环的锅
RAGAS 要你提供四样东西:
question 用户问的
answer 模型答的
contexts ★ 检索到的片段(关键)
ground_truth 参考答案(可选,Context Recall 需要)
关键是有 contexts。正是因为拿到了检索片段,才能把「检索」和「生成」这两层拆开打分:
| 现象 | 哪个指标低 | 是哪一环的锅 |
|---|---|---|
| 答案里有资料没有的信息 | Faithfulness 低 | 生成侧:模型在编 |
| 答案答非所问 | Response Relevancy 低 | 生成侧:跑题了 |
| 该召回的没召回 | Context Recall 低 | 检索侧 |
| 相关的排在很后面 | Context Precision 低 | 排序的锅(融合 / 重排没调好) |
| 被无关片段带偏 | Noise Sensitivity 高 | 检索噪声 |
Context Recall 低,就是检索没召回;Context Recall 高但 Faithfulness 低,就是召回了但模型没用。
这两句话是整套评测方法的支点:
Context Recall
低 高
┌──────────────┬──────────────┐
Faithful │ ④ 资料里没有 │ ③ 资料里有 │
低 │ 模型硬答 │ 模型没用上 │
│ → 拒答策略 │ → Prompt │
├──────────────┼──────────────┤
Faithful │ ① 检索有问题 │ ② 健康 │
高 │ (但答案碰巧 │ │
│ 对/没作答) │ │
└──────────────┴──────────────┘
左上角那一格要特别注意——它是个陷阱,后面会单独讲。
诊断速查表
| 症状 | 哪个指标低 | 该修哪里 |
|---|---|---|
| 回答里有资料里没有的内容 | Faithfulness | Prompt 约束 / 生成环节 |
| 答非所问、答了别的商品 | Response Relevancy | 查询改写 / 意图识别 |
| 回答被无关信息干扰 | Context Precision | 重排 / TopK / 元数据过滤 |
| 该说的没说、漏了政策 | Context Recall | 切片策略 / 召回 TopK |
一句口诀概括这四行:Faith 低 → 生成在编;Rel 低 → 问错了方向;Pre 低 → 捞多了;Rec 低 → 捞少了。
三、诊断出来之后怎么修
知道是哪一环出问题只是第一步,真正的功夫在修法上。这里最容易犯的错误是把它当成两个分支——「检索的问题」和「模型的问题」。实际上它有四个分支,因为 Faithfulness 低有两种完全不同的成因:
| 指标表现 | 症状 | 本质 | 修哪一层 |
|---|---|---|---|
| Recall 低 | 该召回的没回来 | 漏了 | 切片 / TopK / 召回方式 |
| Precision 低 | 召回了,但混一堆无关的 | 噪声多 | 排序 / 过滤 |
| Faith 低(Recall 正常) | 资料里有,模型没用 | 没用上 | Prompt / 上下文组织 |
| Faith 低(Recall 也低) | 资料里没有,模型硬答 | 该拒答 | 拒答策略 |
最后一行是最容易误判的一格:如果 Recall 和 Faithfulness 同时低,那不是「模型没用」,而是「模型在用自己脑子里的东西」。这时候去调 Prompt 是无效的——修的方向是先修召回;如果知识库里确实没有这个信息,那问题就落在拒答策略上。
分支一:检索没做好
① 先确认「知识库里到底有没有」——最容易跳过的一步
这一步不查,后面全是白忙。
| 要查什么 | 常见问题 |
|---|---|
| 文档入库了吗 | 上传了但解析失败,压根没进向量库 |
| 解析对不对 | PDF 里的表格没解析出来 → 参数类问题必然召不回 |
| 是不是被切碎了 | 答案跨在两个 chunk 中间,两边都不完整 |
| 元数据对不对 | source_type 打错了 → 路由到错的库 |
② 切片策略(Recall 低的主因)
| 问题 | 症状 | 修法 |
|---|---|---|
| chunk 太小 | 一句话被切断,语义不完整 | 按结构切(标题层级、表格行),别按固定长度切 |
| chunk 太大 | 一条里塞了好几个主题,检索粒度粗 | 缩到 300~500 token |
| overlap 不够 | 答案正好落在切口上 | overlap 设 10%~15% |
| 表格没处理 | 「X30 吸力多少」召不回 | 表格转成「型号 + 参数 + 数值」文本 |
③ TopK 太小
召回是天花板,K 太小后面再准也救不回来。 调大 K,让 Rerank 去筛。
④ 检索方式太单一
只用向量会漏精确匹配(型号「H20」);只用 BM25 会漏同义表达(「噪音小」vs「静音」)。上混合召回。
⑤ 查询改写
「它多少钱」这类代词没还原,检索直接跑偏。
⑥ 换 Embedding 模型
通用模型对领域术语理解差。但这是最贵的一招,放最后。
分支一之下的另一类:Precision 低(噪声多)
| 手段 | 怎么做 |
|---|---|
| TopK 调小 | 别一次召回 100 条 |
| 加强 Rerank | 检查 Rerank 有没有真生效、候选数对不对 |
| 元数据过滤 | 检索前先缩小范围,比事后重排更有效 |
| 调 RRF 的 k 值 | k 越小越信任头部排名 |
| 切片粒度 | 大 chunk 天然带噪声 |
分支二:模型没用(Recall 正常但 Faithfulness 低)
按成本从低到高。
① Prompt 约束(最便宜,先试)
| 手段 | 怎么写 |
|---|---|
| 限定范围 | 「只基于下面提供的资料回答」 |
| 明确拒答 | 「资料中没有的信息,直接说不知道,不要推测」 |
| 强制引用 | 「每句话后面标注来源编号 [1][2]」 |
| 位置 | 约束写在系统提示里,不是用户消息里 |
强制引用是最好用的一招——它同时干两件事:逼模型看资料 + 出问题能溯源。
② 上下文组织(免费,但最容易忽略)
| 问题 | 修法 |
|---|---|
| 塞太多 | 精排后只留 5~8 条,多了注意力被稀释 |
| 关键信息在中间 | 模型对开头和结尾利用最好,中间容易忽略(lost in the middle)→ 最相关的放开头 |
| 片段没编号 | 加 [1][2] 编号 + 来源标题,模型好引用 |
| 片段有冲突 | 召回的几条互相矛盾 → Prompt 里说明「以更具体 / 更新的为准」 |
③ 降低 temperature
减少自由发挥。这一条见效快但上限低,它压的是随机性,压不住模型「过度自信地编」。
④ 后置校验(工程手段)
把答案里的关键实体 / 数字抽出来
→ 检查是否都在 contexts 里出现过
→ 不在 → 打回重生成,或降级为「这个我不太确定」
这叫 grounding check,是防幻觉的最后一道闸。它不依赖模型的自觉,而是用规则做确定性校验——这一点比前三条都可靠。
⑤ 换更强的模型
小模型遵循指令能力弱,容易忽略约束。但这是最后手段。
通用原则:从便宜到贵
把这五个分支的修法按成本排一下,会得到一个很清晰的排查顺序:
① 先查数据 知识库里有没有 ← 0 成本,但最容易跳过
② 再调配置 切片 / TopK / 过滤 ← 改配置
③ 再改 Prompt 约束 / 组织方式 ← 改文本
④ 最后换模型 换 embedding / 换 LLM ← 最贵
很多人的第一反应是「换个更强的模型」——这是最贵的做法,而且往往不是根因。先查最便宜的那一环。
这个顺序背后的判断是:代价递增的排查路径,能在最早的位置定位到根因。数据层的问题(解析失败、表格丢失、切碎了)在模型层是完全看不出来的,换多少次模型都不会好。
四、改完怎么验证
不能凭感觉说「好像好点了」。方法是:
改之前 → 跑评测集,记录四个指标
改之后 → 跑同一个评测集,对比
而且要盯对指标:
| 你改了什么 | 该看哪个指标涨 |
|---|---|
| 切片 / TopK / 召回方式 | Context Recall |
| Rerank / 过滤 | Context Precision |
| Prompt / 上下文组织 | Faithfulness |
改 A 看 B 是白改——这也是「分开看」的意义。
举个具体的例子:把切片粒度从 200 字改到 500 字,召回率上去了,但 Faithfulness 可能一点没变。这时候如果只盯着忠实度看,会得出「这个改动没用」的错误结论;实际上它已经在检索层生效了,只是生成层的忠实度本来就不是瓶颈。
五、RAGAS 给不了的指标:拒答准确率
这是防幻觉最关键的一环,但 RAGAS 没有现成的指标。
原因在 Faithfulness 的算法里:它把答案拆成断言,逐条检查是否被 contexts 支持。那么当模型正确拒答时:
答案:「抱歉,这个我不确定,建议您咨询人工客服」
拆出来的断言:几乎没有(没有事实性断言)
→ Faithfulness 返回 NaN 或无意义的值
所以:
Faithfulness 高,可能是「老实回答了」,也可能是「什么都没说」——它区分不了这两种。
这意味着**「不硬答」这个能力,在 RAGAS 的指标体系里是测不出来的**。而它恰恰是很多业务场景里最重要的能力——编一个订单号、编一个赔付比例,代价远大于说一句「我不确定」。
解决办法是用 Aspect Critic 自定义一个维度:
criteria = (
"当提供的资料不足以回答问题时,"
"助手是否明确表示无法回答,而不是编造答案?"
)
# → 让 LLM 判 yes / no
同时还要专门准备一批无答案题(知识库里根本没有答案的问题)来测这批案例——这一点后面还会提到,因为合成评测集有一个天然的盲区。
六、RAGAS 的三个局限
用任何 LLM 评测框架之前,先知道它的边界在哪:
| 局限 | 说明 | 应对 |
|---|---|---|
| ① 它是「LLM 当裁判」 | 裁判自己也有偏差,换个裁判模型分数可能差 10 分 | 固定裁判模型和版本;关键结论人工抽检核对 |
| ② 有成本 | 每个样本要多次调用 LLM(拆断言、逐条验证) | 评测集控制规模;只有无参考指标才全量跑 |
| ③ ground truth 不好凑 | Context Recall 要参考答案,参考答案又得人来定 | 用 RAGAS 的 Test Data Generation 从知识库合成一批,再人工筛 |
第 ③ 条顺带解决了「评测集从哪来」的问题——RAGAS 能从知识库文档自动生成测试问题和参考答案,不用全靠人编。
但要注意一个盲区:合成的问题是从文档生成的,所以它不会包含「无答案题」。专门测「会不会硬答」的那批题,还得人工设计。 这也是很多团队评测分数很好看、线上却频繁编造的原因——评测集里压根没有「该拒答」的样本。
七、评测集从哪来
真实可维护的评测集通常来自三个渠道:
| 来源 | 说明 |
|---|---|
| 合成 | RAGAS Test Data Generation 从知识库生成,人工筛 |
| 人工标 | 挑真实线上会话,人工写标准答案;规模不用大,几十到几百条就够做回归 |
| badcase 回流 | 线上出问题的 case 补进评测集,所以评测集是持续长大的 |
第二点的规模感很重要:评测集不是越大越好,几十到几百条的、标注质量可靠的集合,就能支撑起一个有效的回归体系。难的不是数量,是持续维护。
八、工程化:把评测变成回归测试
指标会算只是第一步,真正产生价值的是把它接进迭代流程:
| 步骤 | 做什么 |
|---|---|
| ① 构建黄金测试集 | 问题 + 标准答案 + 应命中文档的三元组,作为评测基准 |
| ② 分阶段评测 | 先单独评检索模块(看 Context Precision / Recall),再评生成模块(看 Faithfulness / Response Relevancy),这样才能定位瓶颈 |
| ③ 引入生产指标 | 除质量外还要监控延迟、Token 消耗、工具调用次数;Agentic RAG 还要额外看工具选择准确性和每请求的调用轮数 |
| ④ 持续回归 | 集成到 CI/CD,每次改切块策略、嵌入模型或 Prompt 后自动跑,防止性能倒退 |
第 ② 步「分阶段评测」是关键——它和前面「把两层拆开」是同一个思路的工程化落地。如果只跑端到端的总分,那么任何一次改动导致的分数波动,都无法归因到具体环节。
除了离线的评测集,线上还要看几个行为指标,它们能反映评测集覆盖不到的问题:
- 点踩率:负反馈的直接来源
- 人工接管率:AI 独立没能解决、需要人工介入的问题占比
- 会话轮次:如果用户反复就同一件事发问,通常说明第一次没答好
- 重复询问率:同一个问题被再次提出的比例,是上面这个信号的细粒度版本
这些 badcase 回流到评测集,评测集就持续长大了。
九、关于离线分数的四个常见误区
| 误区 | 实际情况 |
|---|---|
| 指标跑得越多越好 | Context Recall / Precision(检索)+ Faithfulness(生成)+ 自定义拒答指标是核心;其余按场景增补,跑多了只是徒增 LLM 调用成本 |
| 评测集靠人编就够了 | 合成 + 人工标 + badcase 回流三条腿都要;合成的部分不包含无答案题 |
| 裁判模型打的分可以直接信 | LLM 当裁判本身有偏差;固定裁判模型和版本,关键结论人工抽检核对 |
| 分数涨 5 个点就能上线 | 不能——离线分涨了线上不一定变好。 评测集是人工挑的,可能不覆盖线上真实分布,必须看线上指标同步验证 |
最后一条尤其容易被忽略:离线评测集天然是有偏的——它由团队自己构造,覆盖的是团队认为重要的场景,而不是线上真实的问题分布。所以离线分数只是「没有倒退」的证据,不是「线上会变好」的证据。上线决策必须结合线上的行为指标。
小结
- RAGAS 的指标分三类:检索质量、生成质量、自定义
- Faithfulness / Response Relevancy 是无参考指标,可以全量跑线上数据;Context Recall 需要标准答案,只能跑评测集
- 核心价值是定位是哪一环的锅:Context Recall 低就是检索没召回;Recall 高但 Faithfulness 低,就是召回了但模型没用
- 诊断有四个分支,不是两个:漏了、噪声多、没用上、该拒答——Recall 和 Faithfulness 同时低时,修的是召回和拒答策略,而不是 Prompt
- 修法遵循从便宜到贵:先查数据 → 再调配置 → 再改 Prompt → 最后才换模型
- 改完必须跑同一个评测集对比,并盯对指标——改召回看 Recall,改 Prompt 看 Faithfulness
- RAGAS 没有拒答准确率:正确拒答时 Faithfulness 会返回 NaN,「不硬答」这个能力要靠 Aspect Critic 自定义维度来测
- 工具的局限要心里有数:LLM 当裁判有偏差、评测有成本、合成评测集不包含无答案题
- 评测集来自合成 + 人工标 + badcase 回流,几十到几百条就够做回归,关键是持续维护
- 工程化的目标是把评测变成 CI/CD 里的回归测试,并且离线分数不能直接当作上线依据
评测这件事最反直觉的地方在于:它的价值不在于给出一个好看的分数,而在于当分数掉下去的时候,你能立刻知道该动哪里。 一个能拆开归因的 70 分,比一个说不清来源的 90 分有用得多。
留下点什么
评论基于 GitHub Discussions(giscus)。在项目根目录配置.env.local填入 NEXT_PUBLIC_GISCUS_* 四个变量后自动开启。