微信扫一扫,关注公众号

  • 科技行者

  • 算力行者

见证连接与计算的「力量」

首页 CodeMidas:把开源代码库变成训练AI编程能力的练兵场

CodeMidas:把开源代码库变成训练AI编程能力的练兵场

2026-10-03 11:01
分享至:
----..---.-...-/--...-.-......./-...-....-..--../-............-.- ----..---.-...-/--...-.-......./-...-....-..--../-............-.- ----..---.-...-/--...-.-......./-...-....-..--../-............-.- ----..---.-...-/--...-.-......./-...-....-..--../-............-.-
2026-10-03 11:01 • 科技行者

2024年,训练AI写代码的方法遇到了一个不算新鲜但一直没解决好的问题。

你想让一个模型学会像真正的程序员那样干活,那它就得在真实的软件项目里摸爬滚打,遇到各种各样的任务,还要有人告诉它做对了没有。问题是,真实世界的任务从哪来?靠人一条条写,太慢太贵;靠模型自己瞎编,又怕跟真实场景脱节。于是大家把主意打到了开源代码托管平台上,那里堆着几百种编程语言写成的海量项目,简直是天然的题库。

但这里藏着一个别人没太注意的限制。已有的方法基本上都得靠项目里留下的"痕迹"来出题:有人提的issue、别人写的pull request、开发者留下的commit记录,或者干脆是项目自带的文档和测试用例。

这就好比你想给学生出一套编程练习题,但你规定自己只能从老师批改过的作业本里摘题目。那些从没被人明确提出过bug、没写过文档、没配测试的功能,哪怕代码本身写得再漂亮、逻辑再复杂,你也没法把它变成一道题。这不是代码不够多的问题,是能拿来出题的代码,一直被这些"记录"给卡住了脖子。

如果不解决这个限制,会发生什么?意味着大量已经实现、已经跑通、已经在生产环境里工作的功能代码,永远进不了训练数据。就像图书馆里有几万本书,但你规定只能把读者写过读后感的书拿出来教学生阅读,剩下的书哪怕内容再好,也只能烂在书架上。

来自小米大模型团队等机构的研究者们,提出了一个叫CodeMidas的方案,思路挺直接:别管这段代码有没有issue、有没有PR、有没有人写过文档,只要它是能跑起来的代码,就能变成一道训练题。

代码本身,就是唯一的原材料。

一、这件事到底难在哪

先说说传统做法的具体样子。像SWE-bench这类经典数据集,是从GitHub上抓取issue和对应的修复PR配对而成,模型要做的就是看着issue描述去写出能让相关测试通过的补丁。这类方法效果不错,但天花板很明显:只有那些认真写了issue、认真提了PR的仓库才能贡献任务。

另一条路线是围绕已有测试做文章,比如故意往正确代码里注入bug,让模型去修,这类方法(如SWE-smith)不需要issue,但仍然依赖项目已经写好的测试用例作为"地基"。还有的方法利用函数文档字符串反推需求描述。

这几条路子有个共同的软肋,那就是它们都在某个环节上依赖开发记录*:指issue、PR、commit这类记录软件变更过程的文本或文件。

数据集的规模天然被这些记录的覆盖率锁死了。论文里做了一张对比表,列出了七八个同类方法各自还需要哪些输入才能工作,结果一目了然:CodeMidas是表里唯一一个完全不需要issue、不需要PR、不需要commit、不需要已有测试、也不需要现成描述文字的方法,同时支持的编程语言数量也是最多的,达到23种。

这就好比考古学家发掘古代遗址,过去的做法是只挖那些地表上留有明显标记(比如墓碑、界碑)的地方,CodeMidas相当于换了个思路:直接对整片土地做地质扫描,任何埋在地下的东西都有机会被发掘出来,不再依赖地表上有没有人立过碑。

如果继续依赖开发记录,代价是显而易见的:数据集规模永远追不上开源世界代码总量的增长速度,而且不同语言、不同类型的项目在issue和PR的丰富程度上天差地别,这会导致训练数据在语言和领域上严重失衡。

二、CodeMidas怎么把一段代码变成一道题

整套流程分成四个阶段,论文里配了一张漏斗图,从初筛的22575个候选任务,一路收窄到最后保留的5545个高质量任务,中间每一步都在做减法,把不靠谱的题目筛掉。

**任务设计和代码库改造**

