← 返回 2026-10-12

ProgramGym:面向长程程序复现智能体的可扩展训练环境 ProgramGym: Scaling Training Environments for Long-Horizon Program Reproduction Agents

Chengyi Yang, Renxu Bao, Jue Hou, Zongpei Teng, Ziheng Wang, Yujie Lin, Chengsong Huang, Junnan Zhu, Delai Qiu, Yining Wang, Shengping Liu, Fei Long, Jinsong Su 📅 2026-10-09 👍 44 2026-11-11 18:30
代码智能体 智能体工作流 监督微调 程序复现 训练环境合成 软件工程

自动把开源仓库变成可验证训练环境,再用角色隔离工作流让模型学会从零复现程序

前置知识

SWE-bench 与 issue 修复范式

SWE-bench 是最具代表性的代码智能体基准:给智能体一个真实 GitHub 仓库和一条 issue,要求它生成补丁并通过仓库自带测试。该范式假设代码库已存在,智能体只做局部修改,SWE-Gym、SWE-smith 等训练环境也都围绕这一设定构建。

本文的任务定义正是从这个主流范式出发做对比。理解它的边界(依赖既有代码、无需需求发现和架构设计)才能明白作者为何要另起炉灶做从零复现。

从零程序复现

只给二进制可执行文件和使用文档、不给源码,要求智能体通过运行探索参考程序来发现其外部行为,再自行决定架构并从零写出能复现该行为的源码与编译脚本。ProgramBench 是该任务的主要基准(200 个任务),评分看候选程序在黑盒测试上的通过率。

这是本文的训练任务本身。环境四元组 $(B_i^\star, D_i, T_i, S_i)$ 的定义、"只可执行参考程序"等设定、以及所有评测指标都由此任务而来。

黑盒测试与测试预言

黑盒测试不读被测程序内部代码,只通过命令行参数、标准输入输出等公开接口喂入输入并断言输出。测试预言(oracle)指判定对错的准则:弱预言(如只检查退出码为 0、只检查输出非空)会让错误实现也通过,强预言才对错误实现有区分力。

Program-Env 用黑盒测试套件作为训练的监督信号,测试质量直接决定训练标签是否可靠。论文的四重校验(pass/double/dummy/weak-assert)和 37 条 linter 规则全是为保证预言强度服务的。

覆盖率插桩

编译时向程序注入计数代码(C/C++ 用 gcov/llvm-cov、Rust 用 -C instrument-coverage、Go 用 -cover),运行后报告哪些源码行被执行过。未覆盖代码大致对应未被测试触达的功能,是测试生成最常用的反馈信号。

本文定义核心覆盖率 $C_{\text{core}}^{(t)}$ 并用部分覆盖文件生成下一轮测试目标(coverage_targets.json),插桩是环境反馈循环的技术基础,也是"规则优先、智能体兜底"设计的对象。

拒绝采样与监督微调(SFT)

拒绝采样:让强模型在环境里多次解题,只保留通过验证器筛选的轨迹作为训练数据;SFT 在这些轨迹上做最大似然训练(只对助手 token 计损失)。本文用 DeepSeek-V4-Flash 在 1,648 个环境上以测试通过率过滤,得到 64,505 条轨迹全参微调 Qwen3.8-27B。

RQ1 的核心结论"SFT 让 Qwen3.8-27B 从 34.87% 升到 42.84% Tests Passed"建立在这套流程上,是 Program-Env 环境价值的直接检验,也是理解 SFT 与 Program-Agent 增益如何叠加的前提。

静态程序分析与调用图

不运行程序、直接分析源码的技术,典型产物有代码属性图(CPG)、调用图、控制流和数据流图。调用图记录"谁调用谁",对其反向遍历可以从深层未覆盖函数出发,找到黑盒测试可达的公共命令行入口。本文用 Joern(C/C++/Go)和 CodeQL(Rust)作为可插拔后端。

覆盖率只回答"哪里没测到",静态分析回答"怎么从公开入口到达它"。COLMAP 案例中 AverageUnitVectors 正是靠调用图发现了轻量可达路径,两者配合才能把测试目标变成可执行方案。

研究动机

