上一篇讲完了检索质量优化的三件武器。但优化之前有个前提问题:你怎么知道它变好了? 如果答案只是"感觉好一些了",那接下来的迭代一定会陷入来回摆动——改一版觉得好了,再改一版又觉得差了,几天过去没有结论。这一篇讲的就是怎么把"觉得"变成"测得出"。
一、不评测的代价,比想象中大
先说清楚为什么这件事不能省。
第一个代价是无法收敛。 大模型输出本身有随机性,单次结果的好坏里混着运气成分。你改一个参数、跑一个问题、感觉变好了——但这次变好可能纯粹是因为温度采样抽到了不同的路径。没有多次、成批的对比,你分不清是改动有效还是噪声。
第二个代价是不知道优化哪里。 上一篇把失败分成三层,但分层的前提是你能看出某次失败属于哪一层。只看"答得不对"这四个字,你无法判断该去改检索还是改拼装。
第三个代价是团队无法协作。 没有共同认可的数字,"应该先加重排"和"应该先改切分"就永远争不出结论——两边都能举出支持自己的例子。
所以评测不是"上线前走个流程",它是让迭代能够收敛的唯一机制。前面第七篇讲提示词时给过一个同款结论:准备一个小测试集,看整体通过率而不是单次感觉。RAG 的评测是同一件事,只是要测的环节更多。
二、先分层:检索的账和生成的账要分开算
这是整篇的骨架。如果把所有环节混成一个"答得好不好"的分数,你会知道系统不行,但不知道哪里不行。
所以要拆成两层,各自独立测:
- 检索层:正确答案所在的块,有没有被找出来、排在第几?
- 生成层:拿到了正确的块之后,模型给出的答案对不对?
分开测的价值在于,它能直接告诉你问题出在哪:
- 检索层就差 → 先别管模型。改切分、改写查询、加重排(上一篇的内容)。
- 检索层好、生成层差 → 检索没问题,问题在拼装、提示词,或者模型本身对这类任务的处理能力。
- 两层都差 → 先修检索。因为生成层依赖检索的结果,上面的问题会一直被下面的问题掩盖。
这个顺序不能反。一个常见的错误是在检索召回率很低的情况下去反复调提示词——你调得再好,模型手里也没有正确的资料,等于白花时间。
三、评测集怎么建(最关键,也最费功夫)
整篇里最值钱的就是这一节。评测集是这类项目里回报率最高的一笔投入,而且越早建越好——因为它不只服务评测,还会成为你后续所有改动(换模型、换切分、换提示词)的公共基准。
问题从哪来
从真实来源拿,不要自己编。 可选来源按优先级排:
- 线上真实用户查询(有日志的话最理想);
- 客服工单、内部答疑群的历史提问;
- 让实际用这套系统的同事出题,而不是你自己想。
为什么不能自己编?因为你一旦知道自己的资料长什么样,就会不自觉地按资料的措辞出题。你出的题天然会偏向"容易被检索到"的那一类,测出来的分数会明显虚高。真实用户从来不会照着你的文档措辞提问——这正是检索困难的主要来源。
必须标注的东西
每条评测样本至少要有两样:
- 问题本身;
- 答案所在的块(gold chunk),也就是"这条问题的答案应该出自哪一段"。
第二个标注是很多人省掉的,但它不可省——没有它,你就无法把检索层和生成层分开测。你只能看最终答案对不对,然后把所有失败都归到"效果不好"。
标注工作量不小,但可以增量做:先标 20~30 条跑起来,后面陆续补。
规模与覆盖度
规模上,几十到一两百条就足够指导决策了。不必追求上千条——样本量大了,标注质量反而容易失控。
覆盖度比规模重要,至少要覆盖这几类:
- 高频简单题:用户最常问的,答案在文档里写得很直白。这类应该接近全对,如果这类都错,说明链路有硬伤。
- 长尾难题:问法刁钻、需要多段信息拼起来才能回答的。
- 多跳与指代题:需要先查 A 再查 B,或者问题里有指代需要结合上下文补全。
- 资料里根本没有的问题。这一类最重要,也最容易被漏掉。它测的是模型会不会老实说"资料里没有",而不是编一个听起来合理的答案。 一个检索做得再好、但遇到无答案问题时满口胡编的系统,在真实场景里比答不出来更危险。
四、检索层怎么测
检索层的指标有几个常见口径,理解它们的差别比记住公式有用。
命中率 / Recall@K:正确答案的块,有没有出现在前 K 个结果里。
这是最基础也最重要的指标。它回答的是"有没有找出来",不关心排第几。之所以重要——因为只要没进前 K,后面的环节就永远看不到它。这就是上一篇说的第一层问题。
MRR(平均倒数排名):正确答案排在第几位的倒数,再取平均。排第 1 得 1 分,排第 2 得 0.5 分,排第 3 得 0.33 分。
它衡量的是"排得多靠前"。适合"每条问题基本只有一个正确块"的场景。它能反映上一篇说的第二层问题——召回了但排后面。
NDCG:当一条问题对应多个相关块、而且相关程度还不一样时用它。它同时考虑了"有没有找到"和"排序好不好"。
K 取多少? 这是最容易被忽略的一个细节:K 要和你实际拼进上下文的块数对齐。 如果你线上一次只取 5 个块送给模型,那测 Recall@20 是没有意义的——第 6 到第 20 名在你的系统里根本不会被用到。指标必须对应真实链路,否则测出来的数字和线上表现对不上。
一个实用的做法:同时看 Recall@K 和 Recall@(K 的几倍)。前者反映实际效果,后者反映"潜力"——如果 Recall@20 高但 Recall@5 低,说明问题在排序而不在召回,重心该放到重排上(上一篇的第二层)。这两个数一对比,问题出在召回还是排序就清楚了。
五、生成层怎么测
拿到正确资料之后,答案好不好,要分开看几个维度——它们经常不同时成立。
正确性:答案的事实是否正确。
忠实度(依据性):答案是否真的基于给定资料,而不是模型自己补的。
这两个必须分开,因为它们组合出四种情况,而其中两种特别值得警惕:
- 忠实但错:答案严格引用了资料,但资料本身是错的或过时的。这说明问题在数据治理,不在模型。
- 不忠实但对:答案跳出了资料,靠模型自己的记忆蒙对了。这种情况最难发现,也最危险——因为它在单次测试里表现为"对",分数很好看,但它意味着系统在不确定的时候会编,今天蒙对了不代表明天对。
如果不把"正确性"和"忠实度"分开测,这两种情况都会被算成一个笼统的"对",然后你就失去了发现它们的机会。
完整性:该说的信息有没有漏。比如答案正确但只回答了一部分条件。
拒答准确率:资料里没有答案时,模型是否老实说"资料中没有相关内容",而不是给一个编造的答案。
这一类里,误答(该拒答却编了)比误拒(该答却说没有)严重得多。误拒用户会觉得"这系统没用",误答用户会拿着错误信息去做决策。所以两者要分开统计,不要合成一个"拒答准确率"就完事。
六、用什么来评:人工与模型评委的取舍
人工评测准确,但贵、慢,而且不同人的标准不一致。上百条样本全人工评,多数团队撑不过两轮迭代。
模型评委(用模型来打分)快、便宜,适合跑全量。但它有已知的偏差:
- 长度偏好:倾向于给更长的回答更高分,哪怕长的里面废话更多;
- 自我偏好:倾向于给同族模型的输出更高分;
- 位置偏好:在对比两个答案时,倾向于选排在前面的那个。
所以直接拿模型评委的绝对分数当结论,风险不小。
务实的组合是:人工标小样本 + 模型跑全量。 具体做法:
- 人工精标 20~30 条,作为基准;
- 用模型评委跑这同一批,看它和人工的一致率;
- 一致率高(比如大部分判断一致),才敢把模型评委用到全量上;
- 一致率低,就要改评分标准(把要求写得更具体、给出正例和反例),或者干脆回到人工。
这一步叫校准,不能跳。跳过它,你得到的是一堆看起来很客观、实际上和你真正在意的标准偏离很远的数字。
还有一个降低偏差的实用技巧:让模型评委做两两对比,而不是打绝对分。 "A 和 B 哪个更好"比"A 打几分"更稳定,也更接近人类的判断方式。然后用胜率来做指标。
七、两个容易踩的坑
坑一:对着评测集调参。
这是最隐蔽的一个。你发现某几条题答不对,于是微调提示词让它们对了——分数上去了,但这是过拟合,线上不会变好。尤其当你反复对着同一个小测试集迭代时,这种情况一定会发生。
对策不复杂:
- 留出一部分样本不参与日常调试,只在决定上线前跑一次。这个留出集被"看过"的次数越少,它给出的信号越可信。
- 每次改动都用全量跑,而不是盯着失败的那几条改。看整体通过率有没有提升,而不是某几条过没过。
- 定期补充新问题,让评测集跟着真实使用演化。
坑二:只看离线分数,不看线上。
离线评测是在你选定的问题上测的,而线上流量会带来你没想到的问法。所以上线后要接上在线指标:
- 点踩率:最直接的用户反馈;
- 追问率:用户问完之后又追问同一件事,往往说明第一次答得不够好;
- 采纳率:如果答案会被复制、被引用,这个信号很实在;
- 人工抽检:定期随机抽一批真实问答人工看,这是发现"离线测不出来"的问题的主要方式。
离线指标用来指导优化方向,在线指标用来验证优化真的有用。两者缺一不可,而且当它们冲突时(离线涨了线上没涨),要相信线上。
八、迭代节奏:一次只改一个变量
最后给一条操作纪律,它比任何指标都重要。
每次只改一个变量,然后全量跑一遍评测。
改切分和改提示词一起上,效果好了你不知道该保留哪个;效果差了更不知道该回滚哪个。这条纪律看起来慢,实际上是最快的路径——因为每一步的结论都是确定的。
配合一个门槛:预设"提升多少才值得上线"。比如整体通过率提升不到几个百分点、而延迟或成本明显上升,那这次改动就不值得上。事先定好门槛,能避免被单次波动说服。
九、小结与检查清单
- 评测的意义:让迭代收敛、让分层诊断可行、让团队有共同依据
- 必须分层测:检索层(找到没、排第几)与生成层(拿到资料后答得对不对)分开,否则不知道问题在哪
- 评测集:问题取自真实来源(别自己编)、必须标 gold chunk、规模几十到一两百条够用、覆盖度要含"资料里没有"的拒答题
- 检索指标:Recall@K 看有没有找到、MRR 看排多前、NDCG 看多相关块排序;K 要对应实际拼进上下文的块数;对比 Recall@K 与 Recall@几倍 K 可区分召回问题还是排序问题
- 生成指标:正确性与忠实度必须分开,以识别"忠实但错"(数据问题)和"不忠实但对"(最危险的蒙对)
- 评测方式:人工标小样本 + 模型跑全量,中间必须做校准;优先用两两对比而非绝对打分
- 防过拟合:留出集、每次全量跑、定期补题
- 在线指标:点踩、追问率、采纳率、人工抽检;与离线冲突时相信线上
- 纪律:一次只改一个变量,事先定好上线门槛
一道判断标准:如果有人问你"这次改动让效果提升了多少",你给出的应该是评测集上的一个百分比,而不是"感觉好多了"。 给不出数字,说明这套系统还没进入可迭代的状态。
下一篇
评测有了,RAG 的核心环节基本讲完了。但还有一批"工程落地"的问题没解决:检索每次都要跑一遍、成本怎么压;资料更新了怎么让新内容快速生效;多租户场景下怎么保证 A 部门查不到 B 部门的资料。下一篇讲把这些接进已有 Java 服务时,会碰到的实际问题。
本文是「用 Java 接入大模型」系列第十七篇。上一篇讲了检索质量优化,建议按顺序看。文中指标口径与比例(如人工校准样本量)为实践起点,具体取值请按你的业务规模与风险要求确定。