评测 RAG
把检索和生成分开测。大多数 RAG 失败是检索失败,而一个笼统的质量分掩盖了坏的是哪一半。
一个检索增强生成(RAG)系统有两个各自独立出错的一半。检索负责找到段落,生成负责根据它们作答。
一个端到端的质量分告诉不了你坏的是哪一半——而这恰恰是你唯一需要知道的,因为两半的修法毫无共同之处。
分开测。 RAG 评测里的其他一切,都从这一条推出来。
先测检索
有一个数字比其余所有都重要:对一个已知答案的真实问题,正确的段落有没有出现在检索结果里?
如果没有,生成就无从谈起。改 prompt、换更好的模型、加重排序,都救不了一段从来没被检索到的文字。RAG 的失败大多属于这一类,先查它能省掉巨大的无用功。
常用指标:
召回率@k(recall@k)——正确段落出现在前 k 条里的问题占比。这是头号指标。
MRR(平均倒数排名)——把第一篇正确段落的排名的倒数取平均。它奖励把正确段落排得靠前,这很重要,因为注意力在长上下文里分布不均。
nDCG——当段落是「部分有用」而不是简单的对错时,它能把分级的相关性考虑进去。
真正的工作量在于造数据集。收集真实问题,然后标注哪些段落真的含有答案。一百个标注过的问题就足够有用了,一个下午就能做完。
有个捷径值得知道:拿一段文本,让模型生成一个它能回答的问题,把这个对子记下来。这样能便宜地造出大规模合成数据集。它的偏向是问题都长得像原文段落,所以会高估表现——但比起完全不测,它好得多,而且能抓住明显的回归。
生成单独测
给定正确的段落,模型答对了吗?
三个属性,各自会以不同方式出问题:
忠实度。 每一个论断都有提供的上下文支撑吗?有上下文却出现无支撑的论断,就是幻觉——通常是 prompt 的问题。
相关性。 答案是不是在回答所问的问题?忠实但答非所问,依然是错的。
完整性。 它用上了全部相关的检索信息,还是丢了一半?埋在下文中部的材料通常就是会丢掉的那部分。
这里有个好用的诊断方法:手工喂入已知正确的段落,只跑生成。这样就把生成质量和检索质量彻底隔离开,也是判断你在调哪一半的最快办法。
给生成打分
模型裁判是任何规模下最实际的选择。把问题、上下文和答案一起发过去,问每一个论断是否有支撑。
忠实度格外适合交给它,因为这是针对给定文本的核验任务,而不是对质量的评判。裁判在检查的是能否推出,不是品味,而这类事模型做得很可靠。
那些关于裁判的注意事项依然适用:先在样本上对照人工标注验证一遍;比较两个系统时,优先用两两对比,而不是绝对分数。
论断拆解能提升忠实度的打分质量。把答案拆成一条条独立的论断,逐条对照上下文检查,再报告有支撑的比例。这比整段评判更可靠,还能告诉你哪一条论断没有支撑。
人工审查仍然是标准答案。二十个认真审过的案例,胜过两百个草草打分的案例。
还要盯哪些
拒答行为。 当答案确实不在文档里时,系统会说「文档里没有」吗?用你的语料回答不了的问题去测。一个从不拒答的系统有严重问题,而在可回答问题上的质量指标根本暴露不出来。
引用准确性。 被引用的来源真的包含被引用的论断吗?这件事很容易自动检查,而且经常是错的。
一致性。 每个问题跑几遍。方差大说明 prompt 约束不足,这和「答案错了」是两种不同的修法。
每次查询的成本与延迟。 一个改动提升了准确率却把成本变成三倍,那是取舍,不是胜利。
沿流水线逐段排查
每一段都能单独测,这样调试就从猜变成了按顺序走:
| 阶段 | 问题 | 检查方式 |
|---|---|---|
| 抽取 | 文本完整吗? | 直接读抽取出来的结果 |
| 分块 | 文本块里包含完整答案吗? | 用不同策略跑召回率@k |
| 检索 | 正确的文本块被找到了吗? | 召回率@k、MRR |
| 重排序 | 它被排在前面吗? | 重排序前后的 MRR |
| 生成 | 答案是忠实的吗? | 用手工挑好的上下文做裁判打分 |
改一个阶段,就测那个阶段。某个阶段的改进经常不会体现在端到端结果上,因为瓶颈在别的阶段——这正是必须分段测量的原因。
要点回顾
- 把检索和生成分开测;一个总分掩盖了坏的是哪一半。
- 先看召回率@k:正确的段落从来没被检索到,下游做什么都没用。
- 手工提供已知正确的上下文,把生成单独隔离出来。
- 给忠实度打分时,把答案拆成一条条论断逐条检查——这是裁判模型擅长的核验任务。
- 用无法回答的问题测拒答行为,并自动核验引用。
下一篇: 多 agent 系统