mini-swe-agent 实战指南:在 SWE-bench 基准上批量运行与单实例调试

原创2026-09-26 18:29:25407 阅读
文章标签:人工智能大模型AI Agent代码智能体

mini-swe-agent 实战指南:在 SWE-bench 基准上批量运行与单实例调试

导读

本指南以 mini-swe-agent 仓库提供的两个官方脚本(swebench 批量模式与 swebench-single 单实例调试模式)为核心,完整讲解如何加载 SWE-bench 数据集、选择子集与切片、并行运行 Agent、收集 preds.json 预测结果,并通过云端 sb-cli 或本地 SWE-bench harness 完成评估。读完本文,你将掌握一套可复制、可扩展的 SWE-bench 评测流水线,并理解其底层实现原理(镜像选择、实例筛选、断点续跑、进度报告与异常处理)。

背景:两个脚本的分工

mini-swe-agent 针对 SWE-bench 基准提供了两个入口脚本,二者互补:

  • mini-extra swebench(批量模式):自动遍历所有任务实例(task instance),以多线程并行方式运行 Agent,产出可供评估的 preds.json 文件,适合正式跑分与批量实验。
  • mini-extra swebench-single(单实例模式):在单个任务实例上以交互方式运行,便于调试提示词、观察 Agent 行为;由于带有交互性,它不会生成 preds.json 文件。

两个脚本都位于 src/minisweagent/run/benchmarks/ 目录下,其中 swebench_single.py 通过复用 swebench.py 中的 DATASET_MAPPING 与 get_sb_environment 等公共函数来保持行为一致。如果你要构建自己的批量处理流水线,直接阅读这两个脚本的源码是最佳起点。

快速开始:批量模式(swebench)

查看帮助与最小示例

mini-extra swebench --help
# 等价于直接调用 Python 模块:
python src/minisweagent/run/benchmarks/swebench.py --help

一个典型的最小批量运行命令如下(以 verified 子集、test 分片为例):

mini-extra swebench \
    --model anthropic/claude-sonnet-4-5-20250929 \
    --subset verified \
    --split test \
    --workers 4

⚠️ 架构注意:SWE-bench 的 Docker 容器面向 x86 Linux 架构构建,在其他 CPU 架构上可能无法运行。运行前请确认你的宿主机满足该前提。

批量模式参数全解

分组 参数 说明 默认值
基础 -o, --output 输出目录(存放 preds.json、轨迹与日志) 空(当前目录)
基础 -m, --model 使用的模型名称 由配置决定
基础 -c, --config 配置文件路径;一旦指定,默认配置文件不再生效,需显式带上 swebench.yaml config 目录下的 swebench.yaml
基础 -w, --workers 并行工作线程数 1
数据选择 --subset SWE-bench 子集名或自定义数据集路径 lite
数据选择 --split 数据集分片 dev
数据选择 --slice 切片规格,如 '0:5' 表示只取前 5 个实例 空(不切片)
数据选择 --filter 按正则表达式过滤实例 ID 空(不过滤)
数据选择 --shuffle 是否打乱实例顺序 False
数据选择 --redo-existing 是否重新运行已有结果的实例 False
高级 --environment-class 环境类型(推荐 docker 或 singularity) docker
高级 --model-class 模型类(如 'anthropic' 或完整导入路径) 由配置决定

-c 的合并语义

-c 接受一个列表,多个配置会被递归合并(对应源码 swebench.py 中的 recursive_merge)。但注意:一旦你使用了 -c,内置默认配置就不会被加载,因此常用写法是先显式指定基准配置文件,再叠加自己的覆盖项:

mini-extra swebench \
    -c swebench.yaml \
    -c model.model_kwargs.temperature=0.5 \
    -c agent.step_limit=100

命令行传入的 -m/--model、--environment-class 等选项最终也会作为一份配置参与合并,因此优先级语义一致。

内置子集与数据集映射

