"改了提示词,昨天好好的今天不行了。"这句话在提示词项目里的出现频率,高于任何一个具体 bug。麻烦处不在坏,而在无法定位:同时改了三处措辞、换了个模型小版本、温度从 0.2 调到 0.7,事后说不清是哪一处的功劳。
手感调参的问题不在"手调",而在没有对照。人看到新输出会自动寻找支持自己判断的证据,这是判断机制问题,不是态度问题。所以评测体系买的不是更准的分数,而是三样:可复现的对照、可解释的失败、可回滚的版本边界。
这篇只回答决策问题:什么条件值得建、每档判分买到多少可靠性、付多少代价、什么规模以下体系自身失效。
1. 手感调参的失效机制
| 现象 | 结构性原因 | 后果 |
|---|---|---|
| 同一条提示两次结果不同 | 采样随机性 + 模型版本漂移 | 改动效果被噪声淹没 |
| 新旧两组"各有各的好" | 无固定输入集,比较的是不同样本 | 结论不可累积 |
| 修好一个坏两个 | 只测当下想到的 case | 回归无人发现,直到投诉 |
| 换模型就得重调 | 没有基线,每次重新起跑 | 迁移成本不可估 |
判断是否掉进去,只需回答一句:"变好了"能否写成第三方可复核的话(集合 E 上指标 M 从 a 到 b,跑 N 次)。写不出,就还在手感里。
# 反面:新提示更稳定,人工看了十几条不错
# 可复核:
prompt=classify-v7 temp=0 runs=3 set=core-120
pass=0.83 失败集中在"多意图混写"(11/15);对照 v6 同条件 0.86
2. 评测集的四个准入要求
评测集是这套体系的全部资产,其余都是外围。四条准入缺一条,判分再精细也没意义。
| 要求 | 可检查的判据 | 不满足时的代价 |
|---|---|---|
| 覆盖真实任务分布 | 各类占比与线上日志分布同量级 | 只测容易的 20%,指标虚高 |
| 难度分层 | 打 easy/core/hard 标签,各层都有样本 | "平均分没变"或是分层抵消 |
| 参考答案可判定 | 只看输入与参考即可独立复现结论 | 争议多,评审反复吵 |
| 可扩充 | 加一条是分钟级,不破坏历史可比 | 只加不改,历史分数不可比 |
历史条目可标记废弃,但不能原地修改,否则旧分与今天的分不在同一把尺子上。
{"id":"c-017","task":"classify","hard":true,"input":"...","expect":{"labels":["refund","logistics"],"rule":"keep_both"},"source":"badcase"}
3. 判分方式三档:买到什么,付多少
三档不是"从差到好",而是适用面不同的三段:规则判定精度高但面窄,LLM 判定覆盖宽但有系统偏差。
| 档位 | 可靠性 | 单条成本量级 | 适用任务 | 主要失效模式 |
|---|---|---|---|---|
| 精确规则(Schema/字段断言/正则) | 高、可复现 | 近零 | 结构化输出、分类、抽取 | 换个说法就判错,把"对但不同"记为失败 |
| 关键点命中(必含/禁含) | 中高,取决于关键点定义 | 极低 | 摘要、问答、多要点答复 | 关键点取自某次输出,等于抄答案 |
| LLM-as-judge | 中,随模型与提示波动 | 每条一次模型调用 | 开放写作、风格、整体可用性 | 位置偏好、长度偏好、自我偏好 |
成本按单条调用数 × 条数 × 重复次数 × 频率算,不是"跑一次多少钱"。120 条、每判 1 调用、3 次重复,一次完整评测约 3.6×10² 次判分调用,另叠加被测模型调用;真正决定账单的是频率。
SPEC = { # 关键点定义在语义要点上,不定义在字串上
"must": ["含退款金额", "含原订单号"],
"must_not": ["承诺到账时间", "索要支付密码"],
"scored": {"给出下一步动作": 1}, # 分层加分项
}
def judge(text, hit): # hit: 语义要点判定
return all(hit(text, k) for k in SPEC["must"]) \
and not any(hit(text, k) for k in SPEC["must_not"])
规则判分要复核被判失败的样本:把正确答案判成错,会让人去修没坏的东西。抽检按失败样本数定比例。
4. LLM-as-judge 的三种偏差与校准
| 偏差 | 现象 | 校准手段 | 残余风险 |
|---|---|---|---|
| 位置偏好 | 成对比较偏向先出现的那个 | 交换 A/B 各判一次,两次都赢才算赢 | 成本翻倍 |
| 长度偏好 | 更长的回答更易得高分 | rubric 写明"简洁不减分",统计长度-得分相关性 | 无法完全消除 |
| 自我偏好 | 与自己风格相近的输出得分偏高 | 判分模型与被测模型分开选型 | 同家族时仍偏高 |
结论:LLM-as-judge 适合排序,不适合当绝对分数。当"哪版更好"的相对判据,配少量人工定标,比输出 0–10 可靠得多。
judge_rubric:
规则: 只评"是否满足任务要求",不评措辞是否优美
输出: {"winner":"A|B|tie","reason":"一句话","violations":[]}
硬约束: 安全兜底缺失 → 直接判负,不看其他维度
校准: 每轮变更抽部分条目人工复判;一致率低于阈值时先修 rubric,不信分数
rubric 的纪律:判据要写成可被第三方套用的句子。"更专业"不可用,"含明确结论且不引入输入外事实"可用。
5. 单变量纪律与显著性判断
一次只改一处是硬约束。三处同改,变好不知该留哪处,改坏不知该退哪处——改动失去可归因性,评测从投资变成开销。
| 判断场景 | 样本与重复要求 | 结论强度 |
|---|---|---|
| 单条提示改动,任务稳定 | 全量跑 3 次,看分布不看单次 | 区间不重叠才算有效 |
| 影响面未知 | 先按模块分层看,再定是否扩集合 | 只报总均值会掩盖分层反向 |
| 判分本身不稳定 | 先解决判分复现性,再谈提示差异 | 判分噪声大于改动效果时一切结论无效 |
for i in 1 2 3; do evalctl run --set core-120 --prompt v7 --out runs/v7-$i.json; done
evalctl report --runs 'runs/v7-*.json' --group-by difficulty --show range
常见误判:把"0.83 涨到 0.86"当进步。120 条时单条权重约 0.008,0.03 约等于 3–4 条翻转,在噪声内。样本量决定可分辨的最小差异,集合小于几十条时多数"提升"都是噪声。
6. 版本管理:提示、模型、参数分开记录
三者耦合会摧毁回滚能力:只知道"上周那版好",不知道那版配的哪个模型与参数。
| 维度 | 记录内容 | 易被漏掉的点 |
|---|---|---|
| 提示 | 模板全文 + 变量契约 + 版本号 | 变量默认值变化等同改行为 |
| 模型 | 模型 ID + 提供方版本标识 + 路由策略 | "同名模型"背后的版本可能已漂移 |
| 参数 | 温度、top_p、最大长度、重试 | 重试次数变化会改变输出分布 |
release: rel-2026-11-09-03 # 可回滚的最小单位 = 三元组
prompt: classify-v7@sha256:PROMPT_HASH
model: MODEL_ID@provider-version
params: {temperature: 0, top_p: 1, max_tokens: 1024, retry: 1}
eval: {set: core-120, set_version: v14, runs: 3, pass_range: [0.81, 0.87]}
rollback_to: rel-2026-11-02-02
线上退化先做最小回滚(只动变化的那一维),再分析;全量回滚会丢掉其他有效改动。
7. 线上闭环、成本与腐化
线上反馈不是收集好评差评,而是把坏例变成可判定条目。
| 失败类型 | 回收动作 | 是否进集合 |
|---|---|---|
| 提示缺失业务规则 | 补进 must/must_not 关键点 | 是,更新关键点定义 |
| 判分本身判错 | 修 rubric | 否,进判分校准集 |
| 输入分布变了(新场景) | 新增难度层与类别 | 是,标记新增来源 |
| 模型能力退步 | 记为环境变更事件 | 否,触发全量重跑 |
成本控制靠频率分层,不靠压缩集合规模:
| 时机 | 跑什么 | 理由 |
|---|---|---|
| 提交级 | quick-20,规则判分优先 | 拦截明显退化,成本近零 |
| 日级 | core-120,LLM 判分 1 次 | 兼顾覆盖与花费 |
| 周级/发布前 | 全量 + 3 次重复 + 人工抽检 | 只在这一档谈显著性 |
腐化盯两个信号:过拟合——提示长出只对集合有效的特例措辞,分数涨而线上不变,用未进集合的新流量做影子评测,差距拉大即是;标注漂移——判分口径几个月里悄悄变了,对策是集合版本号,旧分连版本一起读。
8. 团队协作:谁维护、谁能改基线
| 角色 | 权限 | 为什么这样分 |
|---|---|---|
| 提示作者 | 提交改动、跑 quick 档 | 谁改谁付运行成本 |
| 集合维护人 | 条目增删、难度标签、版本 | 公共资产只能一人拍板 |
| 领域专家 | 定标与分歧裁决 | 判分口径的业务来源 |
| 基线责任人 | 批准基线分数变更 | 防止"改不动就降基线" |
最关键:改基线必须比改提示更难。允许任何人调阈值那一刻,体系就成了橡皮图章。
9. 排错:评测体系自身的六种失效
| 现象 | 原因 | 处理 |
|---|---|---|
| 分数忽高忽低 | 判分不稳或集合小 | 先测判分复现性,再扩集合 |
| 每次评测全绿 | 门槛太松或条目全是 easy | 加 hard 层,重设门槛并复核分布 |
| 提示改动总能提升分数 | 过拟合到集合 | 引入未进集合流量做影子评测 |
| 分数涨了线上没变 | 集合与真实分布脱节 | 按线上分布重采条目 |
| 两人跑同一版结果不同 | 三元组未绑定 | 补元数据,跑前校验 |
| 有问题没人认领 | 集合维护人缺位 | 指定单一负责人 + 版本号制度 |
10. 边界:这些情况不必建体系
| 场景 | 判断 | 替代做法 |
|---|---|---|
| 任务一眼可判(格式转换、抽取) | 不建 | 几条断言即可,够了就停 |
| 创意/风格类任务 | 规则判分无意义 | 只做相对排序 + 人工定标,别追绝对分 |
| 集合规模小于几十条 | 结论不可靠 | 扩到可用规模,或承认只能冒烟检查 |
| 需求每周大变 | 建了也会腐化 | 先冻结任务口径 |
| 单人项目 | 流程成本超收益 | 保留三元组记录,跳过协作机制 |
评测体系的价格是持续维护,不是一次搭建。没人做集合维护时,比"没有评测"更糟的是"有一个没人信的分数"。
11. 自测
- 为什么"变好了"必须能被写成第三方可复核的一句话?
- 评测集的历史条目为什么可以废弃、但不能原地修改?
- 三档判分里哪一档的主要代价是假阴性,怎么控制?
- LLM-as-judge 为什么更适合排序而不是绝对分数?
- 集合只有 120 条时,分数提高 0.03 说明什么?
- 回滚的最小单位为什么是提示、模型、参数的三元组?