Jasaxion一只大雄

风打,碎琉璃; 打不碎的,是那阳光漫地。The wind strikes, shattering the glazed glass; Yet unbroken remains the sunlight spilling across the earth.

[基模杂谈]SWE 环境构建与长程轨迹挖掘

Jasaxion / 2026-09-12


主页

现在 Coding 已经逐渐变成基座模型的一项基础能力。继续往上做,绕不开数据:预训练阶段有代码仓库、技术文档和 Stack Overflow,后训练阶段则需要能真实执行、持续交互、自动验收的 Agent 轨迹。

SWE 数据难做,不是因为代码少,而是因为“任务、环境、过程、结果”很难同时闭合。只有问题没有环境,模型无法试错;只有环境没有可靠测试,轨迹又无法判断好坏。

这篇主要记录两件事:一个真实的软件工程任务,怎样被还原成可执行、可验证的训练环境;Agent 在环境中产生的长程轨迹,又怎样被采集、清洗并变成训练数据。

SWE-Gym 给出了较早的一套任务契约和训练样例,后续的重点已经转向自动环境构建、确定性验证和集群化生产。

一、先来看看经典的 SWE-Gym

SWE-Gym 沿用了 SWE-bench 的基本思路,把真实 Issue / PR 拆成一个可以反复运行的任务:

1
2
3
4
5
problem_statement
+ repo / base_commit
+ gold patch / test patch
+ 可复现的依赖与执行环境
+ FAIL_TO_PASS / PASS_TO_PASS

Agent 拿到的是问题描述和修复前的仓库。人类补丁只用于证明问题在历史上有解,并帮助构造验收信号,不应暴露给求解 Agent。

SWE-Gym 从 358 个仓库抽取了 64,689 个原始任务,最后只在 11 个 Python 仓库上做出 2,438 个可执行实例。环境补齐大约投入了 200 小时人工、10,000 CPU core hours,预构建镜像约 6 TB。这些数字真正说明的是:从 GitHub 抽到一个 PR 很便宜,把它恢复成可靠的历史运行现场很贵。

它还有一个重要结果。作者用 GPT-4o 和 Claude 3.5 Sonnet 采到 491 条成功轨迹,平均约 19 轮、19k Token。少量经过执行验证的轨迹就能改善模型的工具使用和修复能力,说明这类数据值得做。不过,同一论文里的自我改进实验也出现过性能下降,说明“采到成功轨迹再混回训练集”并不天然有效,数据分布和训练方法仍然重要。

所以 SWE-Gym 更适合作为一个起点:它说明了什么叫可执行任务,也暴露了人工维护环境的规模上限。

二、工业场景中,谁来构建环境

真实工业流水线里,环境自然尽量由 Agent 自动构建。不过需要区分两个角色:

1
2
离线阶段:Build Agent 负责读仓库、试装依赖、运行测试、修复构建配方
在线阶段:Solve Agent 在已经验收的镜像中定位问题、修改代码、提交补丁

通常不会让 Solve Agent 在每一次 rollout 开头都从裸机重搭环境。这样成本太高,也会把“环境没装好”和“问题没修好”混成同一种失败。更常见的做法是离线批量生成环境,验收后固定镜像 digest 和测试入口,再供后面的 SFT、RL 或评测重复使用。

因此,Build Agent 不是整套系统本身,只是环境工厂中的一个非确定性工人。它擅长读取 README、依赖文件、CI 配置和错误日志,提出安装与修复动作;容器调度、快照回滚、缓存、超时、网络隔离和最终验收,仍然应由确定性程序控制。

三、一条比较完整的环境工厂

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Issue / PR Miner
-> 仓库与许可证过滤
-> 历史 commit、题面、gold patch、test patch 对齐
-> 静态解析依赖文件、CI 和测试入口
-> Build Agent 在沙箱中试装、试跑、修复
-> 固化 Dockerfile、镜像 digest 和 verifier
-> 基线 / gold patch 双态验证
-> 重复运行、质量过滤、人工抽检
-> 写入环境与任务注册表
-> 批量供 Solve Agent rollout

SWE-Hub 把这个思路做成了生产系统:底层是共享的执行基座,负责固定镜像、统一 verifier 接口和产物;上层再生产不同类型、不同长度的软件工程任务。这个分层很有工程价值,因为环境、验证器和任务生成不再绑死在某个 benchmark 上。

SWE-Hub 的生产系统结构

图:SWE-Hub architecture。它把 Env Agent、确定性执行基座和多条任务生产线分开。来源:SWE-Hub

落到存储层,至少要保留这些东西:

否则几个月后重跑失败,很难判断是代码变了、依赖消失了,还是生成管线悄悄变了。

四、Build Agent 实际在做什么