源码 swebench.py 中的 DATASET_MAPPING 定义了可直接使用的子集名:

子集名 对应 Hugging Face 数据集
full princeton-nlp/SWE-Bench
verified princeton-nlp/SWE-Bench_Verified
lite princeton-nlp/SWE-Bench_Lite
multimodal princeton-nlp/SWE-Bench_Multimodal
multilingual swe-bench/SWE-Bench_Multilingual
smith SWE-bench/SWE-smith
_test klieret/swe-bench-dummy-test-dataset(用于测试)
rebench nebius/SWE-rebench

凡不在映射表中的值都会被直接当作数据集路径或名称传给 datasets.load_dataset(dataset_path, split=split)(见 swebench.py),这正好对应 FAQ 中"如何运行自定义数据集"的机制。

实例筛选、切片与打乱

批量脚本在加载数据集后,会调用 filter_instances 完成三步预处理,顺序为:打乱 → 正则过滤 → 切片:

  • 打乱使用固定随机种子 42(保证可复现),源码为 random.seed(42);
  • --filter 用 re.match 匹配 instance_id,例如 --filter 'django__.*' 只保留 Django 相关实例;
  • --slice 支持完整的 Python 切片语法(0:5、3:、:2),作用于过滤后的列表。

测试用例 tests/run/test_swebench.py 覆盖了 filter 与 slice 的各种组合,包括"先过滤后切片"的执行顺序以及打乱的确定性。

断点续跑与重跑

脚本具备天然的"断点续跑"能力:

  • 默认(--redo-existing False)下,若输出目录中已存在 preds.json,脚本会读取其中已记录的实例 ID 并跳过(见 swebench.py);
  • 若你想强制重跑,加 --redo-existing 即可。

对应测试见 tests/run/test_swebench.py(test_redo_existing_false_skips_existing 与 test_redo_existing_true_overwrites_existing)。

单实例模式:面向调试(swebench-single)

mini-extra swebench-single --help
# 等价于:
python src/minisweagent/run/benchmarks/swebench_single.py --help

按实例 ID 运行单个任务:

mini-extra swebench-single \
    --subset verified \
    --split test \
    --model anthropic/claude-sonnet-4-5-20250929 \
    -i sympy__sympy-15599

也可以按索引运行(例如第 0 个实例):

mini-extra swebench-single \
    --subset verified \
    --split test \
    -m anthropic/claude-sonnet-4-5-20250929 \
    -i 0  # instance index

提示:若希望脚本在 Agent 完成任务后不弹出确认提示直接退出,加上 --exit-immediately 标志(或命令行等价项 -y/--yolo)。

单实例模式参数

分组 参数 说明 默认值
基础 -m, --model 使用的模型 由配置决定
基础 -c, --config 配置文件路径(语义同批量模式) config 目录下的 swebench.yaml
基础 -o, --output 输出轨迹文件路径 全局配置目录下的 last_swebench_single_run.traj.json
数据选择 --subset 子集名或数据集路径 lite
数据选择 --split 数据集分片 dev
数据选择 -i, --instance SWE-bench 实例 ID 或实例索引 0
高级 --environment-class 环境类(如 docker) docker
高级 --exit-immediately Agent 想结束时立即退出而非询问 False
高级 --model-class / --agent-class 自定义模型类 / Agent 类(支持完整导入路径) 由配置决定
高级 -l, --cost-limit 成本上限(设为 0 禁用) 由配置决定

从源码 swebench_single.py 可以看到,-i 参数会先判断是否为纯数字:若是,则把数据集按实例 ID 排序后取对应索引;否则直接按实例 ID 查找。随后脚本使用默认的 interactive Agent 类型(default_type="interactive")运行该实例的 problem_statement,因此整个调试过程是交互式的。

评估:云端 sb-cli 与本地 harness

跑完 SWE-bench 后需要评估 preds.json,官方提供两种途径:

方案一:云端评估(免费、快速)

使用 SWE-bench 官方的 sb-cli,安装并获取 token 后:

