评测:怎么知道它好不好?
本章一问:怎么知道它好不好?
主线定位
上游(A1 到 A8):一个能跑的 agent——循环会停、工具能改文件、权限与沙箱各管一层、上下文会压缩、第二天记得规矩、能派子 agent、能换模型也算得清账。
本章(A9 验证与评测):它到底修得好不好?「好」要怎么量、量出来的数该信几分、失败了是谁的错。
下游:课程终点。本章最后回到 A0 的第一个问题:哪些任务值得用 agent。评测的数学口径与 LLM 课是同一套尺子:C14 评测与训练仪表讲噪声、污染和三层可信度,C12 岔路 B1 推过 pass@k 的无偏估计——本章直接用,不重讲。
累计数据流里,本章点亮最后一个环节「验证与评测」:它不在循环里,在循环外面给整次运行下判决。
本章问题链
每一课只回答一个问题;上一课的失败,逼出下一课的问题。表里的数字都由数据现算。
| 课 | 这一课的问题 | 朴素方案在哪个真数字上失败 | 一句话 |
|---|---|---|---|
| 第 1 课 | 修好 test_parse_date 一次,算它会修 bug 吗? | 跑一次看成败:同一配置只换 seed,pd-v2-unlimited 三次是 ✗ ✓ ✓;拿平均成功率套公式,TB 4.0 榜首行 pass@5 算出 98.7%,实测 71.2% | 一次成功说明不了能力,k 次全成功才说明可靠;公式要按任务算,再平均 |
| 第 2 课 | 分数高,是模型强还是 harness 强? | 直接比厂商榜单:同一个模型、同一个 effort,GLM-5.3 在 Claude Code 上 41.82%,在 Terminus 2 上 25.25% | 分数 = 模型 × harness;比模型,先把 harness 统一 |
| 岔路 | 能力在按什么速度增长? | 看平均分:它有天花板,越接近 1 越挤;METR 把成功率换成「人类要做多久」,浏览器里重拟合与发布值相差不到 0.05% | 把「能不能做」换成「能做多长的活」,增长才不会被天花板压扁 |
| 岔路 | 评测标准为什么是一个极简 agent? | 统一 harness 随便挑一个:两个极简 harness(mini-SWE-agent 与 Terminus 2)给 Gemini 3.8 Flash 的分数也差 6.0 个点 | 极简 harness 是一把固定、公开、带版本号的尺子,只在同一把尺子里比 |
| 第 3 课 | 它失败了,失败在哪一步、属于哪一类? | 只看分数:15 次失败只剩一个「0 / 15」;只看最后一句话:5 次明确声称完成,5 次没过 | 分数告诉你成没成,轨迹告诉你为什么 |
| 第 4 课 | 把自己的 agent 接上真实评测,要跑通哪几步? | 直接跑自家 agent:第一次 oracle 冒烟 0 / 5,原因是容器里的 DNS,不是 agent | 先用参考解确认环境,再上自己的 agent |
| 实验课 | 自己的 agent 上 TB 2.0,再回到 A0 复盘 | — | 评测回答的是「这个 agent 在这批任务上行不行」,A0 回答的是「这批任务该不该交给 agent」 |
演进地图
本章的「现代做法」是被一连串真实数字逼出来的。每一课都会用这张图标出「你在这里」。
- 起点 跑一次,看成败最直觉的做法:一个任务、一次运行、一个布尔值解决了最省事:修好了就说「会修」,没修好就说「不会」。卡在同一套配置只换 seed:pd-v2-unlimited 的 s1 / s2 / s3 是 ✗ ✓ ✓;同为 seed 1、只多了一个没碰到的轮数上限的 pd-v2-cap20-s1 又是 ✓。只跑一次,结论取决于你碰上了哪一次。
- Anthropic《Demystifying evals for AI agents》· Harbor 的 -k 与 pass_at_k.py解决了同配置的 7 次运行过了 6 次:p̂ = 0.857,pass@3 = 99.7%,pass^3 = 63.0%;T6 的 3 次重复全过。卡在拿全体平均成功率套公式:TB 4.0 官方榜第一行(Codex + GPT-6 Astra,max)pass@1 为 58.18%,公式给 pass@5 = 98.7%,榜单实测 71.2%:每个任务的成功率不一样。而且重复再多次,也分不出分数里哪部分是 harness。
- 第二步 统一 harness,才能比模型Vals 统一用 Terminus 2 复测 TB 4.0 · SWE-bench 官方 bash-only 榜统一用 mini-SWE-agent解决了同一个模型换 harness 的差距摆上桌:Fable 5.1 在 Claude Code 上 57.88%、在 Terminus 2 上 49.49%;GLM-5.3 41.82% → 25.25%。卡在分数只告诉你成没成:本课 agent 在 TB 2.0 上 0 / 15,15 次失败各是各的样子,一个数看不出为什么。
- 第三步 读轨迹,给失败打带步号的标签Harbor 的 ATIF 轨迹 · Anthropic 工程博客的四类失败 · 本章写明的标签规则解决了15 次失败都落到了带步号的标签上:改完 / 跑完不回头查 7 次,撞上输出上限 4 次,明确声称完成 5 次、5 次没过。卡在标签分不清是 agent 错还是环境错:第一次 oracle 冒烟 0 / 5,原因是容器里的 DNS;arm64 探测里 qemu-startup 连参考解也拿 0 分(verifier 现装 curl 时 404)。
- Harbor v0.23.0:-a oracle 冒烟 → -a module:Class -k解决了参考解 5 / 5 通过、环境就绪之后,再跑自家 agent:5 个任务 × 3 次。卡在k = 3、单一 8B 本地模型、5 个任务、amd64 镜像靠 qemu 模拟:结论只在这个规模成立。(→ 课程终点:回到 A0,哪些任务值得用 agent?)
数字口径:本课项目 T6(Harbor 0.23.0 + Terminal-Bench 2.0,本机 Qwen3-8B-MLX-4bit,录制于 2026-09-26)与 A1 的同配置运行;TB 4.0 官方榜(更新于 2026-09-21)与 Vals(更新于 9/22/2026),均于 2026-09-27 抓取;由 a09-eval.json 与 a09-public-2026-09-27.json 构建时现算。
贯穿任务:修好 test_parse_date,然后上一个真实评测
这一章给贯穿任务的 trace 加上最后一层:判决——verifier 的结果、k 次重复的 pass@k / pass^k、失败标签与对应步号。
本章用到的真实数据(项目线的 T6,录制于 2026-09-26,本机 Apple M5 Max, 128 GB, macOS 26.6.2(arm64)):
- 贯穿任务 parse_date × 3:项目自己的 runner,harness v2,seed 11 / 12 / 13,3 / 3 通过。加上 A1 里配置相同、轮数上限都没碰到的 4 次,合并样本 6 / 7(第 1 课)。
- Harbor 0.23.0 + Terminal-Bench 2.0:89 个任务的镜像 0 / 89(Docker Hub tag API 逐个查,全部只有 linux/amd64),本机 arm64 经 qemu 模拟运行。oracle 冒烟第一次 0 / 5(DNS),修好后 5 / 5。
- 本课 agent × 5 个 TB 任务 × 3 次:Qwen/Qwen3-8B-MLX-4bit(本机 mlx_lm.server),miniagent 0.5.0 经 Harbor 适配器接入,0 / 15 通过。每个 trial 的 ATIF 轨迹、verifier 结果都导出了(第 3 课、实验课)。
- arm64 探测:另外 10 个 TB 任务的 oracle,job 在 3 / 10 时被停掉;两个结果为空的 trial 查清了原因(第 4 课)。
- 公开数据:TB 4.0 官方榜(更新于 2026-09-21)、Vals 的 Terminus 2 复测(更新于 9/22/2026)、Databricks 内部基准(自报)、SWE-bench 官方榜、METR 时间跨度数据,均于 2026-09-27 抓取。
这一章所有关于「我们的 agent」的结论只在这个规模成立:单一 8B 本地模型(4bit 量化)、k = 3、5 个 TB 任务、amd64 镜像经 qemu 模拟。耗时一律只能粗看——本机有其他任务同时占用,且模拟运行比原生慢。本章没有跑任何新的模型运行;数据不够的地方在各课里写明。
整门课回看:T6 的 18 条轨迹里,前九章各留下了什么
十章每章回答一个问题、给项目加一个里程碑。到了评测这一章,前面每一章的选择都在真实轨迹里留下了痕迹。下表每一行的数字都由 T6 数据现算。
| 章 | 那一章的一句话(原话) | 在 T6 里看到的 |
|---|---|---|
| A0 编排选择 | 把决定权交给模型,换来适应性,付出 token、时间与可预期性。 | 同一个 harness:自建的 parse_date 合并样本 6 / 7,TB 的 5 个任务 0 / 15。A0 录制前的预测对了 3 / 4;TB 这 5 个任务按 A0 的三条标准事后判定,有 2 个一段 workflow 就够(实验课) |
| A1 循环 | 停不停可以由模型说了算,做没做成要由模型之外的东西来判。 | 15 次里 11 次以「不再调工具」收工、4 次连续写满输出上限被停下;成败全部由 verifier 判,模型说什么不算 |
| A2 工具 | 同一条 edit,五个引擎给出三种裁决;只有跑过测试才知道谁对。 | 43 次 bash、7 次 write_file、2 次 edit_file。改完就收工、没回头跑一次的有 7 次(第 3 课) |
| A3 权限 | prompt 决定模型想做什么,harness 决定允许什么;匹配子串拦不住改写过的命令。 | Harbor 适配器里权限是 allow_all:隔离边界交给容器;贯穿任务在本地仍用 last_match 标准规则 |
| A4 沙箱 | 关键不是「有没有」,而是写清楚隔离责任在谁、边界画在哪、默认开不开。 | TB 的命令在任务容器里执行,不再套 Seatbelt;本地 parse_date 三次都在 Seatbelt 里跑 |
| A5 上下文 | 窗口是上限,不是有效长度;能少放就少放。 | 18 条轨迹里最长的一步输入 5,348 token,是 40,960 窗口的 13%;压缩一次没触发,「上下文腐化」这条标签 0 命中 |
| A6 记忆 | 规矩放进每轮重注入的指令文件,不放在会被压缩掉的第一条消息。 | TB 版 system prompt 里写着「没用工具核对过,就不许说完成」,5 次明确声称完成里没有一次先核对——写进 prompt 的规矩不是约束 |
| A7 子 agent | 干活的和评活的必须分开,评活的不能动手改。 | 5 次明确声称完成,5 次没过(A7 第 4 课的 32 次运行里是 20 次声称、12 次没过) |
| A8 模型接入 | 缓存命中率就是输入侧的钱:前缀一变就归零;开思考时,大头在输出。 | 15 个 TB trial 合计输入 153,211 token(缓存命中 85%)、输出 142,449 token;70 个模型回合里 20 个把 4,096 的单次输出上限写满 |
三层交互
| 层 | 本章里的组件 | 在哪一课 |
|---|---|---|
| 概念动画 | 演进地图(每一步卡在哪个真数字上);接上真实评测的六步(真实命令、真实结果逐步翻) | 每一课、第 4 课 |
| 算法模拟器(真算法、小数据) | pass@k / pass^k 两条曲线与无偏估计(与 Harbor 0.23.0 自己的函数在 440 组输入上逐一一致);Clopper–Pearson 精确区间;TB 4.0 榜单的「套公式 vs 实测」;METR 的加权 logistic 重拟合与倍增时间回归(复现发布值) | 第 1 课、岔路 B1 |
| 真实数据 | T6 的 18 条轨迹逐步回放、按规则现算的失败标签与步号跳转、工作区重建、学习者自己标注;公开榜单的「同模型换 harness」散点;arm64 探测表 | 第 2、3、4 课,实验课 |
每个移植都配了自检:组件里的纯函数与 python 独立实现逐项对照(pass@k、pass^k、置信区间、动作分类、失败标签、工作区重建、logistic 拟合、倍增时间、榜单配对),32 项全过。生成脚本:src/data/precomputed/gen_a09_eval.py、gen_a09_public.py;node 单测:test_a09_pure.mjs。
项目推进:里程碑 M9 · 接 Harbor
对应 04-实践项目/MILESTONES.md 的「A9 · 评测与失败模式」。已有:Harbor 适配器 miniagent/harbor_agent.py(MiniAgent(BaseAgent))、容器内执行的工具 exec_tools.py、轨迹转 ATIF 的 atif.py、剧本回放的假模型 scripted.py、录制与导出脚本 run_t6.py / t6_harbor_job.py / export_t6.py。代码 AI 来写,决策你来做。
- 成功怎么定义?只看测试退出码,还是同时要求测试文件没被改(本项目选后者,见
runner.py);在 TB 上,只认 verifier 的 reward,agent 的自述一律不算(第 3 课)。 - 选哪 5 个任务、每个重复几次?本项目按镜像体积挑小的、兼顾难度,k = 3。第 1 课的区间告诉你 k = 3 能说明多少;要把 3 / 3 的区间下界提到 0.5 以上,至少要连续 6 次全过。
- 失败标签用哪一套?本章给了七个标签(Anthropic 的四类 + 本批数据里出现的三类),每个都写明规则,分「自动」「人工」两种(第 3 课)。你可以删、可以加,但每个标签都要能指到步号。
- 输出上限要不要调?15 次里有 4 次一个工具都没调就被停下——思考写满了 4,096。调大它是 harness 的决定,调之前先想清楚:这会改变你要比较的那个「agent」(第 2 课)。
- 要不要在停下前让 harness 自己检查?A1 岔路 B3 讨论过;T6 里 7 次「改完不回头查」都发生在模型自己决定收工的时候。
验收标准(对应大纲 M9 ①-⑥;括号里是 2026-09-26 在项目里核对的现状):
- ①
harbor run -d terminal-bench@2.0 -a oracle在所选 5 个任务上全部就绪(已达成:5 / 5;第一次 0 / 5 的原因与修法记在 MILESTONES.md)。 - ② 自家 agent 经
-a miniagent.harbor_agent:MiniAgent产出结果 JSON 与 ATIF 轨迹(已达成:15 个 trial,ATIF-v1.8;剧本冒烟先验证了适配器)。 - ③ 报告通过数、pass@k / pass^k、成本(已达成:0 / 15;pass@k 与 pass^k 在第 1 课由数据现算;本地模型没有账单,成本以 token 计)。
- ④ 每个失败任务都有失败标签与涉及步号(本章补上:第 3 课的规则让 15 次失败每次至少一个标签;项目里的
export_t6.py只导出了「停在哪一步 / 第一次报错在哪一步」这类候选,没有标签)。 - ⑤ t01(parse_date)的 k 次重复入库(已达成:3 / 3,
traces/t6/t6-pd-s1*.jsonl)。 - ⑥ 导出 T6(已达成:
src/data/project/agent-t6-eval.json)。 - 选做:mini-swe-agent 跑 SWE-bench Lite 子集(没做;官方 harness 的门槛与 arm64 限制见岔路 B2)。
- 本章建议补的两条:(a)把第 3 课的自动标签规则移进项目(
scripts/下一个命令,对全部 trial 输出标签分布),人工标注的部分存成labels.json;(b)k 从 3 加到 5——项目的run_t6.py已经支持--suffix追加 attempt,本章没有跑。
坑与带走
本章拦截的误解| 误解 | 纠正 | 在哪一课 |
|---|---|---|
| 跑一次就能下结论 | 同一配置换 seed:一次 ✗ 两次 ✓;同 seed 也会分叉(A0 第 3 课) | 第 1 课 |
| pass@k 高 = 可靠 | pass@k 讲「至少一次」,可靠要看 pass^k,两者随 k 反向走 | 第 1 课 |
| 3 / 3 就是每次都行 | 3 次全过,p 的 95% 区间下界只有 0.29,推出的 pass^3 可能低到 2.5% | 第 1 课 |
| 拿平均成功率套公式就行 | 公式假设每个任务成功率相同;TB 4.0 全榜 27 行,套公式的 pass@5 都比实测高 | 第 1 课 |
| 榜单分数就是模型的分数 | 同一个模型换 harness,通过率变化 -21.8 到 +4.7 个点 | 第 2 课 |
| SWE-bench Verified 仍是前沿尺子 | Vals 已因饱和归档(榜首 97%);官方榜最新一条是 2026-02-26 | 第 2 课 |
| 极简 harness 分数低 = 模型弱 | 它量的是同一把尺子下的相对差;换一把极简尺子,绝对分也会变 | 岔路 B2 |
| 失败都是模型不行 | 4 次是 harness 的输出上限先到;第一次 oracle 0 / 5 是 DNS;CORE-Bench 修好评分器 bug、换了约束更少的 scaffold 后从 42% 到 95%(Anthropic 自报) | 第 3 课 |
| 退出码 0 = 做对了 | log-summary 的脚本从空的标准输入读数据,15 个计数全是 0,退出码照样 0 | 第 3 课 |
| oracle 冒烟通过 = 评测了自己的 agent | 它只跑参考解,证明环境能起、verifier 能判 | 第 4 课 |
-k 3 就会报 pass@3 | Harbor 只报 2 的幂与 5 的倍数:3 次重复只报 pass@2 | 第 4 课 |
| 症状 | 后果 | 怎么办 |
|---|---|---|
| 跑一次定结论 | 被随机性误导 | 重复 k 次,同时报 pass@k 与 pass^k,附区间 |
| 拿厂商自报榜比模型 | harness 与模型混在一起 | 统一 harness,或同模型对照;每个数标来源与日期 |
| 只看最后一条消息 | 自称完成而实际未完成 | 以 verifier 为准,再读轨迹 |
| 分数低就怪模型 | 忽略环境、评分器与 harness 配置 | 先跑 oracle,再看轨迹里是谁先撞了墙 |
| 用 SWE-bench Verified 比前沿模型 | 已饱和,区分不出差异 | 换未饱和的集合并标版本 |
| 长期引用榜单快照 | 数字过时 | 每个数字标抓取日期 |
| 固定 seed 跑 k 次 | k 次几乎一样,重复失去意义 | Harbor 把同一组参数传给每次 attempt,本项目不固定 seed |
| 被取消的 trial 当失败 | 分数偏低(git-multibranch 的 verifier 其实写了 1) | 取消、异常与 0 分分开统计 |
带走这些句子(各课「一句话」):
- 一次成功说明不了能力,k 次全成功才说明可靠;公式要按任务算,再平均。
- 分数 = 模型 × harness;比模型,先把 harness 统一。
- 把「能不能做」换成「能做多长的活」,增长才不会被天花板压扁。
- 极简 harness 是一把固定、公开、带版本号的尺子,只在同一把尺子里比。
- 分数告诉你成没成,轨迹告诉你为什么。
- 先用参考解确认环境,再上自己的 agent。
- 评测回答的是「这个 agent 在这批任务上行不行」,A0 回答的是「这批任务该不该交给 agent」。
整门课带走一句:agent = 模型 × harness;harness 的每一层(循环、工具、权限、沙箱、上下文、记忆、分工、接入)都是你拍板的决策,而判断这些决策对不对,只能靠可重复的评测和读得懂的轨迹。
深入这一章
按你愿意花的时间选。每条都在 2026-09-27 实际打开核对过;站外链接需联网。视频缺口:pass^k、失败归因都没有找到专门讲机制的中文视频;用官方长文和交互站代替。
🎮 想更直观 10–30 分钟
🔬 想吃透原理 1–3 小时
📄 想读原文 按需
我替你排除了什么:掘金《Terminal-Bench 2.1 跑分全解读》(文中数字是二手转述)· TB 2.0 旧榜单链接(已重定向到 4.0 榜)与档案里「142 个提交、榜首 84.7%」的 TB 2.0 快照(动态数据,不再引用)· 「上下文在 25–30 次工具调用后开始退化」一类说法(来源存疑,不能归到 METR)· OpenAI「不再报告 SWE-bench Verified」的原文(本章抓取时被拒绝访问,没能逐字核对,改用 Vals 的归档说明与官方榜的最新日期)· ATIF Viewer 的「用模型自动做失败分析」(要填 API key;本章的标签不调用模型)· 任何没有抓取日期的榜单截图。