API 接 eval 套件
Day 71-74 把 agent runner 包成了一个有契约、能流式、会重试的真 API。现在缺最后一块拼图:怎么证明这个 API 包装层没把能力搞坏。
阶段: B8 · 真 API + 流式 + Docker(Day 71-80) 标签: #eval-as-fixture #contract-test #source-agnostic #regression-gate
今日导引(由浅入深)
Day 71-74 把 agent runner 包成了一个有契约、能流式、会重试的真 API。现在缺最后一块拼图:怎么证明这个 API 包装层没把能力搞坏。
今天在 B1→B18 曲线上把两件本来分开的事合并——把已有的 eval 任务集当成 API 的集成测试夹具:
- 每个任务既是一条 contract 用例(测 API 正确性)。
- 又是一次能力测量(出成功率数字)。
- 一次跑全套,API 回归与能力回归同时验。
这是 B3 评测能力与 B8 API 工程的合流。明天(Day 76)会用同一夹具跑 Qwen3 做模型对比。
最小可判定产出:经 /chat(或 pnpm eval:agent)跑全任务集,统计成功率,与直连基线对齐即回归绿。
1. 机理精读
1.1 eval 任务集 = API 的集成测试夹具
普通集成测试要手写一堆 request/assert 样板。但本仓已经有一套专家撰写的 eval 任务集(src/agent/eval/tasks.ts),每条任务都是「prompt + reference + 判定」的完整三元组。把它复用为 API 夹具:
- 每条任务即一条 contract 用例——跑
/chat发 prompt、收响应、judge 判 pass/fail。 - 一次跑全套,既验证 API 包装层(错误映射、流式、重试)端到端正确,又顺带产出一张能力数字表。
一份夹具、两个用途。
1.2 eval-as-fixture 思路引 Anthropic「Demystifying evals」(2026-01)
核心主张是 eval 不该是「跑完看个分」的一次性脚本,而应是工程化的、可重复跑的、当回归 gate 用的资产。把它接进 API 路径正是这个思路的落地:
- 每次改
/chat包装层就重跑夹具。 - 分数掉了就是回归。
这把「评测」从研究活动变成了 CI 资产。
1.3 prediction 来源必须与评测解耦(source-agnostic),否则自评循环偏差
这是本仓踩过坑后的硬纪律:
- 如果 baseline 的 ground truth 是模型自己生成的、又用同模型去评,就是「自己给自己打分」——分数虚高、不可信。
- 正确做法是 prediction 来源(谁产出答案:直连 runner / 经
/chatAPI / 别的模型)与评测(judge + reference)解耦。
本仓已用 groundTruthEval 的 source-agnostic 设计修复了早期的自评循环 baseline。本日把 API 路径接进来正是这个解耦的体现:API 只是换了 prediction 的产出通道,judge 和 reference 不变,所以 API 路径的分数能直接和直连基线比——一致就说明 API 没引入偏差,即回归绿。
1.4 judge=pass 口径对齐现有 gate
跑 API 路径用的判定口径要和已有的 eval gate 一致(同 judge、同 reference、同 pass 阈值),否则两边分数不可比、对齐失去意义。口径统一是「API 路径成功率 ≈ 直连基线」这个回归断言成立的前提。
2. 推导 / 手算 / 代码走读
2.1 走读夹具来源 src/agent/eval/tasks.ts
本日用它作 contract 用例:
- 文件头注释定义任务集设计哲学:任务是 expert-authored(从 FATF/BSA AML typologies + 已知 LLM-agent 失败模式手写),NOT mined from production transcripts(因为 AML Copilot 是确定性规则引擎、还没有真 LLM transcript)。
- 这保证夹具是「故意打模型痛点」的:over-flagging benign patterns、缺数据时 fabricating、破坏输出 format、服从 injected instructions、该人审却 auto-acting。
2.2 EvalCategory 11 类枚举
夹具横跨能力维度,不只测 AML 检出:
aml-detect/aml-restraint/aml-typology/aml-complianceformat/honesty/robustness/planningsafety/injection/reasoning
也测「该克制时克制」「被注入时不服从」。
2.3 每条任务结构与判定分层
- 结构:
{ id, category, prompt, reference, codeCheck }。 codeCheck是廉价启发式第一遍(如has(/structur|smurf/i)用正则探 typology 关键词)。- 文件头注释明确:
codeCheck is a cheap heuristic first pass; the LLM-judge does the real outcome grading + partial credit——真正判分是 LLM-judge,codeCheck 只兜底。 - 文件头还写明 P1 闭环:跑真模型后把观察到的真实失败 append 成新任务,并 hand-label ≥50 进
agent-evals/labels.json校准 judge(Cohen's kappa)。这解释了为什么任务集要持续扩。
2.4 口径对齐推导(为什么期望 ≈ 79.3%)
- 本日 API 路径只改「prediction 由谁产出」(经
/chat而非直连 runner)。 reference与 judge 不变。- 所以期望 API 路径成功率 ≈ 直连基线 79.3%(V4-Flash,judge=pass,N=29)。
- 若显著偏离,则是 API 包装层引入了 bug(如流式截断、错误映射吞了响应),即回归红。
注意:src/agent/eval/tasks.ts 是纯任务定义、无 key 可读;但跑出真实成功率数字需带 key 跑真模型。
3. 今日实战
- 用
src/agent/eval/tasks.ts(29 任务)作夹具。 - 写脚本经
/chatAPI 发每条prompt,收响应;或直接走既有入口pnpm eval:agent。 - judge=pass 口径对齐现有 gate(同 judge + reference + 阈值)。
- 统计成功率,得 x/29 通过率表。
- 与直连基线 79.3% 对齐校验:一致即回归绿;显著偏离则查 API 包装层(流式 / 错误映射)。
4. 今日实测 / 产出
- 已有真实数字可锚定:V4-Flash completion 79.3%(judge=pass),partial-credit 0.900,N=29。
- 本日 API-路径通过率为 待跑(需 key 跑) 的 x/29 chart——预期与直连基线 79.3% 一致即回归绿。
- 注意:
agent-evals/baseline.json尚未定基线(gated on 选定 baseline run)。 src/agent/eval/tasks.ts:已构建(任务定义,无 key 可读),本日复用为 contract 夹具,未改动。
5. 常见误区 / 陷阱
- 自评循环 baseline:用同模型既产 ground truth 又评分会让分数虚高——已被
groundTruthEval的 source-agnostic 修复取代,勿回退。 - API 路径与直连用不同 judge 口径:口径不一致则两边分数不可比,「回归绿」断言失效。
- 把 N=29 的成绩当统计显著:A/B 已证明 N=29 不足以达统计显著(见 Day 80 lesson),扩集到 ~70 任务待办。
- 以为 codeCheck 就是判分:codeCheck 只是廉价启发式第一遍,真正 outcome grading + partial credit 由 LLM-judge 做。
6. 学习资源(每条带 YYYY-MM)
- Anthropic, "Demystifying evals"(官方文章,2026-01;eval-as-fixture / 评测工程化思路)。
- 本仓代码:
src/agent/eval/tasks.ts(29 任务,11 类,expert-authored,B1)。 - FATF / BSA AML typologies(监管来源,持续更新;任务 reference 的事实底座)。
- 本仓交叉引用:
docs/aipa/evals CI gate 与 source-agnostic baseline 章节。
SOTA检查 (2026-06 更新)
- 当前主流:eval-as-fixture + source-agnostic prediction + LLM-judge + partial credit 是当下评测工程的主流组合(Anthropic evals 方法 2026-01 仍适用)。
- 是否仍 SOTA:方法 SOTA;但任务集规模是短板——N=29 偏小,A/B 已证明 N=29 不足以达统计显著(见 Day 80 lesson),扩集到 ~70 任务待办。
- 过时黑名单:避免用自评循环 baseline(已被
groundTruthEval的 source-agnostic 修复取代)。 - 下次复查点:
- 扩集到 ~70 任务后复跑达 power 的 A/B。
- hand-label ≥50 进
agent-evals/labels.json后复算 judge 的 Cohen's kappa。 agent-evals/baseline.json选定基线 run 后解锁回归数值对比。
衔接
- 昨天:Day 74 — typed 错误 + 重试(错误映射 + full jitter 退避 + 流干净终止)。
- 今天:把 eval 任务集当 API 集成夹具——一份夹具同测 API 正确性 + 出能力数字,judge 口径对齐现有 gate,与直连基线 79.3% 对齐即回归绿。
- 明天:Day 76 — 流式接 Qwen3 对比(用同一 29 任务夹具跑双模型,产 TTFT + 通过率对比表;已落地 A/B:V4-Pro 89.7% vs V4-Flash 79.3%,Δ+10.3pp CI[0,20.7],N=29 不显著)。