第一步,让一个智能体(agent,也就是能自主执行多步操作的AI程序)去逛这个代码库,找那些有明确对外接口、行为可观察的功能。可能是命令行工具,可能是纯函数,也可能是有状态的类库API。找到候选功能后,agent会顺藤摸瓜,把这个功能涉及的核心实现代码整段删掉,同时调整周围代码,让剩下的部分依然能构成一个连贯的、待完成的项目起点,原来被删掉的代码则单独保留,作为这道题的参考答案。

这个过程有点像把一台已经组装好的机械钟拆掉齿轮组,但表盘、指针、外壳全部保留原样,让维修学徒照着表盘上残留的痕迹重新做一套能走时的齿轮。如果直接把整个项目都清空重来,题目就失去了真实代码库该有的复杂度和依赖关系,学徒练的就不是修钟的本事,而是从零造钟,这和真实工作场景是两码事。

**执行驱动的测试构造**

光有题目和答案还不够,得有一把尺子来判断学生做得对不对。CodeMidas这一步的做法是,让agent把任务描述里提到的每一条行为要求,转换成具体的测试用例,然后拿参考答案(也就是被删掉的那段原始代码)在沙箱里真跑一遍,记录下真实的输出结果,作为这些测试用例的标准答案。

这里有个细节处理得挺讲究:如果任务描述里没有明确规定某个细节(比如报错信息的具体措辞),测试就不会死板地要求输出必须一字不差,只检查那些真正被要求的行为,比如是不是抛出了正确类型的异常。agent还会反过来审查每一条测试断言,把那些依赖内部实现细节、和任务描述无关的过度限制找出来并替换掉。

这一步的意义在于区分"必须做对的事"和"做法不重要的事"。就像批改一篇命题作文,你不能因为学生用了跟范文不一样的开头句式就判他跑题,你只该检查他有没有覆盖题目要求的核心论点。如果测试写得太死,会把很多用不同思路、但同样正确的解法误判为失败,这样的训练信号是有毒的,会教坏模型。

**环境准备和执行一致性检查**

准备好题目和测试后,还要确认这道题本身没有逻辑漏洞。CodeMidas会在六个全新的容器里跑测试:两个用空白(缺失核心功能)的代码库跑,必须全部失败;四个用参考答案跑,必须全部通过。

这一步是在确认"这道题确实有解,而且缺了这块代码就真的做不出来"。类比一下,出考卷前老师自己先做一遍标准答案,确认能拿满分,再故意空出那一栏交白卷试试,确认真的拿不到分,这样才能保证考卷本身没印错题。

**滚动执行后过滤**

这是CodeMidas整套流程里最花心思的一环,因为前三步只能保证测试逻辑上没问题,但没法保证题目没有"作弊漏洞"。这里做了三件事:

第一,泄漏检测。让另一个agent专门去代码库里翻找,看能不能靠一些残留的编译产物、缓存文件、构建过程中留下的痕迹,不做真正的开发工作就把答案套出来。这就好比考试前监考老师专门去搜查考场,看有没有小抄藏在桌肚里,发现了就直接取消这道题的资格。

第二,答案审核。让一个agent实际去解四遍这道题,再让另一个审核agent对照任务要求、参考答案和测试判定结果,检查有没有"明明做对了却被测试判错"(假阴性)或者"明明做错了却被测试判对"(假阳性)的情况,一旦发现测试本身有缺陷,这道题就被剔除。

第三,通过率筛选。用一个前沿模型对每道题多次尝试,如果全部尝试都通过,或者全部失败,这道题就会被拿掉,因为这两种极端情况说明不了任务本身到底有没有问题,可能是题目太简单/太难,也可能是测试有暗病,留着这种题对训练没有区分度。

经过这一整套流水线,最开始扫描出来的22575个候选任务,一路筛到只剩5545个,淘汰率超过75%。这个数字本身就说明了一件事:从代码里自动挖题,"能挖出来"和"挖得靠谱"完全是两回事,大部分初筛结果其实是带毛病的。

三、5545道题都长什么样

这批最终留下的任务,来自3185个不同的开源代码库,覆盖23种编程语言,横跨15个技术领域。

语言分布上,Python占21.4%,TypeScript占18.3%,Go占16.2%,加上C++和JavaScript,前五种语言就占了将近八成的任务量,不过剩下的18种语言里也有C、Java、Rust、Ruby、Kotlin等主流语言,覆盖面相当宽。

