问题背景
这是《LLM Ops 评测与可观测实战》系列的第一篇,之后十篇的评测、门禁、追踪、灰度都会站在今天这块地基上。先说一个大多数团队都经历过的场景:客服团队上线了一个基于 RAG 的售后政策问答机器人,演示会上负责人连问五个问题,四个答得漂亮,于是宣布"效果不错,上线"。两周后投诉堆积:退款时效问题答错、把"不支持七天无理由"的商品说成支持、遇到方言输入直接胡编。回头复盘,没有人能说清"上线那天的机器人到底行不行"——因为根本没人系统地量过。传统软件有单元测试和断言,输入确定输出确定;LLM 应用输出的是一条概率分布,"感觉不错"本质上是拿五六个样本去猜一个分布的形状,这种验收方式在统计学上就不成立。本篇回答三个问题:评测集到底在工程上扮演什么角色;一个小到"一周就能建起来"的评测体系长什么样;不建评测集时你实际在用什么替代品,以及那个替代品坏在哪里。
核心原理
第一层,评测集是"效果的版本控制"。代码有 git,配置的每一次变更有 diff 可查,而 prompt、模型版本、检索参数这三样东西的变更在传统流程里完全没有 diff:改了 prompt 的第三行措辞,你不知道它对"多轮追问"类问题造成了什么影响,因为没有任何基线可以对照。评测集做的事情,就是把"效果"变成一个可以对两次变更做差分的标量(或一组标量)。没有它,回滚都无法决策——你想退回旧版本,却拿不出"旧版本到底差在哪、差多少"的证据。
第二层,LLM 的非确定性让小样本彻底失真。同一输入温度不为零时输出会变,于是单次问答结果带有采样噪声;当你只凭十来个案例判断版本好坏,噪声经常比真实效应大。把这件事模拟出来最直观:假设新版本真实通过率 0.75、旧版本 0.72(新版本确实更好),用固定随机种子按不同样本量各做 400 次抽样评测,统计"把更好的新版误判成持平或退步"的比例。
第三层,不建评测集不等于没有评测,只是评测标准劣化了。团队会自发找到代理指标:演示时的通过率、产品经理的手工抽测、上线后前几条用户反馈、竞对 demo 的对比印象。这些代理有三个共同病灶——样本小且偏(专挑能打的问)、标准漂移(每个人心里"好"的定义不同,同一条回答两个人给出相反结论)、不可累积(人的印象无法参与下一次版本比较)。评测集工程的全部动机,就是把这套劣化的隐式评测换成可复现、可累积、可审计的显式评测。
第四层,评测集的最小可行形态。不需要一步到位,三样东西凑齐就算立起来了:一个 200 到 500 条、按业务意图分层抽样的用例集(意图如:政策问答、订单查询、边界拒答、多轮追问),每条带参考答案或评分标准;一套自动打分流程(下一篇建数据集,第三篇讲打分);一条 CI 里的回归基线——每次 prompt 或模型变更跑一遍,出分对比。先有粗糙但稳定的尺子,再谈精细的尺子。
实验一:凭感觉验收在统计上为什么会翻车
本机无第三方依赖,以下用 Python 标准库做确定性模拟(固定种子),演示抽样规模与结论稳定性的关系;生产环境请用真实评测平台跑真实用例。
import random
TRUE_A = 0.72 # 旧版本真实通过率
TRUE_B = 0.75 # 新版本真实通过率(确实更好)
TRIALS = 400
def trial(n, seed):
rng = random.Random(seed)
flips = 0
gaps = []
for _ in range(TRIALS):
a = sum(1 for _ in range(n) if rng.random() < TRUE_A) / n
b = sum(1 for _ in range(n) if rng.random() < TRUE_B) / n
if b <= a:
flips += 1
gaps.append(abs(b – a))
return flips, sum(gaps) / len(gaps)
print("评测集样本量对结论稳定性的影响(每档 400 次重复实验, 种子=42):")
print("样本量 n | 误判率(把更好的新版判成持平或退步) | 平均表观差距")
for n in (20, 50, 100, 300, 1000):
flips, mean_gap = trial(n, seed=42)
print("n=%4d | %5.1f%% | %.3f" % (n, flips / TRIALS * 100, mean_gap))
运行输出:
评测集样本量对结论稳定性的影响(每档 400 次重复实验, 种子=42):
样本量 n | 误判率(把更好的新版判成持平或退步) | 平均表观差距
n= 20 | 47.0% | 0.114
n= 50 | 40.2% | 0.077
n= 100 | 32.8% | 0.059
n= 300 | 24.2% | 0.038
n=1000 | 6.5% | 0.031
这组数字值得裱起来贴在评审会上:两个版本真实差距 3 个百分点时,20 条用例的评测有 47% 的概率得出反向结论——和抛硬币一样;哪怕 100 条仍有近三分之一的误判率。注意 3 个百分点本就是"勉强值得切换"的差距,如果你的真实提升只有 1 个点,需要上千条用例才看得见。这也解释了为什么演示会式的验收总能"成功":演示者挑的案例、挑的轮次,相当于在 47% 误判率之上再做一轮对己有利的筛选。
实验二:要多大的尺子才配说"提升了"
换一个角度,用正态近似算置信区间半宽(纯标准库 math 即可),回答"n 条用例的通过率估计,误差到底有多大"。
import math
BASE = 0.72
Z = 1.96
def half_width(p, n):
return Z * math.sqrt(p * (1 – p) / n)
print("通过率 0.72 的点估计, 不同样本量下的 95% 置信区间(正态近似):")
for n in (20, 50, 100, 200, 400, 800):
h = half_width(BASE, n)
print("n=%4d 半宽=%.3f 区间=[%.3f, %.3f]" % (n, h, BASE – h, BASE + h))
target = 0.03
n = 1
while half_width(BASE, n) > target:
n += 1
print("要把置信区间半宽压到 0.03 以内, 单版本最少需要 %d 个用例" % n)
print("两个版本各自独立评测时, 比较的有效差距约为半宽的 sqrt(2) 倍")
print("可分辨差距下限约 %.3f" % (target * math.sqrt(2)))
运行输出:
通过率 0.72 的点估计, 不同样本量下的 95% 置信区间(正态近似):
n= 20 半宽=0.197 区间=[0.523, 0.917]
n= 50 半宽=0.124 区间=[0.596, 0.844]
n= 100 半宽=0.088 区间=[0.632, 0.808]
n= 200 半宽=0.062 区间=[0.658, 0.782]
n= 400 半宽=0.044 区间=[0.676, 0.764]
n= 800 半宽=0.031 区间=[0.689, 0.751]
要把置信区间半宽压到 0.03 以内, 单版本最少需要 861 个用例
两个版本各自独立评测时, 比较的有效差距约为半宽的 sqrt(2) 倍
可分辨差距下限约 0.042
20 条用例测出的"通过率 72%",真实区间是 [52%, 92%]——这个分数除了自我安慰毫无信息量。要把不确定度压到 ±3 个点,单版本需要近 900 条;两版对比时可分辨差距进一步放大到 4 个点上下。工程上从中得到两条硬结论:其一,评测集规模是按"你想分辨多大的差距"倒推出来的,不是拍脑袋定 100 条;其二,同一批用例要打在两个版本上做配对比较,比两个独立样本比较灵敏得多——这正是第四篇回归测试采用"同案例集逐条 diff"而不是只看总分的原因。
工程落地路径
第一步,从线上日志冷启动。没有评测集的团队几乎一定有对话日志:客服系统、API 请求记录、反馈表。按业务意图分桶抽样 300 条,人工过一遍挑出"答错的、可疑的、典型的"三类,标注预期行为(应该引用哪条政策、应该拒答、应该追问什么)。两三个人工日就能立起第一版,先跑通链路再追求规模。
第二步,评分标准写到字符串级。每条用例除了参考答案,还要写"判分要点":必须包含退款时效三个字、必须不承诺具体到账日、出现电话号码即判错。要点式标准让不同标注员结论趋于一致,也是第三篇 LLM-as-judge 提示词的原料。
第三步,分数进 CI,基线进档案。每次 prompt/模型/检索参数变更自动跑评测,分数与变更号绑定存档。评测集本身也是代码:进版本库、有 owner、有 review,被业务方投诉"答非所问"的案例先进监控名单、季度评审后晋升为用例——数据集要随业务生长,否则半年后它就测不到真实分布了。
常见陷阱
其一,用通用 benchmark(MMLU、GSM8K 这类)代替业务评测:榜上分数与你的售后问答质量几乎不相关,模型选型必须以自己的评测集为准。其二,评测集与训练/提示示例同源:把调 prompt 时用过的案例留在评测集里,等于开卷考试,分数虚高且掩盖真问题——调 prompt 用的案例和评测案例要物理隔离。其三,只测单轮:真实用户大量追问、改口、夹带方言,单轮通过率漂亮的多轮一塌糊涂,评测集中多轮对话用例占比建议不低于三成。其四,把评测当一次性活动:为选型建完集就扔,之后 prompt 改了七版没人重跑,评测集最大的价值恰恰在"持续"两个字。其五,评分标准口头化:"回答要自然"这种形容词无法复核,两个人打出的分差到 0.4 以上(满分 1 分制),尺子本身就是噪声源。
落地清单
- 盘点线上对话日志,按意图分层挑 300 条起步,标注"预期行为 + 判分要点"
- 评测集与 prompt 调优用例物理隔离,版本化管理并指定 owner
- 用置信区间倒推规模:想分辨几个点的差距,就要近千条同集配对的用例
- 每次变更自动跑评测,分数与变更号一同归档,可差分、可回滚
- 投诉与线上坏案例进入候选池,季度评审晋升为正式用例
尺子立起来了,接下来的问题是这把尺子上的刻度从哪来:评测集不能靠几个人坐在工位上编造问题,它必须采样自真实的线上分布,并经过一套能控制一致性的标注流程。下一篇《LLM Ops 评测与可观测实战(2):golden dataset 构建:线上数据的采样与标注流程》把"从十万条日志到三百条金标准"的流水线走一遍。
参考来源
- OpenAI Evaluation guides:https://platform.openai.com/docs/guides/evals
- Stanford HELM:Holistic Evaluation of Language Models:https://arxiv.org/abs/2211.09110
- Wikipedia:Binomial proportion confidence interval:https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval
- Wikipedia:Cohen’s kappa:https://en.wikipedia.org/wiki/Cohen%27s_kappa
- Langfuse 文档(评测与数据集):https://langfuse.com/docs
网硕互联帮助中心







评论前必须登录!
注册