现有编码智能体的训练与评测几乎都围绕两类任务:以 SWE-bench 为代表的 issue 修复(给定代码库和 issue 打补丁)和以 NL2Repo-Bench 为代表的仓库生成(给定需求文档写实现)。两者都从既有代码或明确规格出发,智能体无需回答软件工程师最核心的两个问题——"需要什么"与"系统该怎么设计"。从零复现程序的任务(ProgramBench,200 个任务)只给二进制可执行文件和使用文档,要求智能体探索发现行为并从零实现,难度极高:原评测中没有任何旗舰模型完全解决任何一个任务(Resolved 全部为 0.00%),最强的 Claude Opus 4.6 也只有 52.1% Tests Passed。训练这种能力需要带可靠行为监督的交互环境,但现有资源不适用:SWE-Gym、SWE-smith 只支持 issue 修复式监督;MindForge 仅限命令行程序、不按恢复出的程序行为过滤轨迹,功能错误的复现也可能被当成成功样本。通用 harness 也撑不住长程开发:智能体常在探索不足时就开始实现,并随上下文增长遗忘早期观察到的需求。

本文的目标是本文目标是把"从零复现程序"变成可规模化训练的任务,具体分两层。环境层:设计全自动流水线 Program-Env,把 GitHub 开源仓库批量转化为可验证训练环境,每个环境 $e_i = \Phi(P_i) = (B_i^\star, D_i, T_i, S_i)$ 包含只可执行的参考程序 $B_i^\star$、网络隔离的运行时沙箱 $S_i$、使用文档 $D_i$ 和黑盒行为测试套件 $T_i$,使训练信号由"候选程序与参考程序在测试上的行为一致性"自动给出,无需人工标注。智能体层:设计 Program-Agent 工作流,让模型能在远超 256K 上下文窗口的长程开发中保持探索与实现的协调,不丢失早期行为证据,且能从编译失败中恢复。最终在这些环境上收集轨迹做监督微调,在 ProgramBench 上验证效果:将 Qwen3.8-27B 从 34.87% Tests Passed 大幅提升,并让 27B 级开源模型搭配工作流后超越部分旗舰闭源模型。

与已有工作不同的是,本文的独特切入是把"环境构建"本身当作可用反馈循环自动化的智能体任务,而非人工策划或脆弱的规则流水线。三个差异化设计: 其一,构建与求解解耦——构建阶段允许联网(download.sh 在线准备工具链与依赖),求解阶段完全断网(compile.sh 离线编译),用离线编译成功来验证环境自洽,这与直接把源码交给训练方的做法本质不同; 其二,测试质量用机器可校验的四重检查(pass/double/dummy/weak-assert,含 37 条 linter 规则)保证,拒绝"只检查退出码""在无功能 dummy 实现上也能通过"的弱断言测试,而 MindForge 并不按行为正确性过滤监督信号; 其三,测试扩展不靠盲目生成,而是动态覆盖分析定位未覆盖代码、静态分析(Joern/CodeQL 调用图反向回溯)找到黑盒可达的公共入口,把"接下来测什么"从猜测变成明确可达的目标。这套反馈驱动闭环让 30,459 个候选仓库最终产出 1,648 个可用环境,证明该思路可以规模化。

核心方法

训练"从零造程序"的智能体需要两块拼图:能自动判分的环境,和能撑住长周期开发的工作流。ProgramGym 据此分为 Program-Env 与 Program-Agent。Program-Env 三阶段: 分层检索 GitHub(语言×star 区间),41,833 个仓库经元数据校验、commit 锁定、构建配置检测得 30,459 个候选; 以 Claude Code 为底层 harness 加外层校验循环,生成 download.sh(在线装依赖)与 compile.sh(离线编译),经静态 linter、在线执行、离线编译、ldd 链接检查后产出参考可执行文件 $B_i^\star$ 与冻结沙箱 $S_i$; dispatcher 按复杂度 $\xi = \text{clip}_{[0,10]}(\log_{10}\ell + \log_{10}(1+r) - 2)$ 分配 4–8 个并行子智能体,在"生成→四重校验→结构化反馈→修复/扩展"循环中迭代写所辖模块的测试。Program-Agent 采用分析→实现→评审的角色隔离迭代流程,配合独立编译门禁与失败回滚完成长程开发。