环境构建不是让模型读完 README 后一次性写 Dockerfile,而是一个有执行反馈的搜索过程:

  1. 查看目录、依赖文件、CI 和历史安装说明;
  2. 选择基础镜像,安装系统库和语言依赖;
  3. 找到真实测试命令,运行一小部分测试;
  4. 根据编译、导入、版本冲突和服务错误继续修正;
  5. 成功后把有效动作压缩成可重放的构建配方;
  6. 从空白状态重新构建一次,确认不是偶然跑通。

Repo2Run 的设计比较直观。Agent 在内部容器里安装依赖、查文件和跑测试,外部环境负责更换基础镜像、保存快照和回滚。失败命令可能已经改坏包、文件或缓存,所以不能只看退出码后继续试;需要先回到确定状态。最终 Dockerfile 也不是让模型凭记忆重写,而是从成功动作序列中合成。

Repo2Run 的双环境 Build Agent

图:Repo2Run workflow。上半部分负责交互探索,下半部分负责隔离、回滚和配方生成。来源:Repo2Run

论文在自己的 420 个 Python 仓库基准上报告了 86.0% 的环境构建成功率。这个结果证明专用 Build Agent 比“让通用 Coding Agent 顺手搭环境”可靠,但它不能直接外推到所有仓库。 复杂服务、私有依赖、硬件要求、多语言构建和已经损坏的历史版本,仍然会失败。

后续系统开始把单 Agent 再拆开。daVinci-Env 让不同 Agent 分别做仓库探索、Dockerfile 构建、评测脚本构建和测试分析,并用本地 Git 镜像、基础镜像缓存和集群调度降低成本。 论文报告在 64 个计算节点上约两周构造了 45,320 个验证环境,覆盖约 12.8k 个仓库。

OpenSWE 的多 Agent 环境生成流程

图:OpenSWE framework。右侧几个 Agent 分工生成环境并闭环检查,左侧和中间负责材料去重、缓存与分布式执行。来源:daVinci-Env

这里的关键不是 Agent 数量,而是把不同失败归给不同模块。依赖没装好、测试入口写错、题面与补丁不一致、仓库本身不可运行,不能最后都算成一次模糊的“构建失败”。

五、构建成功不等于环境有效

docker build 返回 0,只能证明镜像能生成。测试命令能启动,也只说明仓库大概可运行。一个 Issue 任务至少要做双态验证:

1
2
3
4
5
6
7
base_commit + test_patch
-> FAIL_TO_PASS 失败
-> PASS_TO_PASS 通过

base_commit + gold patch + test_patch
-> FAIL_TO_PASS 通过
-> PASS_TO_PASS 仍然通过

第一遍证明问题确实存在,第二遍证明参考修复能让目标测试变绿且没有破坏原有测试。每遍还应从干净快照开始,重复运行并过滤 flaky case。

生产环境里还要防几类假正样本,常见的几种 Hacking 现象:

所以 verifier 应尽量小而确定:固定入口、明确退出码、结构化测试明细、只读任务材料、有限资源和默认断网。Agent 可以生成 verifier 候选,但不能自己宣布验收通过。

SWE-Factory 在 671 个跨语言 Issue 中得到 269 个有效任务,约 40.1%;其自动 F2P 判断报告了 0.92 precision 和 1.0 recall。这个漏斗比“生成了多少 Dockerfile”更接近真实产量,因为最终有用的是可区分、可复现的任务,而不是容器数量。

六、传统的 SWE-Gym 方法是否过时?

如果把它理解成“今天搭建工业数据管线的完整方案”,确实已经不够了。它只有 11 个 Python 仓库,环境构建包含较多人工,镜像体量大,也没有覆盖现代的多语言、集群调度和自动 verifier 生产。

如果把它理解成一种数据契约,它仍然没有过时。base commit、gold patch、test patch、F2P / P2P 和隔离执行,至今仍是许多系统的共同基础。后续工作主要是在替换它最贵的部分:

规模也已经发生变化。SWE-rebench V2 报告了 32k+ 容器化任务、3.6k+ 仓库和 20 种语言;GLM-5 技术报告提到 RepoLaunch 管线生成了 10k+ 可验证环境,覆盖 9 种语言,并支撑千级并发 rollout。这说明自动化环境工厂已经不是设想,而是当前训练基础设施的一部分。

不过,不同论文的成功率不能横着比较。Repo2Run 的 86.0% 来自 420 个 Python 仓库;SetupBench 从裸 Linux 出发,包含数据库和外部服务,最好结果为 62.4%;Multi-Docker-Eval 覆盖 9 种语言并要求 F2P,最高为 37.7%;EnvBench 还主动排除了容易仓库,Python 最好结果只有 6.69%。口径越接近复杂工业仓库,数字通常越低。

因此比较 Build Agent 时,至少要一起看:输入是不是裸环境、是否允许网络、覆盖多少语言、只要求测试能启动还是必须通过、是否检查 F2P、失败后能否人工接管,以及构建结果能否在另一台机器重放。

