
为 AI 应用搭建可用的评测集:划分数据、设计评分函数与计算 F1
为 AI 应用搭建可用的评测集:划分数据、设计评分函数与计算 F1
用电商客服 AI 的例子讲清 evals 的完整做法:把问题集拆成示例、调优集与最终评测集,选择机械匹配或 LLM-as-a-judge 评分,用 F1 处理多答案问题,并避开 AI 生成测试集与评分偏差的坑。
给应用接上大模型之后,几乎一定会遇到两个问题:这个模型够不够用?改了提示词之后是变好了还是变差了?要回答它们,需要一套测量 AI 输出的机制,也就是 evals(评测)。评测有两个用途:一是比较不同模型的强弱,像家电横评那样;二是确认自己的应用在真实场景里能不能跑通,像确认买回来的电器能不能插进自家的插座。实际工作里真正想要的通常不是最强的模型,而是满足所需性能前提下最便宜、最快的那个模型;而要做到这一点,前提是「所需性能」可以被测量。测不出来,就只能一直用最贵的那个以防万一。
下面以电商网站的咨询 AI 为例,从零搭一套评测:怎么划分问题集、怎么设计评分函数、怎么汇总成分数、怎么控制成本,以及哪些做法会让分数虚高。全文不涉及复杂公式,重点在流程和判断标准。
准备工作
开始之前,先把几样东西准备好。它们不是软件安装,而是评测能够成立的前提。
- 明确要测的对象。是模型本身(同一家公司的不同型号,或不同厂商的模型),还是你自己的系统(提示词 + 检索到的资料 + 模型)。两者的评测集不能混用。
- 一份真实的问题来源。客服场景可以直接从历史会话、常见问题、客服工单里取。问题要覆盖真实用户会问的形态,而不是自己凭空想象的形态。
- 一份可核对的正解。退货期限、包邮门槛、可用支付方式这类事实,必须来自你自己的规则文档,不能凭印象写。
- 一个能反复调用的接口。评测要跑几十上百次,手工在对话框里粘贴不可行,需要能脚本化调用模型。
- 对成本的预期。模型调用费用通常按输入和输出的字符量计算,跑一千道题就是一千次调用的费用,而且每次改提示词都要重跑。具体价格以各家官网当前信息为准。
还有一条容易被忽略的准备:先决定答案的形态。是选择题、是固定格式的短答案,还是自由文本。这个决定会直接影响后面评分函数的选择,越早定越好。
操作步骤
第一步:把评测定义成「问题 + 正解 + 评分方式」
一个 benchmark(基准测试)由三部分组成:一组问题和对应正解、一套评分方法。就像一份试卷:有题目、有标准答案、有评分标准,只是答题的人换成了 AI。
以电商咨询 AI 为例,问题与正解可以是这样:
| 问题 | 正解 |
|---|---|
| 购买后多少天内可以退货? | 30 天以内 |
| 满多少金额免运费? | 5000 日元以上 |
| 可以使用哪些支付方式? | 信用卡、便利店支付、货到付款 |
评分方式可以先定得极简:与正解一致得 1 分。100 题答对 92 题就是 92 分。先跑通这个最简版本,再考虑复杂情况。
第二步:把问题集拆成三份,各司其职
收集到的问题不能全部混在一起用。按用途拆成三份,这是整套流程里最关键的一步。
| 分组 | 用途 | 退货类问题的例子 |
|---|---|---|
| 示例(few-shot) | 直接写进提示词,作为示范(几条即可) | 「退货期限是几天?」→「30 天以内」 |
| 调优集 | 每次改提示词、改资料后都跑一遍 | 「促销时买的衣服能退吗?」 |
| 最终评测集 | 上线前只跑一次 | 「拆封过的化妆品能退吗?」 |
用学校打比方:示例是课本上的例题,调优集是练习册,最终评测集是期末考。看例题学方法,用练习册反复练手,最后用没见过的考题检验真实水平。运费、支付方式等其他类别的问题,也照同样的方式各拆一份。
这里要守住两条规则,否则分数会高于真实水平:
- 调优时不能看最终评测集的题目。看到最终评测集里某题答错,就往提示词里补一句,等于提前泄题。
- 同一问题的不同说法不能分到不同组。「促销时买的衣服能退吗?」和「打折买的衬衫可以退吗?」问的是同一件事,必须放进同一组。
第三步:选择评分函数
评分函数负责判断单个答案对不对。常见选项按机械化程度从高到低排列:
| 评分函数 | 适合的答案 |
|---|---|
| 机械匹配 | 答案短且固定:日期、金额、选项 |
| 执行测试 | 程序类输出 |
| 数值误差容忍 | 计算结果(例如误差在 1% 以内算对) |
| 词面重叠 / 语义相似度 | 翻译、摘要 |
| LLM-as-a-judge | 自由书写的文本 |
| 人工评审 | 最终确认、制定标准 |
越靠上越机械、越便宜、越可复现;越靠下越灵活,但耗时耗钱。下面重点讲机械匹配和 LLM-as-a-judge 两种。
第四步:用机械匹配时,先统一答案格式
机械匹配就是把 AI 答案的字符串和正解字符串做比较。它快、便宜、结果稳定,但比较方式不同,弱点也不同。
| 判定方式 | 弱点 |
|---|---|
| 完全一致 | 「30天以内」(全角)或「30 天以内。」都会被判错 |
| 部分包含 | 「不是 30 天以内」也会被判对 |
| 归一化后比较 | 全角半角、空格可以统一,但送假名、汉字与假名的写法差异统一不了 |
日语尤其容易出现表记差异:「申し込み / 申込み / 申込」三种写法都对,但作为字符串是三个不同的东西。人一眼能看出意思相同,机器看不出来。
最有效的对策是提前规定答案的形态:改成选择题,或者要求最后一行写成「答案: 30」这样的固定格式。答题者的自由度越小,评分越稳定。数学题集 GSM8K 要求答案写成 #### 30 的形式,就是这个道理。
第五步:需要自由文本时,用 LLM-as-a-judge 并防偏差
用自然语言回答的咨询问题,靠字符串匹配判不准,可以让另一个 AI 来判分:把评分指令、问题、正解、待判答案一起交给它,问「这个答案对不对」。这比人工逐条阅读快得多、便宜得多。
但充当裁判的 AI 有几种已知的偏差:
- 偏袒自己:对与自己同源的模型给出的答案打分偏高。
- 受位置影响:两个答案并排比较时,交换顺序分数就会变。
- 偏爱长答案:内容相同,写得长的更容易被判为好。
- 在自己答错的问题上失灵:裁判自己也会答错的题,它倾向于把犯了同样错误的答案判为正确。
人类评分者也有类似倾向:对自己带的学生更宽容、先读到的答案成为基准、写得长看起来更努力、自己理解错的地方也给同样的错误打了勾。AI 裁判身上发生的是同一类现象。
对应的缓解办法有三条:
- 用多个模型分别充当裁判,而不是只用一个。
- 把两个答案的顺序交换后再评一次,两次都看。
- 把评分标准写得具体。不要写「是否礼貌」,要写「是否提到退货期限为 30 天」。
第六步:多答案问题用 F1 汇总
「可以用哪些支付方式?」这类问题正解不止一个,用对错二分判不了。假设正解有 3 项,AI 答对了其中 2 项,另外多答了 2 项不在正解里的内容。把答案和正解都看成集合:
- 精确率 = 交集 ÷ AI 答案数 = 2 ÷ 4 = 0.5,即「说出来的内容里有多少是对的」。
- 召回率 = 交集 ÷ 正解数 = 2 ÷ 3 ≈ 0.67,即「该说的内容里说出了多少」。
用新冠检测类比:精确率是「检出阳性的人里真正感染的比例」,召回率是「感染者里被检出的比例」。多答会拉低精确率,漏答会拉低召回率。
只看其中一个指标,取巧的答案就能拿高分:把所有支付方式全列一遍,召回率就是 1;只答一个最有把握的,精确率就是 1。F1 只有在两者都高时才高,因为它不是简单平均,而是被较低的一方拉低。精确率为 1、召回率为 0.1 时,普通平均是 0.55,F1 只有约 0.18。
F1 = 2 × 精确率 × 召回率 ÷ (精确率 + 召回率)
= 2 × 0.5 × 0.67 ÷ (0.5 + 0.67)
≈ 0.57
第七步:按「能否区分」来挑题,而不是按难度
假设 10 道题,A 得 90 分、B 得 80 分。拆开看:8 题两者都答对,1 题两者都答错,真正拉开差距的只有剩下那 1 题。所有人都答对的题和所有人都答错的题,对区分模型毫无信息量。
所以选题的标准不是「难」,而是「能不能拉开差距」。招聘考试里如果全员满分,就选不出人;全员零分同样选不出。公开榜单换个题集排名就变,原因也在这里:那个基准里已经没有能在这个水平上区分模型的问题了。
第八步:把评测纳入日常流程
评测不是做完一次就结束,更像体检:定期跑,以及在发生变更时跑。触发重跑的情形至少包括:
- 更换模型(包括同一厂商的型号切换)。
- 修改提示词。
- 更换或更新检索到的规则文档。
- 模型提供方更新了模型版本——即使自己什么都没改,也值得定期复测。
只改一行提示词,导致另一个问题的回答崩掉,是常见现象。
一个完整示例
把上面的步骤串起来,做一个最小可用的退货咨询评测。
1. 定义问题与正解。先准备 12 道退货相关问题,正解全部来自自家退货规则。
2. 拆分。取 2 道写进提示词作为示例,6 道作为调优集,4 道作为最终评测集。注意把同一问题的不同说法放进同一组,例如「促销时买的衣服能退吗」和「打折买的衬衫可以退吗」必须同组。
3. 规定答案格式。要求模型最后一行输出「答案: X」,X 只能是「可以」「不可以」或「30 天以内」这类固定取值。
4. 写评分函数。先用完全一致匹配。跑调优集,发现模型常输出「30 天以内。」带句号,于是把评分前的预处理定为:去掉首尾空白、去掉句末标点、全角转半角。这一步只改评分脚本,不改提示词。
5. 迭代。调优集上发现「促销商品」类问题答错,在提示词里补充「促销商品不可退货」。重跑调优集,确认分数上升,同时确认其他类别没有下降。
6. 最终评测。提示词定稿后,对最终评测集跑一次,记录分数,不再根据结果回头改提示词。如果最终评测分数明显低于调优集,说明调优集被过拟合了,需要补充更多样的问题。
7. 汇总。如果某道题的正解是多项(例如支付方式),改用 F1 计算该题得分,再与其他题一起汇总。
注意事项
不要让 AI 生成正解表或测试集
AI 擅长判定,不擅长枚举。问它「这个答案对不对」,它判得相当准;让它「把所有正确答案都写出来」,漏项会很多。例如让它列出全部支付方式,可能漏掉货到付款。
原因不难理解:判定只需要看着眼前这一个答案判断对错;枚举则要把不在眼前的东西也全部想到。人也一样,被问「这里面有错吗」能答上来,被要求「把漏掉的都列出来」就很难。
有研究在程序题上量化过这个差距:让 AI 判定提交的程序是否满足规格,F1 在 0.74 到 0.90 之间,表现尚可;让同一个 AI 编写用于检验程序的测试,这些测试只能让已知正确的程序中的 19% 到 42% 通过,也就是把一半以上的正确程序判成了不合格。原因是 AI 往测试里加了规格里根本没写的条件,比如规格只说「排序」,它却加了一条「空列表应报错」,而返回空列表的实现完全符合规格,却被判失败。
更麻烦的是,漏项和多余条件要么根本没写出来,要么写得像模像样,回读时很难发现。所以 AI 生成的正解表或测试集,必须先用已知正确的答案试一遍。如果已知正确的答案被判为不合格,错的是正解表,不是那个答案。
控制评测成本
题目越多,每轮评测的时间和费用越高;如果每次改提示词都要重跑,成本会成倍放大。在加题之前,先做减法:把拉不开差距的题删掉。
还有一种更省的做法:根据上一题的结果动态选下一题——答对就出更难的,答错就出更简单的。有在安全类基准上的结果显示,大约 10 道题就能基本还原整套题集的分数。这类做法适合快速回归,不适合作为上线前的最终判定。
评测做出来之后,才能谈成本优化
有了评测,就可以做模型分流:简单咨询交给便宜模型,难题才转给贵模型。类似医院分诊,轻症去社区诊所,重症去大医院。但实践中的反馈反复指向同一点:比搭建省钱机制更难的,是测出「省到这个程度是否仍然安全」。没有评测,分流就只是猜测。
为什么代码领域跑得更快
让 AI 写代码这类用法比其他领域普及得更早,原因有两个:公开代码数据量大;正确与否可以机械判定——跑一下测试就知道。程序领域早就有现成的验证工具,AI 写的代码运行一遍就能看出对不对,所以模型改进和使用者调优都能立刻看到反馈。
反过来看,其他领域用 AI 的障碍也正在「能不能评测」上。如果你要做的是自己的咨询 AI、内部工具,那么第一个该做的东西可能不是提示词,而是测量它的那套题集。
关于数字与版本
文中涉及的模型价格、调用配额、模型版本与可用地区都会变化,请以各服务商官网当前信息为准。评测集本身也应随业务规则更新而同步维护,规则改了,正解就要跟着改。