核心创新是把"可靠性"显式编码为机器可校验的循环,而非寄希望于单次生成质量。环境侧,测试 $t$ 必须同时满足四条件才保留:在参考程序上通过(pass)、两次独立运行结果一致(double)、在无功能 dummy 实现上必须失败(dummy)、不触发 37 条弱断言 linter 错误(weak-assert),即 $t(B_i^\star)=\text{PASS} \wedge t^{(1)}(B_i^\star)=t^{(2)}(B_i^\star) \wedge t(B_\varnothing)=\text{FAIL} \wedge L(t)=\varnothing$。智能体侧的本质区别是"角色隔离+会话分离":分析阶段独占参考程序执行权并把行为证据冻结为只读 Handoff 工件;实现阶段在文件系统层面接触不到参考程序,只能读冻结工件,杜绝"边对答案边写代码";评审阶段对比参考程序与不可变候选副本,只输出经核实的差异清单,且禁止改源码以防自证式修改。这与单会话 harness(上下文压缩后遗忘需求、易过早终止)形成鲜明对比。

方法步骤详情

流程如下。 收集:GitHub Search API 按语言与 star 分桶分层检索,经元数据校验、commit 锁定、构建标记检测得 30,459 个候选。 构建:智能体生成 download.sh 与 compile.sh;系统先跑静态 linter(拒绝 || true 等失败掩蔽写法),再带网执行前者并冻结容器为 $S_i$,最后断网执行后者,校验产物为可用 ELF;失败带诊断反馈重试,至多 4 次。 测试:dispatcher 按复杂度拆分模块($\xi<2$/4 模块、$2\le\xi<4$/6、$\ge4$/8),每模块配一个子智能体;每轮先修复被校验标记的测试,再按覆盖目标(每轮至多 10%、上限 300 个)结合静态分析的公共入口写新测试;达 80% 覆盖或轮数上限(5–20 轮)终止,连续 3 轮覆盖增益<0.25% 则早停。 执行:预算 $K$ 下跑 1 次分析、$K$ 次实现、$K-1$ 次评审;每轮实现后导出干净快照在区外独立编译,失败则新会话重试(默认 2 次),仍失败回滚到最近稳定修订。

技术新颖性

新颖性有四。 其一,可扩展的可验证环境合成:已有工作(SWE-Gym、SWE-smith)从既有代码库构造 issue 修复环境,Program-Env 则大规模把编译型语言仓库转化为"无源码、行为对齐"的复现环境,全程自动(均值约 82.99M token/环境)并实证 1,648 个。 其二,测试监督可信性的形式化:把"忠实、稳定、有效"三性质落成四重可执行检查的交集(式 (3)),从机制上排除"假通过"监督,直接对比 MindForge 不做行为过滤的缺陷。 其三,"规则优先、智能体兜底"的覆盖率插桩:语言级规则(gcov/llvm-cov、RUSTFLAGS、go -cover)先试,独立验证器确认失败才切换 LLM 修复,兼顾确定性与适应性。 其四,角色隔离的工程化落地:用文件系统权限(参考程序移出实现可见路径、Handoff 工件转 root 只读、评审用不可变副本)而非仅靠提示词约束角色边界,并用独立编译+last-stable 修订实现崩溃恢复;静态分析总成本仅 11.74 小时(25.64 秒/仓库)。

Overview of ProgramGym.
Figure 1: Overview of ProgramGym.
Overview of the Program-Env.
Figure 2: Overview of the Program-Env.
Overview of Program-Agent.
Figure 3: Overview of Program-Agent.
A case of executable and sandbox generation guided by feedback.
Figure 10: A case of executable and sandbox generation guided by feedback.
Program analysis guiding test writing on COLMAP.
Figure 12: Program analysis guiding test writing on COLMAP.
Iteration-wise coverage, test counts, and validation metrics for two representative source modules.
Figure 13: Iteration-wise coverage, test counts, and validation metrics for two representative source modules.

实验结果

主实验在 ProgramBench 上展开。 RQ1:SFT 让 Qwen3.8-27B 从 34.87% 升至 42.84% Tests Passed(+7.97);换 Program-Agent 后基座达 55.71%(+20.84)、SFT 版达 56.25%(+21.38),均超 Claude Opus 4.7(50.90%)与 Gemini 3.5 Flash(53.60%)。但 Resolved 最高仅 0.50%,完整复现远未解决。 RQ2:1,648 个环境覆盖 C(149)/C++(378)/Go(818)/Rust(303),共 665,512 个测试(均值 404/仓库),平均覆盖率 72.99%。 RQ3:K=1/3/5 下 SFT 模型为 43.49%/54.13%/56.25%,增益主要在前 3 轮。 RQ4:Program-Agent 使 read/git 操作占比上升;≥75% 通过率的任务份额从 18.0%→34.0%(基座)、9.5%→29.5%(SFT);高质量解中位 1,881 行 vs 参考 2,596 行,收益来自更完整的行为覆盖。