技术领域方面,系统软件类任务占比最高,达17.4%,其次是Web技术14.6%,开发者工具13.6%,这三块合起来接近一半。此外还有AI/ML、数据科学、多媒体、区块链、游戏开发、安全、硬件、移动开发等多个领域都有覆盖。

参考答案*:指CodeMidas在删除代码前保留下来、能让测试全部通过的原始实现,相当于这道题的标准答案。

参考答案的代码量中位数是142行,四分位区间在66到305行之间,超过六成的任务需要动两个以上的源文件才能完成,这说明这批任务不是那种"填一行空"的玩具题,而是需要模型理解跨文件依赖关系的真实工程任务。

四、拿这批题练出来的模型,到底强在哪

研究团队用这5545个任务,通过GRPO算法(一种强化学习训练方法)对MiMo-V2.5模型做了训练,然后在五个完全不相关的外部测试集上验证效果。

GRPO*:Group Relative Policy Optimization的缩写,一种强化学习训练算法,通过比较同一批多次尝试的相对得分来更新模型,不需要额外训练一个打分模型。

结果相当亮眼,五个测试全部提升,而且提升幅度都不小。

| 测试集 | 训练前得分 | 训练后得分 | 提升幅度 | 考察方向 |

|---|---|---|---|---|

| SWE-bench Pro | 50.3% | **54.4%** | +4.1个百分点 | 长周期软件工程任务 |

| DeepSWE | 10.0% | **21.7%** | +11.7个百分点 | 真实issue修复 |

| ProgramBench | 4.5 | **21.5** | +17.0个百分点 | 从零构建完整程序 |

| RepoZero C2Rust | 40.5% | **51.8%** | +11.3个百分点 | 代码翻译 |

| Terminal-Bench v2.1 | 63.7% | **72.2%** | +8.5个百分点 | 终端命令行操作 |

DeepSWE和ProgramBench的提升尤其值得说道说道。DeepSWE的分数几乎翻倍,从10%直接跳到21.7%,这意味着原本每十个issue只能修好一个,训练后能修好两个多。ProgramBench考察的是让模型从零重写一个完整程序,这个任务比修bug难得多,提升幅度反而是五个测试里最大的,达到17个百分点。

值得琢磨的是,这五个测试集覆盖的任务类型五花八门,issue修复、从零写程序、代码语言翻译、命令行操作,彼此差异很大,但训练效果都能迁移过去。这说明CodeMidas挖出来的任务,不是针对某一类狭窄场景的偏科训练,而是真的锻炼出了某种通用的编程能力。

五、任务数量和质量,哪个更重要

研究团队做了一组对照实验,专门回答一个问题:如果只看数量不看质量,会发生什么?

他们准备了四组训练数据:从高质量的5545个任务里随机抽1000个、抽3000个,以及全部5545个,再额外准备一组约8000个任务,这组是初筛后但没经过环境清理、执行一致性检查、也没经过后续过滤的"毛坯版"数据。

结果很说明问题。1000、3000、5545这三组高质量数据呈现清晰的递增趋势,在DeepSWE上的得分从17.57一路涨到19.05再到21.70,说明高质量数据是越多越好,没有出现边际效益递减的明显拐点。

但更值得关注的是那组8000个的毛坯版数据。即便任务数量比高质量的3000组还多,它在三个评测集上的表现却全部低于经过清理筛选的3000组,在DeepSWE上更是被5545组高质量数据甩开了4.59个百分点。

| 训练数据 | SWE-bench Pro | DeepSWE | CodeMidas Val |

|---|---|---|---|

| 高质量1k | 52.86 | 17.57 | 41.30 |

| 高质量3k | 54.02 | 19.05 | 43.22 |

| 高质量5k(全量) | **54.40** | **21.70** | **44.73** |

| 未清理8k | 53.81 | 17.11 | 40.24 |

这个结果推翻了一个直觉,很多人会觉得训练数据"多多益善",哪怕带点噪声也无所谓,反正数据量大能稀释掉。但这组实验清楚地告诉我们:3000道精心把关的题目,效果能超过8000道良莠不齐的题目。

