CodeMidas:不给 issue 不看 commit,只把源代码扔进炼丹炉,炼出 5545 个 RL 训练环境
核心摘要
训练编程智能体最缺的不是算力,是"带可靠验证器的多样化任务"——而现在几乎所有 RL 环境构建流水线都绑死在 issue、commit、现成测试这些开发产物上,代码库里大量已实现但从没被记录过的功能根本用不上。CodeMidas 换了个思路:把源代码本身当作唯一的任务输入,让智能体自己去读代码、提炼行为规格、基于真实执行构造测试、再用多轮 rollout 把有缺陷的环境筛掉。最终从 3185 个开源代码库、23 种语言里产出 5545 个高质量训练任务。用它对 MiMo-V2.5 做 GRPO 训练后,五个外部基准全线上涨:DeepSWE 涨 11.7 个点、ProgramBench 涨 17 个点、Terminal-Bench v2.1 涨 8.5 个点。这不是底层算法突破,是一条非常扎实的"数据侧"工程路线——但数据侧恰恰是目前 agentic coding RL 最卡脖子的地方,值得细读。
论文信息
- 标题:CodeMidas: Scaling Agentic Coding RL Environments from Code Itself
- 作者:Bowen Ye、Lei Li、Shicheng Li、Zihao Yue、Linghao Zhang、Hanglong Lv、Yuanxin Liu、Wenhan Ma、Hao Tian、Rang Li、Jinhao Dong、Yikai Zhao、Xiangwei Deng、Hailin Zhang、Liang Zhao、Qi Liu、Lingpeng Kong、Tong Yang、Fuli Luo(共同通讯)
- 机构:小米 LLM Core、北京大学、香港大学、中国人民大学
- 链接:https://arxiv.org/abs/2609.22068
- 发表日期:2026 年 9 月 18 日
🎯 问题动机:RL 环境的天花板,不在代码量,在"开发记录"
做 agentic coding RL 的人最近应该都有体感:模型进步的速度,开始被训练环境供给的速度拖住了。
一个可用的 RL 训练任务需要三样东西:明确的任务陈述、一个能跑起来的开发环境、一个可信的验证器。代码从来不缺——GitHub 上的开源仓库要多少有多少。缺的是"把代码变成任务"的那条转换通道。
现有的转换通道几乎都走同一条路:依赖开发产物。从 issue 和 PR 里挖任务描述(SWE-bench 那一脉),围绕已有测试合成任务,或者直接拿 docstring 当规格说明。这条路能 work,但它天然有个筛选偏置——只有那些被开发者认真记录过、测试过、文档化的功能,才有资格变成训练任务。一个代码库里大量"能跑、有用、但从没被写过 issue"的功能,全部被挡在门外。
我的第一反应是:这限制真的有那么严重吗?看论文里的 Table 1 对比就明白了——对比的 pipeline 里,SWE-rebench V2 覆盖 20 种语言、MindForge 15 种、SWE-Hub 11 种,其余大多只有 1 种,而它们在"不需要 issue/PR/commit/已有测试/书面描述"这五栏里多少都有依赖项。CodeMidas 是唯一五行全打勾、且覆盖 23 种语言的方法。
这个对比很说明问题:一旦你不再依赖开发记录,语言覆盖和领域覆盖就立刻打开了,因为任何能编译能跑的代码库都是候选。
🏗️ 方法核心:一个四阶段的"点金"流水线
CodeMidas 这个名字起得挺贴切——Midas 点石成金,它点代码成环境。核心思想一句话:已实现的功能本身就是最好的任务素材,它同时提供了任务的基础(要实现什么)和参考解(原始实现),而源代码的公开接口和可观察行为就是规格的来源。