Distribution of the black-box interaction categories over 5,918 subagents from 1,648 repositories.
Table 1: Distribution of the black-box interaction categories over 5,918 subagents from 1,648 repositories.
Results on ProgramBench across models and agent scaffolds.
Table 2: Results on ProgramBench across models and agent scaffolds.
Repository statistics across the four-stage collection pipeline.
Table 3: Repository statistics across the four-stage collection pipeline.
Resource access across Program-Agent stages.
Table 15: Resource access across Program-Agent stages.
Main training settings for Qwen3.8-27B.
Table 17: Main training settings for Qwen3.8-27B.
Distribution of the 1,648 repositories across eight functional categories.
Figure 4: Distribution of the 1,648 repositories across eight functional categories.
Distributions of code lines, coverage, and test cases in Program-Env.
Figure 5: Distributions of code lines, coverage, and test cases in Program-Env.
Tests Passed of Qwen3.8-27B-SFT with Program-Agent across different iteration budgets on ProgramBench.
Figure 6: Tests Passed of Qwen3.8-27B-SFT with Program-Agent across different iteration budgets on ProgramBench.
Distribution of action types over agent turns.
Figure 7: Distribution of action types over agent turns.
Build-attempt distribution across programming languages.
Figure 9: Build-attempt distribution across programming languages.
Performance distribution of large language models on ProgramBench with respect to output token length and test pass rate.
Figure 19: Performance distribution of large language models on ProgramBench with respect to output token length and test pass rate.
Cumulative distribution of test pass rates across models and agent scaffolds on ProgramBench.
Figure 21: Cumulative distribution of test pass rates across models and agent scaffolds on ProgramBench.
Reference vs. model code lines on a log–log scale.
Figure 22: Reference vs. model code lines on a log–log scale.
查看结构化数据
任务指标本文基线提升
ProgramBench 程序复现(Qwen3.8-27B-SFT,最佳配置) Tests Passed (%) 56.25(Program-Agent, K=5) 34.87(同模型 + Claude Code) +21.38 个百分点;另超过 mini-SWE-agent 下的 Claude Opus 4.7(50.90)与 Gemini 3.5 Flash(53.60)
ProgramBench 程序复现(Qwen3.8-27B 基座) Tests Passed (%) 55.71(Program-Agent) 34.87(Claude Code) +20.84 个百分点,工作流增益远大于 SFT 增益(+7.97)
Program-Env 轨迹监督微调(同 harness 对比) Tests Passed (%) 42.84(Qwen3.8-27B-SFT + Claude Code) 34.87(Qwen3.8-27B + Claude Code) +7.97 个百分点,且超过 GPT 5.4(37.70,mini-SWE-agent)
ProgramBench 程序复现(DS-V4-Flash-0731) Tests Passed (%) 58.97(Program-Agent) 57.68(Claude Code) +1.29 个百分点,强模型上工作流增益边际递减
ProgramBench 部分解决(Qwen3.8-27B) Almost Resolved (%)(≥95% 测试通过) 5.50(Program-Agent) 3.50(Claude Code) +2.00 个百分点;但完全解决 Resolved 始终 ≤0.50%
测试时扩展(Qwen3.8-27B-SFT + Program-Agent) Tests Passed (%) 随迭代预算 K K=1: 43.49 / K=3: 54.13 / K=5: 56.25 K=1(43.49) K=1→K=5 提升 12.76 个百分点,增益主要在前 3 轮
训练环境构建质量(Program-Env 本身) 核心覆盖率 / 测试用例数 平均 72.99%(中位 81.63%)/ 665,512 个验证用例(404/仓库) 单次生成测试(弱断言、低覆盖,论文 Figure 13 案例中 linter 通过率 0%、覆盖 4.88%) 反馈循环把 violet 的 linter 通过率从 0% 提到 98.3%、假通过率 1.41%→0%,把 kubesess 覆盖率从 4.88% 提到 85.77%

局限与改进