这就好比健身,与其每天花两小时做一堆动作变形、姿势不标准的训练(哪怕训练时长更长),不如花四十分钟做几个动作规范、真正刺激到目标肌群的训练。数量堆上去了,但如果动作本身有偏差,练出来的可能是错误的发力习惯,反而不如少而精的训练更有效果。这也反过来证明了CodeMidas那套繁琐的过滤流程,泄漏检测、答案审核、通过率筛选,不是可有可无的装饰,是真正影响训练效果的关键环节。

六、训练过程中,AI的"行为习惯"发生了什么变化

除了看最终分数,研究团队还扒了训练过程中模型解题行为的变化,这部分分析挺有意思,相当于给AI做了一次行为观察。

他们盯了三个指标:代码库探索程度(编辑代码前先读了多少文件、搜索了多少次)、代码打草稿的比例(写进代码的内容有多少是之前在推理过程里就构思过的)、以及自我验证的多样性(写完代码后执行了多少种不同的验证命令)。

代码探索*:指agent在动手修改代码之前,通过读文件、搜索关键词等方式了解项目结构的行为,次数越多说明越谨慎、越不会瞎改。

数据显示,训练早期agent平均只做27.2次探索动作,训练后期涨到40.1次;打草稿比例从0.358涨到0.629,几乎翻倍;验证命令的多样性从2.03种涨到2.53种。三项指标全部同步上升,说明模型在强化学习的过程中,自己学会了"先想清楚再动手,动手后再检查"这套更靠谱的工作方式,而不是训练前那种上手就改、改完就交的莽撞风格。

更有说服力的是,研究者还专门验证了自我验证行为和最终成功率之间的关系:在同一个任务、同一个训练阶段下,那些agent自己主动写了检查代码并执行了的解答,平均通过率比没做自我验证的高出4.2个百分点。

这个发现最打动人的地方在于,这些行为变化不只出现在CodeMidas自家的测试集上,在完全没见过的SWE-bench Pro、ProgramBench、Terminal-Bench上同样能观察到类似的探索增加、验证增多的趋势。这说明训练学到的不只是"怎么答对CodeMidas的题",而是更底层的解题习惯,这种习惯能跨场景迁移。

有一个细节挺值得琢磨:在ProgramBench上,探索次数从55.7涨到83.6,交互轮数却从155.1降到了122.8,也就是说模型探索得更多了,但整体花的轮次反而更少了。这暗示模型学会了把力气花在刀刃上,前期多看几眼项目结构,能避免后面走弯路、反复试错,这和"磨刀不误砍柴工"是同一个道理。

七、这套方法的边界在哪

不过这里也得说句实话,CodeMidas这套流程本身极其依赖agent的能力。无论是任务设计、测试构造,还是最后的泄漏检测和答案审核,每一步都得靠另一个大模型来完成判断,这意味着如果底层用来做数据构造的模型本身能力有限,那生成出来的题目质量也会打折扣,这套方法某种程度上是在用AI的能力去生产训练AI的数据,存在一定的自举依赖。

另外,论文里提到最终保留的5545个任务,只占最初候选池22575个的24.6%,超过四分之三的候选题目在某个环节被剔除了。这说明"把任意一段代码变成一道靠谱的训练题"这件事本身成本不低,虽然比人工出题省事很多,但也远没到"随便拿一段代码就能直接用"的地步。

Q&A

Q1:CodeMidas是什么?

A:CodeMidas是一套自动化流程,只用源代码作为输入,就能把开源代码库里已经实现的功能变成可执行、可验证的编程训练任务,不需要依赖issue、PR、commit这类开发记录。

Q2:CodeMidas构建的训练数据集训练出来的模型效果怎么样?

A:研究团队用5545个CodeMidas任务训练MiMo-V2.5模型后,在DeepSWE、ProgramBench、Terminal-Bench等五个外部测试集上全部取得提升,其中ProgramBench提升了17个百分点,DeepSWE几乎翻倍。

Q3:CodeMidas的训练数据是不是越多越好?

A:不完全是,实验显示3000个精心筛选过的高质量任务效果能超过8000个未经清理的任务,说明数据质量比单纯堆数量更重要,但在保证质量的前提下,任务数量增加确实能带来持续的性能提升。

分享至
0赞

好文章,需要你的鼓励

推荐文章
----..---.-...-/--...-.-......./-...-....-..--../-............-.- ----..---.-...-/--...-.-......./-...-....-..--../-............-.- ----..---.-...-/--...-.-......./-...-....-..--../-............-.- ----..---.-...-/--...-.-......./-...-....-..--../-............-.-