图 1:CodeMidas 全流程。注意中间那个漏斗——从 22,575 个候选任务一路筛到 5,545 个,留存率不到四分之一。这个筛选力度本身就是论文想强调的:质量是筛出来的
每个产出的任务由三部分组成:任务陈述、容器化开发环境、一个对 solver 不可见的隐藏验证器——评分时才注入,返回二元的 0/1 奖励。
任务设计:把实现"挖"出来,留下一个真实的坑
智能体先读代码库结构和构建元数据,找那些有公开入口点、有可观察结果的功能。支持的接口形态有三种:命令行工具(看进程输出)、纯库函数(看返回值)、有状态库 API(看跨调用的状态变化)——这个分类挺务实的,基本覆盖了真实项目里功能的主要暴露方式。
找到目标功能后,移除选定的核心实现,把剩余代码整理成一个连贯的开发起点。原始实现单独留着当参考解。任务陈述只定义输入、可观察行为和必须保留的公开接口,内部实现自由度完全留给 solver。
这里有个细节我很欣赏:论文明确优先选择"需要跨代码库推理"的任务。最终数据也印证了这点——65.9% 的任务参考解涉及至少两个源文件。不是那种改一个函数就完事的玩具题。
测试构建:断言的期望值,必须来自真实执行
这一步解决的是"测试从哪来"的问题。既然不依赖已有测试,那就自己造——但造法有讲究。
智能体把任务陈述里的行为要求映射成测试输入和边界用例,然后在代码库的参考副本上真实执行,记录结果作为断言期望值。陈述里没固定的方面,就只检查约束本身。论文给的例子很具体:可以强制要求抛出的异常类型,但不固定报错消息的具体措辞——因为那是实现自由度。
更狠的是后面的断言审查环节:智能体逐条检查断言里有没有不被任务陈述支持的限制——确切措辞、偶然顺序、内部结构——全部替换成行为检查。如果某条断言依赖私有符号且找不到行为层面的替代方案,整个任务直接拒绝。
说实话,做过测试生成的人都知道,"测试意外绑死实现细节"是这类流水线最常见的隐性毒药。它不会让你的环境跑不起来,但会让正确的替代实现被误判为失败——RL 训练里这就是在给模型喂错误奖励。把这个审查显式做成 pipeline 的一环,是被坑过才会有的设计。
执行一致性与 rollout 后过滤:宁可错杀,不可放过
第三阶段做环境准备和执行一致性检查:统一基础镜像装依赖,清掉所有可能泄露被删实现痕迹的产物(编译输出、缓存、构建智能体遗留文件),连与目标功能相关的原始测试也一并移除。然后每个任务在 6 个全新容器里跑检查——2 个装空起点(必须都失败)+ 4 个装参考解(必须都通过),验证 fail-to-pass 转换稳定成立。
第四阶段是 rollout 后过滤,三道闸:
- 泄露过滤:用对抗性 rollout 主动诱导智能体"作弊"——去搜编译产物、缓存目录、已安装的目标项目副本,看能不能绕过开发直接恢复答案。确认可绕过的任务,拒绝。
- 解答审计:编程智能体每任务试 4 次,审查智能体对照陈述、验证器和参考解,专门抓假阳性(错解过了测试)和假阴性(正解没过)。验证器有缺陷的,拒绝。
- 结果过滤:前沿模型多次尝试后,全过或全败的任务都不要——全过可能太简单,全败往往指向测试太弱或陈述有缺漏。只留"有成功也有失败"的。
第三道闸初看有点反直觉——全败的任务为什么不修一修留着?但站在 GRPO 的角度想就通了:组内奖励全零或全一,优势估计直接退化,这种任务对训练梯度没有贡献,留着还浪费 rollout 预算。这个过滤标准与其说是质量控制,不如说是"为 GRPO 量身定制"。
📊 数据集:5545 个任务,成色如何

图 2:语言分布。前 10 种语言覆盖 98.2% 的任务,全集横跨 23 种语言。注意 TypeScript 和 Go 的占比——这在依赖 issue 的 pipeline 里很难见到,因为它们的高质量问题池远不如 Python 深

