2883 字
约 9 分钟
17
S21-A09 · Agent 评测:离线集、在线信号与人工抽检
离线跑分 87%,上线三周,运营的同学说"没人用"。查日志发现:用户在第一轮就问完了,Agent 多走的两步是白走;任务确实"完成"了,但完成方式是用户已经自己做完之后点了个确认。
这说明分数本身没问题,评测口径和用户价值对不上。Agent 评测不是打分,是三个来源互相校准:离线集回答"能力有没有退化",在线信号回答"有没有人真的用",人工抽检回答"分数是不是在骗人"。
1. 三个层次与各自的成本
| 层次 | 判定对象 | 判定方式 | 单位成本 | 能发现 | 发现不了 |
|---|---|---|---|---|---|
| 单步正确 | 一次工具调用/一次检索 | 精确比对、schema 校验 | 极低 | 参数错、格式错 | 策略整体走偏 |
| 任务完成 | 一个任务是否达成 | 规则校验、终态检查 | 中 | 流程断点、循环 | 用户是否满意 |
| 用户接受 | 输出是否被采用 | 行为信号、人工抽检 | 高 | 白走步骤、体验差 | 长尾能力缺口 |
三层缺一层就有一个盲区。只做单步,测不出"多做两步";只做任务完成,测不出"用户早就做完了"。
2. 离线集的三种成分与更新机制
| 成分 | 来源 | 占比(典型) | 更新触发 |
|---|---|---|---|
| 黄金任务 | 人工构造、业务方确认 | 40–60% | 需求变更时 |
| 对抗任务 | 已知越权、诱导、歧义问法 | 20–30% | 每次线上事故后 |
| 失败回放 | 线上失败会话的脱敏快照 | 20–30% | 每月或每事故 |
一条任务的最小字段
{
"id": "task-0142",
"input": "...", # 用户原始输入
"context": {...}, # 环境/工具返回值快照
"expect": {"type": "rule", "rule": "..."},
"tags": ["golden", "multi-turn"],
"source": "incident-2026-09-11"
}
更新纪律:只增不删。删用例等于删记忆;过时的期望改成 skip 并注明原因,保留在那里作为历史。
3. 任务级判定必须可自动化
判定不可自动化,回归就只能靠人眼,人眼一停,回归就停。
| 任务类型 | 可自动化的判定 | 不可自动化时怎么办 |
|---|---|---|
| 有确定终态(下单、归档) | 检查数据库终态 | — |
| 有结构化输出 | schema + 字段断言 | — |
| 开放写作/建议 | 规则 + 模型裁判 | 只能抽样,不能全量门禁 |
| 多轮澄清 | 检查澄清次数与关键槽位 | 抽检兜底 |
# 规则校验器:返回 (通过, 原因),原因用于归因
def check_order(task, trace):
if trace.final_state != "created":
return False, f"final_state={trace.final_state}"
if trace.args.get("sku") != task["context"]["sku"]:
return False, "sku_mismatch"
if trace.tool_calls > 3:
return False, f"redundant_steps={trace.tool_calls}"
return True, "ok"
最后那条 tool_calls > 3 是关键:它把"白走两步"变成了可回归的失败,而不是等用户抱怨。
4. 三种评分器与模型裁判的偏差
| 评分器 | 稳定性 | 成本 | 主要偏差 |
|---|---|---|---|
| 精确匹配 | 最高 | 极低 | 对表述差异零容忍 |
| 规则校验 | 高 | 低 | 只覆盖写得出规则的维度 |
| 模型裁判 | 中 | 中高 | 位置、长度、自我偏好 |
| 偏差 | 表现 | 缓解 |
|---|---|---|
| 位置偏好 | 总选第一个/最后一个候选 | 随机交换候选顺序,取多次平均 |
| 长度偏好 | 长答案得分更高 | 长度分桶后比较,或先压缩再判 |
| 自我偏好 | 同族模型互相打高分 | 换第三方裁判,或用规则兜底 |
裁判使用的三条纪律
1. 裁判提示里给判定标准与反例,不给"请打分"
2. 同一批样本跑两次,一致率 < 85% 的条目进人工池
3. 裁判只判"是否满足某条具体标准",不判整体优劣
5. 在线信号的选取与噪声
| 信号 | 定义 | 噪声来源 | 敏感度 |
|---|---|---|---|
| 完成率 | 走到终态的比例 | 用户中途离开也算失败 | 高 |
| 重试率 | 同一意图重复提交 | 用户习惯性多点 | 中 |
| 人工接管率 | 转人工/转人工按钮 | 入口位置影响点击 | 高(口径要固定) |
| 放弃率 | 会话无后续动作 | 用户去别处完成 | 中 |
| 追问深度 | 平均轮次 | 任务难度混杂 | 低 |
# 按提示版本切分在线指标,避免不同版本混算
curl -s "http://metrics/query" --data-urlencode 'q=
sum(rate(agent_task_done_total[1d])) by (prompt_fp)
/ sum(rate(agent_task_start_total[1d])) by (prompt_fp)'
没有版本维度的在线指标,只能说明"现在怎么样",无法说明"这次改动怎么样"。
6. 人工抽检的抽样设计
| 维度 | 抽什么 | 抽多少(经验起点) | 谁判 |
|---|---|---|---|
| 失败会话 | 全部失败中随机 | 每周 30–50 条 | 一线 + 产品 |
| 成功会话 | 分层随机(按任务类型) | 每周 20–30 条 | 产品 |
| 新意图 | 未归类的输入 | 全量 | 产品 + 业务方 |
| 争议条目 | 裁判两次不一致 | 全量 | 标注负责人 |
抽检要产出可回归的资产,不是产出一份报告。每条被判定为"实际不好"的样本,必须转成一条离线用例,否则下一版还会犯。
抽检记录的最小字段
会话ID | 任务类型 | 系统判定 | 人工判定 | 不一致原因 | 是否转用例
7. 离线与在线的落差归因
| 落差的形态 | 归因方向 | 验证方法 |
|---|---|---|
| 离线高、在线低 | 任务分布不同 | 用线上输入分布重跑离线集 |
| 离线高、在线低但用户满意 | 判定口径太严 | 对齐"完成"的定义 |
| 离线低、在线高 | 离线集偏难 | 分层看子集分数 |
| 两者都低但有人用 | 价值不在准确率 | 换评测目标(时间节省等) |
8. 可复现性:三元组
一次评测结果只有在记录模型版本 + 提示指纹 + 工具版本之后才可复现。
{
"model": "vendor/model@2026-09-01",
"prompt_fp": "9f2c1ab3d7e4",
"tools": {"search": "1.4.2", "db": "2.0.1"},
"dataset": "eval-2026-10-12",
"seed": 42,
"temp": 0
}
| 缺哪一项 | 后果 |
|---|---|
| 模型版本 | 供应商静默更新后,分数变化无法解释 |
| 提示指纹 | 提示微调与模型升级混在一起 |
| 工具版本 | 工具返回格式变了,被误判为模型退化 |
温度设 0 不等于确定:并发、缓存、外部工具都可能引入差异,所以同一配置要跑两次看波动。
9. 成本与频率
| 评测规模 | 每次 token 量级 | 时间量级 | 建议频率 |
|---|---|---|---|
| 冒烟(20–30 条) | 低 | 分钟级 | 每次提交 |
| 回归(150–300 条) | 中 | 十分钟级 | 每日 / 每次发布 |
| 全量(含人工抽检) | 高 | 小时级 + 人力 | 每周或每双周 |
分层策略(用成本换覆盖)
提交级:冒烟集 + 规则校验,必过
发布级:回归集 + 模型裁判,允许 2% 抖动
周期级:全量 + 人工抽检,产出新用例
频率不是越高越好:回归集太小跑得太勤,会把噪声当信号,团队会开始无视红灯。
10. 不要把评测集当训练集
污染检测的三个信号:
| 信号 | 检测方式 | 阈值(经验) |
|---|---|---|
| 分数跳变 | 某子集准确率从 60% 到 95% | 需要解释,否则视为污染 |
| 逐字复现 | 输出与用例期望高度重合 | 相似度 > 0.9 报警 |
| 提示词过拟合 | 换同义改写后分数大跌 | 改写后跌幅 > 15 点 |
防污染的最小制度
1. 评测集与训练/微调数据物理隔离,权限分开
2. 评测集带 held-out 子集,只在发布决策时看
3. 每次模型升级必须跑同义改写版本
11. 上线门禁与灰度
| 门禁 | 判据 | 不通过怎么办 |
|---|---|---|
| 冒烟 | 全过 | 阻断合并 |
| 回归 | 不低于基线 −2% | 阻断发布,先归因 |
| 对抗集 | 越权类零容忍 | 阻断 |
| 在线灰度 | 完成率不低于对照 −3% | 回退 |
灰度放量的三个台阶
5% → 看错误率与人工接管率(不看平均分)
25% → 看任务结构是否变化(新意图是否激增)
100% → 看一周后的留存/复用
12. 排错
| 现象 | 原因 | 处理 |
|---|---|---|
| 分数每天抖 5 点 | 温度、并发、外部工具不稳 | 固定 seed,跑两次取中位 |
| 回归通过但线上告警 | 用例不含线上分布 | 用线上输入重采样 |
| 裁判判定与人工差很多 | 裁判提示缺标准与反例 | 改判具体标准,两次不一致进人工 |
| 新模型分数全面上涨 | 疑似污染或裁判偏好变化 | 跑 held-out 子集与同义改写 |
| 抽检结论无法沉淀 | 缺转用例环节 | 抽检表强制加"是否转用例" |
13. 边界
| 场景 | 搭评测体系的价值 | 理由 |
|---|---|---|
| 原型/概念验证 | 很低 | 需求还在变,用例活不过两周 |
| 任务无客观判定标准(创意、咨询) | 低 | 只能抽检,无法自动门禁 |
| 用户量极小且人工全量复核 | 低 | 人工复核本身就是评测 |
| 多工具、多轮、要上量 | 高 | 回归成本远超建设成本 |
| 受监管、需审计 | 最高 | 判定过程本身要被留存 |
评测体系是规模的成本:它解决的是"人看不过来了"这个问题。人还看得过来时,先别搭。
14. 自测
- 你的离线集里,"失败回放"占多少,最近一次更新是什么时候?
- 任务级判定里哪一条把"多做两步"变成了失败?
- 模型裁判跑两次一致率多少,不一致的条目去哪了?
- 在线指标的查询语句里有没有版本维度?
- 上一个被判"实际不好"的会话,是否已经变成一条离线用例?
- 一次评测结果能不能凭记录复原出模型、提示、工具三个版本?
S21-A09 · Agent 评测:离线集、在线信号与人工抽检
https://www.clxhxhhr.top/posts/6222/ 评论
0 条
还没有评论,先写一条吧。