
01 一道评测题,得带上环境和验收方法
假设我们出一道题:修复解析器的边界问题,保留旧 API,不许改测试。 把这句话写进 prompt 还不够。仓库在哪个 commit?依赖装好了吗?Agent 能联网吗?如果上次运行已经生成了修复文件,这次就不是从同一个起点开始了。 我会把这些条件放进一个任务包:指令、初始环境、允许的操作、预算,以及验收程序。模型、Harness 和评分器的版本各自记录,只留一个仓库 commit 往往对不上完整的运行条件。任务包可以长这样:02 Runner 的工作不止是启动进程
这里约定一下名字:task 是一道题,trial 是某个版本做这道题的一次尝试。每个 trial 都拿到独立的运行环境、数据目录和产物目录。上一次的记忆、登录配置、缓存和后台进程,不能悄悄影响下一次。 Runner 按下面几个阶段执行。状态变化要落盘,调度器重启后才能知道哪些还没开始、哪些仍在跑、哪些只差评分。重复执行一次任务会多花钱,也可能让结果混进两次运行的产物。
03 用真实的 MiniMax Code 跑任务
适配器只做启动、读输出、停止和收集产物这些事。工具调度、上下文压缩、模型重试继续交给 MiniMax Code。为了方便评测重写一套执行循环,可能把最想测的 Harness 行为也换掉了。 MiniMax Code 已有mcode exec,可以指定工作目录、配置、超时和步数上限,并输出 stream-json。在准备好的隔离环境里,启动方式如下。变量由 Runner 填入,使用前需要准备对应的目录和配置。
schemaVersion、sequence,以及 runId、sessionId、turnId。适配器验证事件的版本、身份和顺序,按 item ID 合并增量,同时保存原始流。遇到截断行、重复终态或错误的 runId,要留下异常记录。
终态事件 exec.completed 携带执行结果。status: succeeded 只说明这次执行成功结束,代码有没有改对,仍要验收。--output-schema 也只校验最终回答的结构。回答 JSON 再规整,测试照样可能失败。
还会有连终态都来不及输出的情况,比如预检失败或进程崩溃,所以退出码和 stderr 要一起收集。Headless 运行如果卡在需要人回答的问题上,就按预先约定的无人值守或交互任务规则处理;临时帮其中一组回答,会改变实验条件。
接适配器时,可以直接对照 CLI 契约、事件投影和结果类型。
04 测试全绿,也得看是谁改的测试
Agent 能改工作区里的测试、构建脚本和依赖。它输出一行“全部通过”,甚至真的把测试跑绿了,都还不足以验收。 对代码修改任务,我会先冻结最终工作区,由宿主检查受保护文件、文件类型和修改范围,再把允许交付的变更放进干净的验收环境。镜像、测试入口和隐藏测试由评测侧固定。候选代码仍然不可信,运行它的 Verifier 也需要隔离。 导出产物时也有细节。只存一份普通 Git diff,可能漏掉未跟踪文件、二进制文件、权限变化或符号链接。产物协议得把这些写清楚。如果交付的是服务状态或数据库变更,还得保存相应快照,并从外部检查实际行为。
accepted 仍是 false。这是数据结构示例,不是真实跑分。
05 拿一次压缩改动做实验
现在有了运行和验收流程,可以回到开头那个问题:改进 checkpoint 里保留用户约束的方式,能不能减少压缩后的约束违背? MiniMax Code 的压缩实现已经有工具输出归档、checkpoint,以及程序附加近期状态等机制。这次只改约束的保留方式,其他提示词、归档阈值、模型和预算保持一致。几处一起改,即使效果好了,也很难判断是哪处起了作用。 这个实验我会分两层做。先检验局部机制:等工具调用结算、后台写入停止,在压缩前保存一份共同状态,让基线和候选分别从这里继续。观察用户约束是否还在、早先的证据能否读回,以及后面有没有重复劳动、能否完成任务。 这份状态不能只有 messages。工作区、会话、压缩状态和后续会引用的归档产物都要恢复;依赖数据库或外部服务的任务,还要恢复那些资源。归档文件在原机器上能读到,换了目录之后引用失效,也会影响实验。公开 CLI 目前不能直接一键完成这套分叉,需要另做触发压缩和恢复状态的测试接口。 然后从任务起点再跑端到端实验,用实际部署的上下文容量和触发策略。候选版本可能更早触发压缩,也可能少读几次文件、换一种工具调用顺序。这些变化都是完整策略的效果,要算进去。
06 分数之外,要留下哪些记录
某道题退步了,我希望能找到它读过什么、调用过哪些工具、在哪一步偏离了要求。评分器改了,也应该能拿旧产物重新验收。这是评测里做可观测性的实际用途。 记录可以按用途分开存。运行清单保留版本与实验条件,轨迹保留模型和工具事件,产物目录保存最终文件、环境快照与验收输出。重新评分时给出新的 grade revision,关联同一个冻结产物,不覆盖旧分数。 运行清单里只写模型名字不够。还需要模型配置和能拿到的服务版本、Harness commit、展开后的 prompt 与工具 schema 指纹,以及任务、评分器版本。权限策略、资源与预算、实验组和重复编号也要能查到。服务端版本固定不了,就记录运行时间窗口,把这个限制带进分析。 MiniMax Code 的 eval reporter 已有模型调用前快照、工具调用与结果、usage 和回合结束等采集接口。采集失败不会中断 Agent 的正常运行,这个取舍适合产品;放进评测之后,还得补上证据完整性标记。日志里没有某次调用,可能只是没采到。 用量也会缺失。ExecResult 里的 usageSource 和 usageIncomplete 就是为这类问题保留的信息;失败、压缩等场景下,账目可能不完整。算成本时,未知部分保留未知,能确认的费用记作下界。把缺失填成零会低估成本;把可能重叠的缓存、推理和总 token 字段直接相加,则可能多算。
失败怎么处理,也要提前定。下面这张表是一种可用的约定:
用尽预算和机器故障看起来都可能是“进程没了”,需要靠事件与资源记录区分。每次重试保留原 trial、原因和新的 attempt ID。报告里同时给出基础设施错误率和任务覆盖率,否则删掉几次失败,分数就好看了。
补跑达到上限仍没有有效评分,就报告缺失和它对结论的影响。模型调用失败也不能一律归为外部故障:如果这次评测要考察 Harness 的恢复能力,它本来就在考题里。哪些情况排除,按实验开始前的约定处理。
07 怎样比较两个版本
A/B 两组先对齐任务、模型配置和预算,在同一时间窗口内随机交错运行。并发度、限流、冷暖缓存也要一致。一组上午跑、一组晚上跑,服务波动就可能混进版本差异。 资源分配本身也要控制。Anthropic 的基础设施噪声研究讨论过资源配置对 Agent 编程评测的影响。所以 CPU、内存、网络和时限都应和模型配置一起记录。 每道任务跑多少次,在开始前约定。先算同一道任务在两组中的通过比例,再比较差值。第 i 个任务的通过比例记为 pᴀ,ᵢ 和 pʙ,ᵢ;任务等权时,整体差值是 Δ = (1/N) Σᵢ(pʙ,ᵢ − pᴀ,ᵢ)。如果想按真实使用分布加权,提前定好权重。某道题多跑了几遍,不应因此在总分里更重要。
08 别把评测集调成了开发集
把真实失败收进回归集很有用。但一直盯着同一批题改 Harness,我们也会越来越熟悉这些题,分数上涨未必代表新任务做得更好。 开发集拿来复现和调参,验证集用来选候选,最终留出集等候选冻结以后再用。切分按仓库、问题家族或时间段做,防止同一道题换个名字出现在两边。留出集看得多了、拿来改策略了,就应当承认它已经是开发集的一部分。 压缩实验可以有定向任务集,但还要跑常见任务的回归,检查副作用,并定期补充新任务。只收失败案例,会让困难场景占得过多;只收适合演示的任务,又会把系统想得过于可靠。 这套评测也不必每个 PR 全跑一遍。协议、评分器和短回归先跑;改到压缩、工具或权限时,再触发相关的行为评测。昂贵的重复实验和新任务测试按预算定期安排。源码里的pnpm verify 继续检查工程正确性,真实模型的任务表现另行评测,两边各自报告。
如果现在动手,我会从一道任务开始:重置环境,启动 MiniMax Code,独立验收,留下能复查的产物。再拿几个已知好坏版本试评分器。等这些都跑通了,才增加任务数和并发。先做大规模调度,很可能只是把排查问题的难度也一起放大。
MiniMax Code 的公开源码里已经有运行入口、结构化事件和评测采集接口。想动手的话,可以接一个 Runner,也可以先贡献一道能稳定复现失败的任务,或检查评分器会不会误收坏答案。这些工作都能帮助判断下一次 Harness 改动该不该保留。
项目在 GitHub。欢迎带着复现和实验来讨论;觉得这篇有用,也欢迎点个 Star。
实现与参考入口
源码核对版本为14053355f39c。文中的任务协议、外部 Runner 和分叉实验是设计方案;本文没有运行在线模型对照实验,也不报告性能提升。