图 3:领域分布。前三名合计 45.6%,但长尾领域加起来也不小——这是"只看源代码"路线的直接红利,硬件、区块链这类领域的开源项目很少走 issue 驱动的开发流程

图 4:参考解规模。中位数 142 行、四分位距 66–305 行——这个量级说明任务不是单行修复,而是实打实的功能实现
任务难度这个维度值得多说一句。142 行的中位 patch,配上"65.9% 跨多文件",再对照 rollout 过滤里"前沿模型也会失败"的筛选标准,这批任务的平均难度应该明显高于 SWE-bench 里大量单行修复的样本。这对训练是利好——但对照后文基准结果时要记住这一点。
🧪 实验:五个基准全线上涨
训练配置很朴素:MiMo-V2.5 作为初始策略,GRPO,奖励就是验证器的 0/1 结果,没有奖励模型,没有学习式验证器,优势归一化也关了。Batch 32、每任务 32 个 rollout、最大 500 轮交互、response 上限给到 516k tokens——这个上下文预算给得相当慷慨。
评估用五个外部基准加一个内部验证集(CodeMidas Val,200 个不与训练集重叠的抽样任务)。

图 5:五个外部基准全部上涨,右侧标注绝对提升的百分点
| 基准 | 初始 MiMo-V2.5 | CodeMidas RL 后 | 绝对提升 |
|---|---|---|---|
| SWE-bench Pro | 50.3 | 54.4 | +4.1 个点 |
| DeepSWE | 10.0 | 21.7 | +11.7 个点 |
| ProgramBench(Almost Solved) | 4.5 | 21.5 | +17.0 个点 |
| RepoZero C2Rust | 40.5 | 51.8 | +11.3 个点 |
| Terminal-Bench v2.1 | 63.7 | 72.2 | +8.5 个点 |
几个观察。涨幅最大的是 ProgramBench——整程序构建任务,涨 17 个点,从 4.5 到 21.5。这跟训练任务的形态(从空起点实现完整功能)高度同构,属于意料之中。真正让我意外的是 DeepSWE 直接翻倍还多,从 10.0 到 21.7。基数低是一方面,但翻倍级别的提升说明训练分布里"跨文件、需要探索"的任务确实补上了 issue 修复需要的能力。
SWE-bench Pro 只涨 4.1 个点,看起来最少,但它基数本来就高(50.3),而且是五个基准里离训练分布最远的一个。这个涨幅我觉得是合理的。

图 6:内部验证集的学习动态。step 40 之后每个检查点都稳定高出初始策略 8–10 个百分点,曲线没有塌方的迹象
🔬 消融:质量和数量,哪个更值钱?
这是全文我最喜欢的一组实验。四个设置对比:高质量 1k / 3k / 完整 5k 任务池,外加一个 vanilla 8k——约 8000 个过滤前的任务,没做环境清理、没做执行一致性检查、没做三重 rollout 过滤,训练配置完全相同。

图 7:CodeMidas Val 上的学习曲线对比。vanilla 8k 那条虚线波动明显更大,这很符合直觉——脏环境带来的噪声奖励会直接污染梯度

图 8:注意看——高质量 3k 在全部三个评估上都超过了 vanilla 8k。5545 个精选任务打不过 3000 个精选任务的反面,是 8000 个脏任务打不过 3000 个干净的
两个结论都硬:
- 数量单调有效:1k → 3k → 5k,DeepSWE 上 17.57 → 19.05 → 21.70,Val 上 41.30 → 43.22 → 44.73。高质量任务池的 scaling 没有饱和迹象。
- 质量比数量值钱:完整 5k 对 vanilla 8k,SWE-bench Pro 高出 0.59 个点、DeepSWE 高出 4.59 个点、Val 高出 4.49 个点。更狠的是 3k 干净任务就在三个评估上全部打赢 8k 脏任务。
做过 RL 数据工程的人看到这里应该会心一笑。"数据量翻倍不如数据洗一遍"这件事在 SFT 时代就是常识,但在 agentic RL 的环境里被定量验证一次,价值不小——因为这里的"脏"不是标注错误,是验证器本身在撒谎。
🔍 行为分析:模型到底学会了什么
分数涨了,但涨在哪?论文用三组行为指标拆解了 rollout 轨迹,这是比分数本身更有信息量的部分。
训练早期到晚期:首次编辑前的 read/search 调用从 27.2 涨到 40.1(多了 12.9 次),代码起草比率(Write/Edit 的内容先在推理里出现过的比例)从 0.358 涨到 0.629,最终编辑后的不同验证命令数从 2.03 涨到 2.53。
翻译成大白话:模型学会了先看清楚再动手、想清楚再写、写完了换着花样自测。