作者承认的局限: Resolved 最高 0.50%、Almost Resolved 最高 5.50%,Tests Passed 的提升主要来自部分行为恢复,从零复现整个程序远未解决; 任务难度严重偏易——按复杂度分数 $\xi$ 划分,1,648 个任务中 1,492 易、151 中、仅 5 难,作者辩解 $\xi$ 度量仓库规模而非复现难度,且过难任务采不出有效轨迹; 测试只覆盖有限输入,通过测试仅保证已测行为一致而非完整语义等价; 未与 MindForge 直接对比(对方未开源环境与轨迹,无法同协议评测)。我的补充观察: 全链路对 Claude Code 强依赖(环境构建、测试生成、轨迹收集、Program-Agent 底座都是它),结论可能混杂该 harness 的特定行为,换底座只测了 DS-V4 一个额外骨干; SFT 在 Almost Resolved 上反而从 3.50% 降至 1.50%,暗示拒绝采样轨迹可能强化"部分正确"的局部模式; 评测成本高(每任务 8 核 16GB、8 小时时限、K=5 迭代); 5 个 hard 任务难以支撑"可扩展到更难仓库"的论断。

独立分析的弱点

弱点一:验证的"有限输入"本质带来 reward hacking 风险。$T_i$ 只能采样有限输入,训练轨迹又按测试通过率过滤,模型可能过拟合测试可观察行为而非真正理解语义(SFT 后 Almost Resolved 下降即警示)。改进:引入属性测试/模糊测试,或训练行为差异判别器作辅助验证。弱点二:黑盒不可达代码被系统性放弃。平均覆盖 72.99% 且有低覆盖长尾,大量代码无法经公开接口触达,永远得不到监督。改进:白盒约束分析或带桩混合接口扩大可测面。弱点三:环境构建昂贵且不可增量。均值 82.99M token/环境、共 136.77B token,commit 锁定意味着上游演进后环境即过时。改进:差分式更新、跨仓库共享测试模式库。弱点四:固定迭代预算 K 不自适应,简单任务浪费、复杂任务不足,K=5 已近饱和。改进:由评审输出"剩余差异估计"驱动动态预算。弱点五:SFT 学到的可能是特定 harness 的操作习惯——轨迹全部来自 Claude Code+DeepSeek-V4-Flash。改进:跨 harness 混合收集,或转向以四重校验为奖励的强化学习(RLVR)。

未来方向

作者方向: 发布 ProgramGym(环境、构建代码、训练工件),支持社区研究"发现需求、从零设计系统"的编码智能体; 随模型能力增长用同一全自动流水线扩展到 medium/hard 仓库(当前仅 151 中/5 难); 隐含方向是把这些可验证环境用于强化学习——四重校验天然构成过程奖励,论文只做了拒绝采样 SFT。我的延伸: 把"覆盖率反馈+调用图入口回溯+四重校验"范式迁移到其他长程域,如游戏引擎、前端 UI、科学计算库的复现; 用变异测试系统量化测试套件区分错误实现的能力,弥补 dummy check 只有单一 dummy 实现的不足,建立"测试充分性"标准; 多智能体协作:当前实现/评审串行交替,可引入并行多实现者竞争投票或跨任务复用已验证架构方案; 研究成本-质量帕累托前沿:136.77B token 成本绝大部分花在写测试,可用更强早停或"小模型写测试+大模型复审"压缩; 增加"设计质量"评测维度(模块划分、抽象选择),真正度量"从零设计"区别于"按规格实现"的能力——这正是该任务设定最有价值的部分。

复现评估

开源与文档:作者承诺在 huggingface.co/ProgramGym 与 programgym.github.io 发布全部工件,Reproducibility Statement 逐环节给出指引:仓库收集四阶段过滤(附录 B.1、表 3)、构建与沙箱(B.2,linter 规则表 5、修复建议表 6)、dispatcher 与插桩(B.3)、测试四重校验(B.4,37 条规则与式 (3))、Program-Agent 编排(附录 C,算法 1、访问矩阵表 15)、训练超参(表 17:Qwen3.8-27B 全参、ms-swift、2 epoch、BF16、序列 262,144、lr $1\times10^{-5}$ 余弦衰减)。实际复现评估:管道全自动但极昂贵——1,648 环境耗 136.77B token,个人难复制全集,但自动化意味着可选小子集构建;27B 全参微调需多卡集群;评测容器规格明确(8 核/16GB/30GB/8 小时)。工件兑现后中等规模实验室可用子集环境+高效微调复现核心结论;目前工件尚未放出,最终取决于承诺兑现。

相似论文推荐