sb-cli submit swe-bench_verified test --predictions_path preds.json --run_id some-id-for-your-run

通常约 20 分钟内出结果。需要注意:耗时不受实例数量影响,而取决于 SWE-bench 中评估最慢的那个实例。

方案二:本地评估

安装 SWE-bench 包后,使用其 harness 在本地跑:

python -m swebench.harness.run_evaluation \
    --dataset_name princeton-nlp/SWE-bench_Verified \
    --predictions_path preds.jsonl \
    --max_workers <num_workers> \
    --run_id <run_id>

本地评估适合需要完全掌控运行环境、或不便上传数据的场景;注意其 --predictions_path 接受的是 preds.jsonl,而批量脚本默认输出 preds.json,两者格式需自行对齐。

输出产物与进度管理

输出目录结构

批量模式运行后,输出目录中包含:

  • preds.json:评估所需的核心产物。每个实例对应一条记录,格式为 {instance_id: {"model_name_or_path": ..., "instance_id": ..., "model_patch": ...}},由 update_preds_file 以线程安全(threading.Lock)方式增量写入;
  • <instance_id>/<instance_id>.traj.json:每个实例的完整轨迹文件,包含 exit_status、submission、异常信息(如有)以及全部对话消息;
  • exit_statuses_<timestamp>.yaml:各实例退出状态的汇总报告(由 RunBatchProgressManager 维护);
  • minisweagent.log:运行日志(通过 add_file_handler 写入)。

实时进度面板

批量模式使用 rich 的 Live 渲染双进度条(见 batch_progress.py):主进度条显示整体完成数、已花费成本(累计 GLOBAL_MODEL_STATS.cost)与 ETA;每个实例对应一个子任务,状态文本由 ProgressTrackingAgent 在每个 step 更新为 Step N ($cost)。因此你在终端能同时看到"总进度 + 每个实例当前走到第几步 + 退出状态统计表"。

默认配置剖析

批量与单实例模式的默认配置均指向 src/minisweagent/config/benchmarks/swebench.yaml,它定义了 Agent 行为、环境与模型三大部分:

agent:提示词与限制

  • system_template / instance_template:Jinja2 模板,把每个 SWE-bench 实例的 problem_statement 渲染进 <pr_description>,并给出完整任务指令(工作目录 /testbed、禁止修改测试文件、最终必须通过 echo COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT && cat patch.txt 提交补丁等);
  • step_limit: 250:单实例最大推理步数;
  • cost_limit: 3.:单实例成本上限(美元)。

environment:运行沙箱

  • cwd: "/testbed":SWE-bench 标准工作目录;
  • timeout: 60:单条命令超时(秒);
  • interpreter: ["bash", "-c"]:命令执行解释器;
  • env:设置 PAGER/MANPAGER=cat、LESS=-R、关闭进度条噪音,并通过 BASH_ENV=/root/.bashrc 确保 conda activate testbed 生效;
  • environment_class: docker:默认容器后端。

model:观测与回退模板

  • observation_template:把命令输出包装成 <returncode>/<output>;当输出超过 10000 字符时自动截断,仅保留前 5000 与后 5000 字符并提示 elided 数量;
  • format_error_template:针对输出 token 耗尽(finish_reason == "length")与工具调用错误给出纠正提示;
  • model_name: "anthropic/claude-sonnet-4-5-20250929",并开启 drop_params 与 parallel_tool_calls。

底层原理:从实例到容器

镜像名推导

每个 SWE-bench 实例都运行在独立容器中。若数据集未提供 image_name 或 docker_image 字段,get_swebench_docker_image_name 会按规则构造镜像名:因为 Docker 不允许镜像名中出现双下划线,源码把实例 ID 中的 __ 替换为魔法 token _1776_,生成形如 docker.io/swebench/sweb.eval.x86_64.<repo>_1776_<repo>_1776_<version>:latest 的镜像名。相关单测见 tests/run/test_swebench.py。