图 9:一个 rollout 里三种行为的实拍。注意右列的自我验证——模型自己构造了一个 .secret.csv 来测两种 flag 设置,这种"自造测试用例"的行为和通过率强相关
相关性数据也给了:在 Val 集上同任务同检查点内比较,自己编写并执行检查的 rollout 平均 pass rate 高 4.2 个点(95% CI: 1.8–6.6)。探索行为的增益是 0.7 个点但置信区间跨零——说明探索更像是必要不充分条件,真正和成功率硬挂钩的是自验证。
更关键的是这些行为泛化到了外部基准:SWE-bench Pro 上探索调用从 23.1 涨到 35.5,Terminal-Bench 上从 11.9 涨到 16.8。有个有趣的分化——ProgramBench 上探索暴涨(55.7 → 83.6)的同时,总交互轮次反而从 155.1 降到 122.8。看得多了,话反而少了。我理解成:探索效率提升后,模型不再需要靠反复试错来定位问题。这个解释论文没明说,是我自己的推测,不一定对。
🤔 我的判断
这篇论文最值钱的地方,一句话:把 RL 环境构建的瓶颈从"开发记录"解绑到了"源代码"上,并且用消融实验证明了清洗环节每一分投入都有回报。
也要泼几盆冷水。
其一,整条 pipeline 的成本结构论文没怎么展开。从 22,575 个候选筛到 5,545 个成品,每个阶段都是智能体在跑——探索、写测试、审查断言、对抗性泄露检查、每任务 4 次审计 rollout 再加多次结果过滤 rollout。这个 agentic compute 的总量绝对不小。"scaling"这个词用在任务数上成立,但单位任务的成本到底是涨是跌,没有数字。这决定了这条路能不能被算力有限的团队复现。
其二,二元 0/1 奖励加 142 行中位 patch 的任务,信用分配的粗糙度可想而知。GRPO 组内全零全一被过滤掉了一部分,但"部分正确的实现"在这种奖励下依然只有失败一个标签。后面接过程奖励或者测试粒度的部分奖励,是显而易见的下一步。
其三,隐藏验证器的思路防了"读测试写代码"的投机,但代价是验证器质量成了整个系统的单点。论文用解答审计抓了假阳性假阴性,抓得干不干净,直接决定训练信号的天花板。从 22,575 筛到 5,545 的留存率看,这个单点的误伤率应该不低——只是误杀总比漏检强。
跟同期工作摆在一起看:SWE-smith、SWE-rebench 这类工作走的是"从已有测试和 issue 出发扩规模",CodeMidas 走的是"扔掉开发产物、直接从代码长出任务"。两者不矛盾,甚至互补——后者的覆盖面前者碰不到,前者现成的测试资产后者也没必要重新造。但论对"任务多样性"这个根本瓶颈的推进,CodeMidas 这条路的想象空间明显更大。
对工程的启发很直接:如果你在为 coding agent 攒 RL 环境,别再只盯着 issue 池了,你手里任何能跑的代码库都是任务矿。另外那个"6 容器一致性检查 + 三重 rollout 过滤"的组合拳,成本不高、效果在消融里被验证得明明白白,可以直接抄。
觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我