七、环境轨迹和解题轨迹是两种数据

自动搭环境以后,会自然产生两类长程轨迹。

第一类是环境构建轨迹。 它记录 Agent 如何读 CI、选择版本、解决依赖冲突、发现测试入口、处理失败命令并生成 Dockerfile。这类轨迹适合训练 Build Agent,也适合做错误分类和环境记忆库。

第二类是 Issue 求解轨迹。 它记录 Agent 如何理解题面、搜索代码、形成假设、修改文件、运行测试和检查最终 diff。这类轨迹才直接用于训练 Coding Agent。

两者不要混在同一种成功率里。环境失败意味着这次任务不一定给 Solve Agent 提供了公平机会;求解失败则说明在环境有效的前提下,策略没有找到正确补丁。

一条可回放的轨迹至少要保存:

1
2
3
4
5
6
7
8
-> task_id、repo、base_commit、镜像 digest
-> 模型版本、采样参数、system prompt、tool schema
-> Agent scaffold / harness commit
-> 每轮模型实际收到的 observation
-> 模型输出的 action 与参数
-> stdout、stderr、exit code 和资源消耗
-> 文件变化、git diff、测试明细和最终奖励
-> 上下文压缩、自动重试、超时与人工介入事件

尤其要区分“模型做的事”和“harness 替模型做的事” 。自动截断日志、补全命令、重试工具、恢复快照、调用子 Agent,都可能改变结果。如果只保存一份整理过的聊天记录,后面就无法准确训练,也无法解释线上行为为什么复现不了。

八、长程轨迹怎样变成训练数据

一个朴素的采样流程是:

1
2
3
4
5
6
每个任务运行多个 seed / temperature
-> 每次从同一干净快照启动
-> 统一 verifier 验收
-> 保存真实 observation / action 和最终 diff
-> 按成功、失败类型、成本和污染风险打标签
-> 去重、分层采样、人工抽检

成功轨迹适合做 SFT,但仍要清理空补丁、动作循环、无关大改和测试欺骗。失败轨迹不应该直接做行为克隆,可以用于训练 verifier / critic、构造同题偏好对,或者总结常见错误。对于 RL,环境奖励比文本打分可靠,但终局奖励稀疏,rollout 又很慢,需要单独处理吞吐和信用分配。

近期系统在这件事上有几个朴素的方向:

长轨迹压缩时,至少要留下当前假设、已读文件、关键符号、失败原因、未完成事项、执行过的命令和当前 diff。只保留一段自然语言总结,很容易在后半程重复搜索或把已经排除的方向重新走一遍。

九、如果自己搭一条最小流水线

我会先做四个相互独立的模块:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Task Builder
负责 Issue / PR 对齐、commit 定位、patch 拆分和许可证过滤

Environment Factory
负责静态分析、Build Agent、镜像构建、缓存、快照和资源隔离

Evaluator
负责 F2P / P2P、重复运行、隐藏检查和最终奖励

Trajectory Service
负责 rollout 调度、真实 observation / action、diff、测试与成本记录

第一阶段只选少量仓库,先把二次构建成功率和 verifier 精度做稳。第二阶段再接入 Build Agent,允许失败任务进入待修队列,不要为了追求自动化率放松验收。第三阶段才扩语言、扩仓库、扩集群,并加入环境配方记忆和镜像缓存。最后再根据训练目标采 Solve Agent 轨迹。

监控指标也要分开看:

在工程上,40% 的自动有效率并不一定差。只要候选池足够大、失败可观测、验证严格,而且成功环境能够缓存复用,它仍然可以成为高吞吐的数据生产线。真正危险的是把构建成功、测试启动和任务有效混成一个数字。

十、Takeway

SWE-Gym 没有过时,但它代表的是第一代可执行 SWE 数据:少量仓库、较多人工、严格验证。现在更值得关注的是第二代环境工厂:Build Agent 自动探索配方,确定性基础设施负责隔离和验收,集群系统负责批量生产,最终再为 Solve Agent 提供稳定环境。

工业系统也不是“让一个更强的 Agent 从头包办一切”。更现实的组合是:

1
2
3
4
5
Agent 提供适应性
+ 程序提供确定性
+ 测试提供可验收性
+ 注册表提供可追溯性
+ 集群提供吞吐

最后仍然要记住这几个不等号:

1
2
3
4
代码仓库很多
!= 可执行环境很多
!= 可验证任务很多
!= 高质量长程轨迹很多

从工程角度看,长期价值最大的不是某一种生成 prompt,而是可重建的环境、可信的 verifier 和忠实记录的轨迹。它们决定后面的 SFT、Verifier、RL 和推理时扩展,究竟是在学习真实的软件工程过程,还是在放大数据管线里的噪声。

参考资料