修好 test_parse_date 一次,算它会修 bug 吗?
本课一问:本课的 agent 修好了一次 test_parse_date。这能说明它「会修这个 bug」吗?要跑几次、怎么算,才算说清楚?
这一课先不碰:分数里哪部分是模型、哪部分是 harness(第 2 课);失败在哪一步(第 3 课);怎么接真实评测(第 4 课);pass@k 无偏估计的推导(LLM 课 C12 岔路 B1 已经推过,这里直接用)。
从已有出发
两个伏笔在这里兑现。A0 第 3 课看过「孪生运行」:同配置、同 seed 跑两次,4 个任务里 2 个在中途分叉——工具输出里差了几个 token(工作区目录名、耗时),后面整条路就变了;那一课的结尾说「想让两次运行可比,要么固定这些东西,要么用多次运行的统计来说话」。模型这一侧本来也在抽样:本课项目的 temperature 是 0.6、top_p 0.95,采样怎么把概率变成一个字,见 LLM 课 C13 的采样岔路。这一课就是「用统计说话」。
先自己设计:跑一次,看成败
最省事的评测:把任务交给 agent 跑一次,测试过了就说「会修」,没过就说「不会」。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
同一套配置、只换 seed 的三次运行,并排按轮对齐(A1 的真实录制):
数据:本课项目 miniagent 的真实运行(src/data/project/agent-traces.json,2026-09-26 导出;模型 Qwen/Qwen3-8B-MLX-4bit,本机 mlx_lm.server)。token 数取自服务端 usage;思考截取约 600 字、正文与工具输出约 900 字(保留头尾)。耗时受本机同时运行的其他任务影响,只能粗看;token 与轮数才可比。
失败不在「跑得不够认真」,而在一次运行只是一次抽样。要回答「会不会修」,得先说清楚问的是哪个问题:
- 允许重试、只要有一次修好就行(例如人在旁边看着,不行就再跑一次)——问的是 pass@k:k 次里至少成功一次的概率;
- 每次都得修好(例如无人值守地跑在 CI 里)——问的是 pass^k:k 次全部成功的概率。
两者用的是同一个单次成功率 p,讲的是相反的两个故事。
试三件事:① 停在第 2 轮:三列第 1 轮都调了 list_dir、拿到同样的结果,第 2 轮的请求都是 990 token;分叉出在第 2 轮的回复——s1 先跑测试,s2、s3 先读源文件;② 拖到 s1 的第 6、7 轮:第 6 轮改了第二处 bug,第 7 轮又把同一行改了一遍(+ 1 加了两次),第 8 轮没有重跑测试就收工;③ 看 s2、s3 的倒数第二轮:都是跑过测试、看到通过才停。
改进一:重复 k 次,算两个数
本课项目里,配置与 pd-v2-unlimited 相同、只是轮数上限不同(不设 / 20 / 30)且每次都没碰到上限的运行共有 7 次:A1 的 4 次加上 T6 的 3 次,通过 6 次。把它们当作同一个 agent 的 7 次独立试验,单次成功率的点估计 p̂ = 6 / 7 = 0.857:
数据:本课项目 T6(2026-09-26 录制,本机 Qwen3-8B-MLX-4bit)与 A1 同配置运行。两个公式都假设各次试验相互独立、成功率相同;无偏估计的写法与 Harbor 0.23.0 的 pass_at_k.py 相同(本页 JS 与 Harbor 自己的函数在 440 组 (n, c, k) 上逐一比对一致)。
试三件事:① 默认是合并样本 6 / 7:把 k 从 1 拖到 10,蓝线升、紫线降;② 点「Anthropic 的例子」,k 拖到 3,核对 42%;③ 点「贯穿任务 · T6 3/3」:p̂ = 1,两条线都贴在 1 上——三次全过,公式就说「永远都会过」。这显然说多了,下面的「区间」回答它到底说明了多少。
空心点是另一种算法:不先估 p,而是直接从「n 次里成功 c 次」算——从 n 次结果里不放回地抽 k 次,至少一次成功的概率是 1 − C(n−c, k) / C(n, k),全部成功的概率是 C(c, k) / C(n, k)。前者就是 LLM 课 C12 岔路 B1 推过的无偏估计 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条从 n 个样本里不放回地抽 k 个、至少一个正确的概率,期望等于真实的 pass@k;pass^k 的写法同理(超几何分布)。前提仍是各次试验独立同分布。 出处LLM 课 C12 岔路 B1 ↗ ;k 不能超过 n。
改进二:k 次也只是 k 次——看区间
3 次全过,p 最低可能是多少?用二项分布反过来问:p 取多小时,「3 次全过」这件事的概率只剩 2.5%?这就是 95% 的精确区间(Clopper–Pearson)的下界:
数据:本课项目 T6(2026-09-26 录制,本机 Qwen3-8B-MLX-4bit)与 A1 同配置运行。两个公式都假设各次试验相互独立、成功率相同;无偏估计的写法与 Harbor 0.23.0 的 pass_at_k.py 相同(本页 JS 与 Harbor 自己的函数在 440 组 (n, c, k) 上逐一比对一致)。
试三件事:① 默认 3 / 3:p ∈ [0.292, 1],推出的 pass^3 最低只有 2.5%;② 点「TB 单个任务 0/3」:p 最高仍可能是 0.708——三次都没过,不能说明「这个任务它做不了」;③ 点「TB 合计 0/15」:上界降到 0.218,但这是把 5 个不同任务当成同一个 p 算的,只能当粗略的上界。
3 / 3 的点估计是 1,可 p 的 95% 区间是 [0.292, 1]。要让「连续全过」把区间下界推过 0.5,至少要连续 6 次。本课项目的合并样本 6 / 7,区间是 [0.421, 0.996]——比 3 / 3 更能说明问题,因为多了 4 次,还包含一次失败。
改进三:不同任务不能共用一个 p
有了 k 次重复,自然想在一个任务集上报一个数:先算全体的平均成功率,再套公式。Terminal-Bench 4.0 官方榜每一行都报了 pass@1 到 pass@5(66 个任务 × 5 次),正好拿来检验这个做法:
数据:tbench.ai 的 Terminal-Bench 4.0 官方榜(页面内嵌 JSON,更新于 2026-09-21,2026-09-27 抓取);每行 330 个 trial = 66 个任务 × 5 次,pass@k 为榜单自报。每行由谁跑页面没有写(自跑性质未核实)。公式与榜单都由本组件现算 / 转录,没有手写的数。
榜首行 Codex + GPT-6 Astra(max)的 pass@1 是 58.18%:套公式,pass@5 = 1 − (1 − 0.5818)⁵ = 98.7%;榜单实测 71.2%。全榜 27 行,套公式都比实测高,差 13.6 到 35.8 个百分点。
原因就是公式的前提「每次成功率相同」在任务之间不成立:有的任务几乎每次都过,有的几乎从不过。前者再多试几次也不会更好,后者试 5 次也碰不上;用全体平均的 p 去算,等于假设每个任务都是「一半一半」,于是大大高估了多试几次的收益。Anthropic 的原文也写着:「每个任务有自己的成功率——一个 90%,另一个 50%」 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条算法性质:若各任务的 p_i 不同,平均的 pass@k = 平均(1 − (1 − p_i)^k),由于 1 − (1 − p)^k 是 p 的凹函数(k ≥ 2),按 Jensen 不等式它不大于 1 − (1 − 平均 p)^k。所以「先平均再套公式」只会高估,不会低估——榜单 27 行全部高估与此一致。 出处待补 。
正确的顺序是先在每个任务上算,再对任务平均。Harbor 0.23.0 就是这么写的——也就是本课项目在第 4 课用的那一版:
本章组件里的 JS 是这几行的逐行移植,和 Harbor 自己的函数在 440 组 (n, c, k) 上逐一比对一致(误差 2×10⁻¹⁶,见 test_a09_pure.mjs)。
极小真数字:0 / 15 与 3 / 3 各说明了什么
本课 agent 在第 4 课的 Terminal-Bench 2.0 上是 0 / 15(5 个任务各 3 次),在贯穿任务上 T6 是 3 / 3。同一个 harness、同一个模型,为什么差这么远?三个常被拿来解释的因素,各自能说明什么、不能说明什么:
| 因素 | 能说明的 | 不能说明的 |
|---|---|---|
| k 次重复 | 两边都不是「碰巧一次」:每个 TB 任务 3 次全失败,p 的 95% 上界 0.71;贯穿任务合并样本 6 / 7,下界 0.42 | 为什么失败;k = 3 时单个任务的区间仍很宽,TB 上「完全做不了」与「三成能做」分不开 |
| 任务难度 | parse_date 是本课自己设计的小任务(约 4 步能修好);TB 任务是真实的终端活,作者估专家要 5 / 20 / 20 / 45 / 75 分钟 | 难度标签是给人定的:fix-git 标 easy、专家 5 分钟,本课 agent 3 次都没过 |
| 模型规模 | 本机是 8B、4bit 量化的模型;regex-log 三次都在思考里写满 4,096 个输出 token,一次工具都没调 | 本章没有同一 harness 下更大模型的对照,「8B 太小」只是假设;4,096 这个上限是 harness 定的,也在起作用(第 2、3 课) |
pass@k 只要求 k 次里有一次成功。合并样本的 pass@3 已经是 99.7%,可 pass^3 只有 63.0%——每 3 次无人值守的运行里,约有 37% 的机会至少错一次。要回答「能不能放心交给它」,看 pass^k。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 一次运行只是一次抽样;重复 k 次,把「会不会」拆成能力(pass@k)与可靠(pass^k)两个可以回答的问题 |
| ② 数学上为什么成立? | 两个公式在「独立、同一个 p」的前提下直接推出 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条P(至少一次成功) = 1 − P(全失败) = 1 − (1 − p)^k;P(全成功) = p^k。前提不成立(不同任务 p 不同)时,「先平均再套」必然高估 pass@k(凹函数的 Jensen 不等式)。 出处待补 ;精确区间由二项分布直接反解 |
| ③ 实验上呢? | 本课项目:同配置换 seed 一次 ✗ 两次 ✓,合并样本 6 / 7 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条项目实测:单一 8B 本地模型(Qwen3-8B-MLX-4bit),贯穿任务一个;这 7 次的轮数上限不同但都没碰到。数字只在这个规模成立。 出处待补 ;TB 4.0 榜 27 行,套公式全部高估 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条官方榜自报的 pass@k,每行由谁跑页面没写(自跑性质未核实);高估这个方向与数学推论一致。 出处tbench.ai 官方榜(2026-09-27 抓取) ↗需联网 |
演进地图:你在这里
- 起点 跑一次,看成败最直觉的做法:一个任务、一次运行、一个布尔值解决了最省事:修好了就说「会修」,没修好就说「不会」。卡在同一套配置只换 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 构建时现算。
一句话
先停在这里:记住三件事——pass@k 升、pass^k 降;3 / 3 的区间下界只有 0.29;任务集上先按任务算再平均。
再深一层:去岔路 B1:能力在按什么速度增长——METR 把「成功率」换成「能做多长的活」,拟合用的也是这一课的思路:成功率随任务变化,要按任务一个个算。
下一个缺口
分数高,是模型强还是 harness 强? → 第 2 课:分数高,是模型强还是 harness 强?
重复够多次,分数稳了;可这个分数属于谁?本课的 agent = Qwen3-8B × miniagent × 一组配置。换一个 harness,分数会变多少?
你可能会问
- 「那该跑几次?」 看你要回答的问题。想把「连续全过」的区间下界推过 0.5,至少 6 次;想比较两个配置,还要看它们的区间是否重叠。本课项目选 k = 3 是预算决定的(本机一个 TB trial 约 1–9 分钟,只能粗看),它能说明的有限,上面的表写清了。
- 「固定 seed 不就能复现了吗?」 A0 第 3 课看过:同 seed 也会因为工具输出里的几个 token 分叉。而且评测想量的是「这个 agent 的成功率」,固定 seed 等于只量了一次抽样。T6 的 Harbor 运行特意没固定 seed:同一组参数会传给每次 attempt,固定了 k 次就几乎一样。
- 「pass@k 的无偏估计为什么是那个样子?」 推导在 LLM 课 C12 岔路 B1,那一课用它讨论「RL 是扩展能力还是重排」;这里的 Harbor 源码第 87–94 行是同一个公式的连乘写法。