环境装配与启动命令

get_sb_environment 负责把配置与实例结合出真实环境:

  • 复制配置中的 environment 段(不修改共享配置,避免多线程竞争,有专门测试验证);
  • 按环境类设置镜像:docker/swerex_modal 直接用裸镜像名,singularity/contree 则加上 docker:// 前缀;
  • 若配置了 run.env_startup_command,会先用 Jinja2(StrictUndefined 模式)以实例字段为模板变量渲染,再在容器内执行,失败则抛出 RuntimeError。

并发、异常与中断

批量模式通过 concurrent.futures.ThreadPoolExecutor(max_workers=workers) 并行调度实例(swebench.py)。每个实例的执行被包在 try/except 中:任何异常都会以异常类名作为 exit_status 记录进轨迹与 preds.json(model_patch 为空字符串)。测试 tests/run/test_swebench.py 验证了 RuntimeError/ValueError/ConnectionError 等异常都会被正确记录并通知进度管理器。

若你按下 Ctrl+C(KeyboardInterrupt),脚本会先取消尚未启动的任务,等待已运行任务收尾,再次 Ctrl+C 才强制退出。

FAQ 与常见问题排查

能否设置全局成本上限?

可以。通过环境变量/全局配置中的 MSWEA_GLOBAL_CALL_LIMIT(全局模型调用次数上限,0 表示不限)与 MSWEA_GLOBAL_COST_LIMIT(全局成本上限,美元,0 表示不限)实现,详见 docs/advanced/global_configuration.md。

用 Ctrl+C 中断后,未完成的任务怎么办?

轨迹只在任务完成时才保存,因此多数情况下直接重新运行脚本即可续跑未完成任务(preds.json 中已完成的实例会被自动跳过)。但个别已保存的任务可能以 KeyboardInterrupt 作为 exit_status,重跑前建议检查 preds.json。

删除了轨迹文件,某些任务仍然卡住不跑?

"已完成"的判定依据是 preds.json,而非轨迹文件。请把对应实例从 preds.json 中删除。

如何运行自定义数据集?

只要数据遵循 SWE-bench 格式,且能被 datasets.load_dataset(path, split=split) 加载,就可以通过 --subset /path/to/your/dataset 直接指定。--split 同样生效。

部分任务长时间卡在 "initializing task" 甚至超时?

这通常是因为正在拉取 Docker 镜像,第二次运行会立即开始。若是 docker pull 超时,可调大环境配置中的 environment.pull_timeout(默认 120 秒)。

遇到 Docker 问题怎么排查?

脚本会在控制台打印将要执行的 Docker 命令,可以手动复制执行观察报错;用 docker ps 确认容器在跑,再用 docker exec -it <container-id> ls 验证容器可交互。

HPC 集群上没有 Docker?

改用 Singularity/Apptainer 后端:在 Agent 配置文件中设置 environment.environment_class: singularity(参见 docs/advanced/yaml_configuration.md),或直接命令行加 --environment-class singularity。

能否在环境里先执行启动命令?

可以,配置 run.env_startup_command,命令会以 Jinja2 模板渲染实例字段后执行。例如:

run:
  env_startup_command: "apt-get update && apt-get install -y python3-pip"

利用实例变量做初始化尤其适合轻量环境,例如:

run:
  env_startup_command: "git clone {{ repo_url }} . --force"

该能力在配合 docs/reference/environments/bubblewrap.md 这类无预置代码的沙箱时非常实用。

SWE-bench 可以使用哪些环境后端?

docker(默认,经 docker exec 执行)、singularity(HPC 友好)、swerex_docker/swerex_modal(经 SWE-ReX 的本地/云端执行)、bubblewrap(Linux 无特权沙箱,实验性)、contree(ConTree 安全执行沙箱)等。各后端的取舍与配置详见 docs/advanced/environments.md。

延伸阅读

登录后查看全文
mini-swe-agent