这篇重点学什么
本篇重点:固定运行环境、任务规则和结果检查器,检查训练或调试是否提前使用了测试内容;分别说明全部计划任务和实际有效运行有多少,不能悄悄丢掉异常任务。
开始读正文 ↓学过相近内容?查看哪些可以跳过
两条路线有些基础相同。已经学会的部分可以跳过,另一条路线只用来补你当前需要的内容。
数据划分与评测集
共同基础这组原则只学一次:先确定以后要处理哪些新数据,再据此给相关样本分组;同组不跨数据集,测试集不用来调参,并划清时间先后,避免测试内容的相同或近似版本提前进入训练。
另一条路线补充什么?
写清系统允许和禁止做什么,把同一原始案例的变体归为一组,记录失败类型,并固定回归测试的版本与通过条件。
读完这篇,你能做什么
运行修复与回归检查的小环境,Java拒绝缺失或重复试验记录并计算两种聚合指标。
学习理由、准备要求与知识点
为什么学它
只看最终文字或成功截图,无法判断实际执行能力。遗漏失败或异常记录,还可能让成功率看起来比实际更高。
先读这些内容
知识点清单
- 任务与环境快照
- 独立成功oracle
- 修复与回归检查
- 重置及种子
- 终止和预算耗尽
- 基础设施异常
- 微平均与宏平均
- 测试泄漏与隔离
运行前先确认SWE-bench论文v3与WebArena论文v3;Java17、Python3.14标准库的独立教学环境。未运行公开基准、容器或外部模型。
01先弄懂它是什么
比较两个 Agent 之前,要先确认它们在做同一种任务。例如“真的修改订单总额”和“说出总额应该怎样修改”,验收方法完全不同。一个可执行基准需要规定任务从哪里抽取、环境起点是什么、允许哪些动作、预算多少、怎样算成功。最好把这些约定写成程序可检查的规则;否则最终文字看起来都合理,实际完成的工作却可能不一样。
判断任务是否完成,应由独立于被测策略的检查器负责,这常叫成功 oracle。代码任务可以运行指定测试,网页任务可以检查页面或后台状态。但检查器也可能漏掉要求,测试全过仍不一定涵盖所有真实目标。因此要保存检查器版本和它能看到的信息,并单独分析那些“通过了检查,却没有完成用户目的”的情况。
试验需要区分成功、策略失败、预算超时与基础设施异常。基础设施异常可能让任务未真正开始,和模型做错不是一回事,但不能悄悄丢掉这些记录后只展示剩余高分。预先定义重跑规则、报告有效试验覆盖率,并保持每个计划任务都有记录,才能解释分数的真实分母。
文中这几个词,先认一认
- Oracle
- 按任务实际状态判断成功或失败的一套独立规则或测试,不由被测策略自己宣布结果。
- 回归检查
- 修改或修复之后,重新确认以前已经正确的行为没有被破坏。
- 宏平均
- 先分别算每个预先定义分组的指标,再给各组相同权重求平均,避免大组单独主导总分。
02看看它怎么工作
SWE-bench把问题描述和代码快照作为输入,对候选补丁执行测试;修复相关失败测试与保持原有通过测试都重要。WebArena提供可交互网页环境,并按任务结果设计评价。二者说明Agent能力应落在环境行为与结果上,但它们的任务范围不同,不能用其中一个分数推断所有软件或网页工作都能胜任。
本文Python只有受控字典状态:总额最初为零,要求改成数量乘单价,同时币种保持USD。动作可修改指定字段,自述成功被忽略;每次重新复制初始状态,按动作步数限制预算。检查器分别验证修复与回归,因此“改对总额却改坏币种”仍失败。它没有执行不受信任代码,也没有提供安全沙箱。
Java按预声明任务清单核对结果映射,缺失、未知或重复ID直接拒绝。operational使用成功数除所有计划任务,反映完整运行的可交付比例;validRate排除显式INFRA后给出条件成功率,并同时报告异常数量。macro先对每个分组算完整分母比率再平均,两种指标回答不同问题,不能任意挑高者作为主结论。
先跑通一个最小例子
Python3.14标准库执行experiment.py,字典状态模拟修复和回归检查;没有执行生成代码或真实网页动作。
from copy import deepcopy
TASK={"quantity":2,"price":3,"currency":"USD"}
INITIAL={"total":0,"currency":"USD"}
def evaluate(actions,budget=2,healthy=True):
if type(budget) is not int or budget<1: raise ValueError("budget")
if not healthy: return "INFRA",None
state=deepcopy(INITIAL) # 每次试验从同一初始状态开始。
for index,action in enumerate(actions):
if index>=budget: return "TIMEOUT",state # 这是步数预算,不是墙钟超时隔离。
if not isinstance(action,dict) or len(action)!=1: return "FAILURE",state
key,value=next(iter(action.items()))
if key=="claim_success": continue # 代理自述不替代独立结果判定。
if key=="total" and type(value) is int: state[key]=value
elif key=="currency" and isinstance(value,str): state[key]=value
else: return "FAILURE",state
repaired=state["total"]==TASK["quantity"]*TASK["price"]
unchanged=state["currency"]==INITIAL["currency"]
return ("SUCCESS" if repaired and unchanged else "FAILURE"),state
assert evaluate([{"total":6}])[0]=="SUCCESS"
assert evaluate([{"total":5}])[0]=="FAILURE"
assert evaluate([{"total":6},{"currency":"EUR"}])[0]=="FAILURE"
assert evaluate([{"claim_success":True}])[0]=="FAILURE"
assert evaluate([{"total":6},{"claim_success":True}],budget=1)[0]=="TIMEOUT"
assert evaluate([{"total":6}],healthy=False)[0]=="INFRA"
assert evaluate([{"total":6}])[1] is not evaluate([])[1] and INITIAL["total"]==0
assert evaluate([{"total":True}])[0]=="FAILURE"
print("PASS 8 checks; reset, repair, regression, budget and infrastructure separated")
核对运行结果PASS 8 checks,覆盖正确修改、错误结果、回归、预算、重置和基础设施分类。
正在加载流程图…
查看流程图源码(Mermaid)
flowchart TD
N0["固定任务初始状态和预算"]
N1["重置环境并记录可见输入"]
N2["受控执行并区分结束原因"]
N3["独立检查目标和回归条件"]
N4["核对记录完整性后聚合报告"]
N0 --> N1
N1 --> N2
N2 --> N3
N3 --> N4按顺序看,每一步做了什么
- 固定任务初始状态和预算
- 重置环境并记录可见输入
- 受控执行并区分结束原因
- 独立检查目标和回归条件
- 核对记录完整性后聚合报告
03对照实现代码
SWE-bench论文 arXiv:2310.06770v3 · Section 2.2与Appendix A.4评价流程
原创执行判定模型,参考固定论文;未运行SWE-bench容器或WebArena服务。
def resolved(after, fail_to_pass, pass_to_pass):
eligible = bool(fail_to_pass) # 本教学任务要求至少有一个待修复测试。
repaired = all(after.get(name, False) for name in fail_to_pass) # 缺失测试结果不视为通过。
preserved = all(after.get(name, False) for name in pass_to_pass) # 保持原有功能也属于判定条件。
return eligible and repaired and preserved
固定论文描述从真实问题与补丁构建任务,再在指定代码状态上应用候选补丁并运行测试。本文短函数是修复加回归判定的原创布尔模型,after中的值被约定为已经解析好的布尔通过状态,不能把任意非空错误字符串直接传入并依赖Python真值判断。
真实harness还处理补丁是否可应用、环境构建、命令执行、日志解析和测试状态分类。作者grading.py可对照get_eval_report、get_resolution_status等流程;main链接是阅读入口,基线固定到论文,不把几行all判断冒称完整框架源码或安全执行器。
环境失败发生在不同阶段时要保留原因:构建失败、日志缺失、运行超时与断言失败各自需要诊断。本文选择单列INFRA并报告两种分母,不宣称这是任何官方榜单默认规则。复现实验应遵守所使用基准的明确规则,不能自行换算后继续沿用官方指标名称。
可重复环境也不能自动避免污染。模型可能见过公开问题、测试或解决补丁,实验设计还需说明数据时间范围与可见材料。本文不下载公开任务集,不运行真实仓库补丁,独立小环境只验证重置和判定逻辑,不能报告为SWE-bench或WebArena成绩。
代码先调用谁,再调用谁
- 准备指定任务快照
- 应用候选修改并运行测试
- 解析修复与保持状态
- 生成含失败原因的任务报告
04动手写一个例子
预声明任务清单的完整性审计与聚合
对任务ID和分组清单逐一匹配结果,计算所有计划任务成功率、分组宏平均、排除基础设施异常的条件成功率。
- 输入 1
A组三题成功1,B组一题成功1- 输出 1
整体.5,宏平均2/3
- 输入 2
两题一成功一INFRA- 输出 2
完整比例.5,条件比例1,异常1
先扫描任务清单建立唯一ID集合与分组计数,再从结果映射读取每项状态。每个计划任务必须有且只有一个结果;清单重复ID、结果缺失和额外未知ID都拒绝。这样可以阻止用不完整日志计算看似精确的成功率,输入清洗错误不会被静默隐藏。
每完成一个任务,success是此前成功项数,infra是基础设施异常项数,每组数组保存成功和总数。遍历结束后整体比率按任务等权,宏平均按组等权;超时在这两项和条件成功率中都作为未成功保留。全部INFRA时条件分母为零,返回OptionalDouble.empty而非伪造零或一。
哈希容器的期望常数查找使期望时间为O(N+G),其中N为任务数、G为组数;额外ID集合和组表为O(N+G)。这个复杂度不包括生成或运行任务,也不保证恶意哈希分布下严格线性。统计汇总再快,也不能补救不一致的执行预算。
为什么这样写是对的已处理任务恰好一次计入对应组与全局计数,结果映射不允许缺失状态。
扫描N条任务并汇总G个分组;依赖哈希集合与映射的平均查找成本。
保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。
展开收起代码 · Main.java · 完整可运行程序
长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。
import java.util.*;
public class Main {
static void near(double expected,double actual) {
if (!Double.isFinite(actual) || Math.abs(expected-actual)>1e-9*Math.max(1,Math.abs(expected)))
throw new AssertionError(expected+" != "+actual);
}
static void check(boolean ok) { if(!ok) throw new AssertionError(); }
static void bad(Runnable r) {
try { r.run(); } catch(IllegalArgumentException e) { return; }
throw new AssertionError("invalid input accepted");
}
enum Status {SUCCESS,FAILURE,TIMEOUT,INFRA}
record Task(String id,String group) {}
record Report(double operational,double macro,OptionalDouble validRate,int infrastructure) {}
static Report report(List<Task> tasks,Map<String,Status> results) {
if(tasks==null||tasks.isEmpty()||results==null) throw new IllegalArgumentException("empty");
Set<String> ids=new HashSet<>();Map<String,int[]> groups=new HashMap<>();int success=0,infra=0;
for(Task t:tasks) {
if(t==null||t.id()==null||t.group()==null||t.id().isBlank()||t.group().isBlank()||!ids.add(t.id())) throw new IllegalArgumentException("task");
Status s=results.get(t.id());if(s==null) throw new IllegalArgumentException("missing"); // 缺失日志不静默当作有效完成。
int[] counts=groups.computeIfAbsent(t.group(),x->new int[2]);counts[1]++;
if(s==Status.SUCCESS) {success++;counts[0]++;}
if(s==Status.INFRA) infra++; // 基础设施异常单列,同时保留预声明任务总分母。
}
if(results.size()!=ids.size()) throw new IllegalArgumentException("unknown task");
double macro=0;for(int[] c:groups.values()) macro+=(double)c[0]/c[1]; // 先求每组比率再等权平均,与全体任务比例不同。
int valid=tasks.size()-infra;
return new Report((double)success/tasks.size(),macro/groups.size(),valid==0?OptionalDouble.empty():OptionalDouble.of((double)success/valid),infra);
}
public static void main(String[] args) {
List<Task> ts=List.of(new Task("a1","A"),new Task("a2","A"),new Task("a3","A"),new Task("b1","B"));
Report r=report(ts,Map.of("a1",Status.SUCCESS,"a2",Status.FAILURE,"a3",Status.TIMEOUT,"b1",Status.SUCCESS));
near(.5,r.operational());near(2.0/3,r.macro());near(.5,r.validRate().orElseThrow());
Report i=report(List.of(new Task("a","G"),new Task("b","G")),Map.of("a",Status.SUCCESS,"b",Status.INFRA));
near(.5,i.operational());near(1,i.validRate().orElseThrow());check(i.infrastructure()==1);
check(report(List.of(new Task("a","G")),Map.of("a",Status.INFRA)).validRate().isEmpty());
near(0,report(List.of(new Task("a","G")),Map.of("a",Status.TIMEOUT)).operational());
bad(()->report(ts,Map.of()));
bad(()->report(List.of(new Task("a","G")),Map.of("a",Status.SUCCESS,"x",Status.SUCCESS)));
bad(()->report(List.of(new Task("a","G"),new Task("a","H")),Map.of("a",Status.SUCCESS)));
bad(()->report(List.of(),Map.of()));
System.out.println("PASS 8 cases");
}
}
这些特殊情况也要试一试
- 全部INFRA返回空条件指标
- 超时保留在失败分母
- 缺失和额外ID拒绝
- 重复ID拒绝
进阶选读 · 并行可执行基准的隔离与成本对照
场景任务可能运行不受信任代码、耗尽资源或污染后续环境。
做法使用独立受限运行环境、固定镜像和数据快照,实施墙钟与资源上限,结束后回收;并行度和重试协议纳入实验配置。
复杂度N次执行耗时取决于单题时长与并行度,调度隔离和镜像准备需另外测量,不能由O(N)汇总算法推断吞吐。
好处与代价隔离提高可控性但增加启动成本;真实安全边界需要容器或更强机制评估,普通字典与子进程不是完整沙箱。
05项目里怎么用
建立自有基准时先从少量人工核对的任务开始,确认失败版本确实失败、参考修复确实成功、回归条件确实能抓住破坏。之后再扩大规模,避免一千个错误标签比十个正确任务更“客观”的错觉。记录任务来源和覆盖边界,固定主指标及预算后再比较方法。
要把执行层日志与模型可见观察分开存放。隐藏检查可用于最终评价,但不应在调参循环中不断反馈具体答案;开发集可反复调试,最终保留集只用于确定配置后的评价。公开测试的通过情况可作为反馈,仍需防止修改测试或利用检查器漏洞绕过目标。
报告中要同时列出原计划测试多少题、实际跑了多少题、各类结束原因,以及总体和分组指标。若基础设施总在难题上出故障,只统计跑完的题,就可能让成功率偏高,不能拿它代表全部任务能力。本篇仅验证合成状态机和汇总公式;真实环境能否恢复、是否隔离,以及模型调用是否可靠,还需分别验收。
容易踩的坑
- 代理自述成功替代环境检查
- 每轮未重置导致状态污染
- 只跑修复测试忽略回归
- 删掉超时和异常后夸大成功率
- 把测试全过说成完整语义证明
几种做法,怎么选
表格有四列,窄屏可左右滑动查看代价和适用条件。
| 方案 | 优势 | 代价与限制 | 适用条件 |
|---|---|---|---|
| 纯文本评价 | 成本低、易扩展 | 不能证明动作生效 | 解释和生成质量初筛 |
| 可执行任务 | 结果有直接状态证据 | 环境与oracle维护复杂 | 代码和业务操作评估 |
| 人工复核加自动检查 | 能发现检查器盲区 | 成本高且需一致标准 | 高价值失败分析与标签审计 |
06检验是否读懂了
先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。
先用自己的话解释
01为什么检查最终环境?
展开参考答案与推导
可执行任务要求状态变化,语言承诺本身不证明动作生效。
02宏平均为何不同?
展开参考答案与推导
它给每个分组相同权重,整体比例给每个任务相同权重。
03全部基础设施异常能算能力零吗?
展开参考答案与推导
本协议的条件能力指标不可计算,应报告无有效试验;完整交付比例可为零但含义不同。
换个情况,还会处理吗
01只修新测试破坏旧测试?
展开参考答案与推导
判为未满足完整要求,同时记录修复与回归结果帮助定位。
02一半任务日志缺失?
展开参考答案与推导
先拒绝聚合并恢复完整记录,不能将剩余任务默认代表总体。
03基准分数很好却真实工作差?
展开参考答案与推导
检查任务覆盖、污染、预算和oracle漏洞,并在目标场景建立新保留集。
写代码试一试
01计算宏微指标。
- 输入 / 条件
A组三题1成功,B组一题1成功- 输出 / 预期
微.5,宏2/3
提示 先分组再平均
展开参考答案与推导
组成功率分别1/3和1,再求等权均值。
02处理基础设施分母。
- 输入 / 条件
一成功一INFRA- 输出 / 预期
完整.5,条件1且异常1
提示 同时报告覆盖
展开参考答案与推导
不静默删除异常,也不将两种指标混名。
03阻止自述作弊。
- 输入 / 条件
动作只包含claim_success- 输出 / 预期
FAILURE
提示 最终状态oracle
展开参考答案与推导
忽略声明,根据总额和币种检查目标。
读完之后,独立完成
课后作业:自己做一遍
本篇共 12 道作业,先完成 9 道基础与综合任务,再按前置知识挑战进阶题。其中包含 2 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。
运行修复与回归检查的小环境,Java拒绝缺失或重复试验记录并计算两种聚合指标。
本篇重点加练
独立判定、异常归因和隔离决定基准可信度,重点测试高分是否依赖验收漏洞。
- 独立成功oracle
- 基础设施异常
- 测试泄漏与隔离
重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。
先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。
基础必做
- 作业 01原理问答
为一个可在临时目录运行的文件修复任务定义初始快照、提交物、独立成功 oracle 和回归检查,列出代理自述不能替代的证据。
- 提交内容
- 任务规格与验收表
- 怎样算完成
- oracle 独立于代理叙述
- 旧功能回归包含在内
练到的知识点任务与环境快照 · 独立成功oracle · 修复与回归检查
- 作业 02代码推演
自建六次运行记录,包含成功、功能失败、预算耗尽、环境启动失败与日志缺失;声明每类如何进入各报告分母。
- 提交内容
- 结果账本与分母表
- 怎样算完成
- 未知与失败区分
- 未完成运行没有被静默删除
练到的知识点重置及种子 · 终止和预算耗尽 · 基础设施异常
- 作业 03原理问答
同一任务存在多个合法实现。自行构造两个外观不同但满足需求的提交,审查结果判定器(oracle)是否把参考实现的细节误当成任务要求。
- 提交内容
- 合法实现对与结果判定器(oracle)审阅
- 怎样算完成
- 先规定功能要求,再考虑实现形式
- 误拒绝案例可执行
练到的知识点独立成功oracle
综合应用
- 作业 04编程实践
实现 CPU 基准执行器,在专用临时目录内重置三个小任务并执行只读验收;保存环境版本、种子和产物摘要。
- 提交内容
- 执行器与重复运行报告
- 怎样算完成
- 任务间状态隔离
- 临时路径与超时边界明确
练到的知识点任务与环境快照 · 独立成功oracle · 重置及种子
- 作业 05排错实验
向基准注入过宽测试、残留文件和可读取标准答案三类漏洞,用反例检查原有高分是否可信。
- 提交内容
- 故障实验与修补验证
- 怎样算完成
- 成功判定能识别作弊
- 修补保留合法解覆盖
练到的知识点修复与回归检查 · 基础设施异常 · 测试泄漏与隔离
- 作业 06面试场景
两个任务家族的题数分别为 3 和 9,各方法成功分布不同。自建逐题结果,比较微平均与宏平均并写出适用目标。
- 提交内容
- 逐题数据与两种统计
- 怎样算完成
- 任务家族权重公开
- 样本量差异不被掩盖
练到的知识点基础设施异常 · 微平均与宏平均
- 作业 07编程实践
实现 CPU oracle 自测集,包含正确解、局部错误解、超时及验收器自身异常,输出任务结果与评价器健康状态两个字段。
- 提交内容
- 自测程序与分类记录
- 怎样算完成
- 任务失败与判定失败区分
- 已知样例独立于被测代理
练到的知识点独立成功oracle · 基础设施异常
- 作业 08排错实验
让两个临时目录任务共享一个缓存文件,注入前一任务残留答案,比较隔离前后的评价;所有测试仅使用自建无敏感数据。
- 提交内容
- 污染复现及隔离验证
- 怎样算完成
- 数据读写路径可追踪
- 状态重置验证实际发生
练到的知识点基础设施异常 · 测试泄漏与隔离
- 作业 09设计评审
基准允许代理看到单元测试,但要求隐藏最终验收。设计公开与保留测试的职责边界,说明哪些修改属于合理修复、哪些会破坏评价身份。
- 提交内容
- 测试资产清单与访问契约
- 怎样算完成
- 公开信息合法范围明确
- 最终 oracle 身份稳定
练到的知识点独立成功oracle · 测试泄漏与隔离
进阶挑战 · 掌握前置后选做
- 作业 10设计评审
制定基准升级后的可比性协议,包括旧新环境交叉运行、任务变更记录和保留集隔离;明确何时不能沿用历史排名。
- 提交内容
- 版本比较协议
- 怎样算完成
- 难度和环境变化分开
- 结论依据可审计
练到的知识点任务与环境快照 · 终止和预算耗尽 · 测试泄漏与隔离
思维拓展
先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。
- 作业 11思维拓展 · 条件变化
如果 oracle 本身有小概率误判,任务成功率与模型能力的关系如何变化?自建已知真实标签的 CPU 模拟,比较不同误判率下的观测。
- 提交内容
- 误判模拟与识别边界
- 怎样算完成
- 真实标签与观测标签分开
- 无法辨识参数明确列出
练到的知识点独立成功oracle · 基础设施异常
- 作业 12思维拓展 · 跨域迁移
把基准隔离迁移到编译器测试或数据库压测:缓存热身、残留状态与系统故障分别怎样影响可比性?选择一个领域做最小对照方案。
- 提交内容
- 迁移设计与证据清单
- 怎样算完成
- 状态因素具体可控
- 业务错误与环境错误分开
练到的知识点基础设施异常 · 测试泄漏与隔离
完成后,再检验一次
给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。
继续阅读
先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。
- 必读参考文档英文
SWE-bench论文v3 (新标签页)↗
阅读任务输入、执行测试与修复判定。
- 实践参考文档英文
SWE-bench grading实现 (新标签页)↗
对照报告生成及测试状态分类,main为可变入口。
- 深入参考文档英文
WebArena论文v3 (新标签页)↗
理解网页任务、可复现环境与结果评价。
- 深入参考文档英文
Gymnasium环境接口 (新标签页)↗
实践reset、step及终止和截断的独立字段。