[NeurIPS'25 spotlight]

Abstract

尽管语言模型(LMs)在软件工程领域近年来取得了显著进展,但训练数据的收集仍是一大痛点。现有数据集规模较小,训练实例最多仅有数千条,来源也不超过11个GitHub仓库。构建此类数据集的流程往往十分复杂,需要耗费数百小时的人工劳动;配套的执行环境还会占用数TB的存储空间,严重制约了其可扩展性与易用性。

为解决这一痛点[pain point],我们提出了SWE-smith——一个用于大规模生成软件工程训练数据的新型流水线[a novel pipeline for generating software engineering training data at scale]。对于任意Python代码库,SWE-smith能够自动构建对应的执行环境,并自动合成数百至数千个任务实例[task instances],这些实例会导致代码库中已有的测试用例失败。借助SWE-smith,我们构建了一个包含5万条实例、来源于128个GitHub仓库的数据集,规模比此前所有工作大一个数量级。

基于此,我们训练了SWE-agent-LM-32B模型,在SWE-bench Verified基准测试上实现了40.2%的Pass@1解决率,达到开源模型中的最优水平。我们将SWE-smith的全部资产(数据收集流程、任务实例、轨迹数据及模型权重)完整开源,以降低自动化软件工程领域LM系统研究的门槛。所有资源均可在 https://swesmith.com 获取。

1 Introduction

语言模型(LM)智能体,如SWE-agent(Yang et al., 2024a)和OpenHands(Wang et al., 2024),在自动化软件工程[automating software engineering](SE)任务方面取得了显著进展,这一进展由SWE-bench(Jimenez et al., 2024b)等基准测试持续追踪。
然而,最有效的智能体仍依赖于专有语言模型,因为构建面向软件工程的开源语言模型仍受制于大规模、高质量训练数据的匮乏。为确保开源研究在该领域持续保持竞争力,开发可大规模收集软件工程训练数据的基础设施至关重要。
当前开源生态系统为训练软件工程语言模型提供了两类数据来源。一种简单的方法是从GitHub仓库中爬取拉取请求(pull requests, PR)和议题(issue)。然而,由于缺乏执行环境或测试用例,这些实例无法对生成的解决方案进行可靠验证,语言模型只能从代码的表层形式[the surface form of code]中学习(Xie et al., 2025a),或依赖基于表面字符串相似度的奖励信号[rewards based on superficial string similarity](Wei et al., 2025)。
相比之下,SWE-bench通过对提出的解决方案运行单元测试[unit tests],提供了可靠的验证机制。另一类工作则将SWE-bench的数据收集策略[SWE-bench collection strategy]直接扩展到新的代码仓库,用于训练目的(Pan et al., 2024)。这为训练和蒸馏语言模型智能体提供了灵活的环境,因为我们可以生成智能体轨迹[agent trajectories]并根据单元测试结果对其进行过滤。
然而,该方法的可扩展性受到SWE-bench数据收集策略本身局限性的严重制约。SWE-bench的过滤流程最终只保留了少量[pull requests]PR——这些PR不仅需要解决一个GitHub议题,还需要对单元测试进行有实质意义的修改。此外,为每个实例配置执行环境需要大量的人工干预。
本文介绍了SWE-smith工具包,它将SWE-bench灵活的执行环境与可扩展的实例收集方法有机结合(见图1)。
Figure 1: Scaling task instances (left) and performance (right) for SWE-agent’s with SWE-smith. Using SWE-smith, we can create 100s to 1000s of instances for any Python codebase,
enabling us to train SWE-agent-LM-32B which achieves 40.2% on SWE-bench Verified.

SWE-smith集成了多种在现有GitHub仓库中自动合成缺陷的技术,包括:(1)利用语言模型生成函数的错误重写[errant rewrites of functions];(2)以程序化方式修改函数的抽象语法树(abstract syntax tree, AST);(3)[undoing]撤销已有PR;(4)组合多个缺陷[combining bugs]。

我们的核心洞察在于:基于执行的验证[execution-based validation]不仅能够验证所提出的解决方案,还能识别出会导致严重软件退化[software regression](即导致测试失败[break tests])的缺陷候选项[bug candidates]。

Figure 2: SWE-smith creates training data for software engineering agents by crafting bugs
into real codebases. Given a codebase, we employ several strategies to create task instances
that break existing tests. Using SWE-smith, we create 50k+ task instances with execution
environments from 128 real world repositories.

简而言之,SWE-smith提出了如图2所示的任务创建工作流程。给定一个代码库[codebase],我们使用SWE-agent(Yang et al., 2024a)自动构建相应的执行环境。在此环境中,我们利用上述技术自动合成数百至数千个任务实例。最后,我们借助语言模型自动生成真实感强的议题描述[issue descriptions]。

SWE-smith的设计显著减少了构建执行环境所需的人工投入[human labor]和存储开销[storage required]。借助SWE-smith,我们构建了一个涵盖128个真实GitHub仓库、共计5万条任务实例的数据集。基于SWE-smith数据集,我们在SWE-bench Verified基准上取得了开放权重模型的新一代最优成绩。

利用SWE-smith任务实例,我们通过Claude 3.7 Sonnet生成了5,016条专家轨迹,并在此基础上对Qwen 2.5 Coder Instruct 32B进行微调。所得模型SWE-agent-LM-32B在SWE-bench Verified上单次尝试即可达到40.2%(+33.4%)的解决率,且无需推理时扩展。这一结果刷新了开放权重模型的最优水平。SWE-smith数据集的规模与多样性使我们得以开始探索并验证有关SWE智能体开发的若干规律性结论与有趣现象。在更多实例、更多缺陷类型和更多代码仓库上进行训练是有益的。

语言模型生成的议题文本能够有效逼近真实议题。通过SWE-smith,我们发现可以针对特定代码仓库对语言模型进行优化,同时仅付出较小的泛化性能损失。我们将SWE-smith作为开源工具包发布——涵盖任务实例、执行环境和专家轨迹——以推动更强大的开源语言模型智能体的发展。

2 SWE-smith: Software Task Generation at Scale

SWE-smith数据收集策略的核心原则是:首先定义执行环境,然后在环境中合成任务实例。从概念上讲,这与SWE-bench的方法恰好相反——SWE-bench优先识别任务实例,再尝试为每个实例构建对应的环境。
本节将详细描述该流程,并说明SWE-smith在代码仓库数量、任务实例规模和存储效率方面如何实现显著更优的可扩展性。

2.1 Collection 2.1 数据收集

为测试通过的代码仓库构建执行环境。给定一个代码仓库,我们在其最新提交上运行SWE-agent(Yang et al., 2024a),最多执行100步,指示其安装代码库并运行测试套件。随后,我们人工验证安装与测试指令,检查现有测试的通过率是否超过80%,最终为该仓库创建Docker镜像。
我们以2024年11月18日Python包索引(Python Package Index, PyPI)中下载量最高的5,000个包所对应的代码仓库为目标,按GitHub星标数[GitHub stars]对PyPI包进行排序,剔除星标数低于1,000的包,同时排除全部12个SWE-bench测试仓库。

Creating task instance candidates.创建任务实例候选。

如图2所示,每种策略以代码仓库作为输入,生成以.diff文件[.diff files]形式表示的任务实例候选。
针对每个代码仓库,我们采用四种不同策略来创建候选任务实例。
  • 语言模型生成[LM Generation]: 针对每个仓库,我们识别所有程序实体(函数、类),并采取两种方式:(1)将函数提供给语言模型,提示其引入错误修改(以下简称"LM Modify");(2)仅提供函数头和文档字符串,要求语言模型对其进行重写("LM Rewrite")。
  • 程序化修改[Procedural Modification]: 针对每个函数,我们获取其代码的抽象语法树(AST)表示,然后随机执行一种或多种变换(例如,删除条件语句/循环、修改运算符,以及另外11种变换,详见表8)。
  • 组合缺陷[Combine Bugs]: 语言模型生成和程序化修改的任务实例仅针对单个函数或类进行修改。为创建需要编辑代码库多处位置的更复杂任务,我们设计了"补丁组合"[Patch Combination]策略,通过聚合来自相同文件或模块的候选实例来构建任务。
  • 反转PR(即"PR镜像")[Invert PRs (or "PR Mirror")​​​​​​​]: 针对每个仓库,我们收集所有修改Python文件的PR。对于每个PR,我们尝试在当前版本的仓库中撤销其修改。为此,我们将PR的代码变更(.diff纯文本)提供给语言模型,提示其对每个受影响的文件进行重写,使PR的编辑被还原。与SWE-bench不同,我们不检出PR的基础提交[PR's base commit],因为上一步骤确定的安装规范可能与仓库的旧版本不兼容。

Execution-based validation of candidates. 基于执行的候选验证。

我们将每个候选补丁[candidate patch]应用于对应的代码仓库,运行测试套件,仅保留那些导致一个或多个原本通过的测试失败的补丁(称为"由失败到通过"测试,即F2P测试)。

出于效率考虑,我们将测试运行时间限制为两分钟;导致测试运行时间超过此限制的缺陷候选将被丢弃。

Generating problem statements. 生成问题描述

与缺陷关联的议题文本会显著影响任务实例的难度和可解性。议题文本中对"预期"行为与"实际"行为["expected" vs. "observed" behavior]的详细描述,以及缺陷复现代码,会深刻影响智能体定位缺陷或迭代改进解决方案的能力。

我们探索了§D中详细介绍的多种技术,最终采用了一种简单的策略。针对每个任务实例,我们向语言模型提供.diff补丁[.diff patch]、随机选取的F2P测试源代码[a random F2P test],以及在应用缺陷补丁后运行测试套件所得的执行输出[execution output]

PR是Pull Request的缩写,直译为"拉取请求",是GitHub上的一种协作机制。

核心概念

当你想向某个代码仓库贡献代码时,通常不能直接修改别人的代码。你需要先将仓库"叉"(fork)一份到自己账号下,在自己的分支上做修改,然后向原仓库发起一个"请求",请求原仓库的维护者把你的修改合并(merge)进去——这个请求就叫PR。

一个具体例子

假设你在使用PyTorch,发现某个函数有个bug:当输入为空列表时会崩溃。你的修复流程大概是这样的:

  1. 将PyTorch仓库fork到自己账号
  2. 在自己的分支上修改代码,加入对空列表的判断
  3. 向PyTorch官方仓库提交一个PR,标题可能是:"Fix: handle empty list input in xxx function"
  4. PR里会包含你的代码改动(即一个.diff文件,显示哪些行被删除、哪些行被新增)
  5. PyTorch的维护者审查你的代码,觉得没问题后点击"Merge",你的修改就正式进入了主代码库

和SWE-smith的关系

SWE-smith里的"Invert PRs"策略,就是把这个过程反过来——找到历史上已经被合并的PR(即已经修复好的bug),然后用语言模型把这个修复"撤销"掉,人为地把代码还原成有bug的状态,从而制造出一个训练任务实例。这样做的好处是,这些bug来自真实的开发场景,非常自然且有代表性。

点击任意一个PR查看详情 进入一个PR后,你会看到几个子标签:

  • Conversation:讨论区,包含PR描述、代码审查评论
  • Commits:这个PR包含哪些提交记录
  • Files changed:最关键的部分,显示具体的代码改动,即.diff内容——绿色行表示新增,红色行表示删除

我们提示语言模型生成GitHub议题风格的文本,其中包含基于F2P测试的缺陷复现代码。

What human labor remains? 还需要哪些人工劳动?

需要人工参与的步骤有:(1)从智能体轨迹中解析正确的安装配置流程(每个仓库约7分钟);(2)为测试输出实现解析器[the parser](每个仓库约1分钟)。

第二步所需时间极少,因为具有相同测试基础设施的仓库(如使用pytest的仓库)可以复用同一解析器。SWE-smith消除了为代码库的多个历史版本逐一确定安装规范的人工需求,而这正是SWE-bench数据收集中耗时最长的步骤。

构建SWE-smith总计仅花费了一位作者约20小时的人工劳动。

先回顾SWE-bench的痛点

SWE-bench的做法是:找到一个PR → 然后试图为这个PR对应的历史版本的代码库搭建环境。问题在于,一个仓库在不同时间点的依赖、Python版本、配置文件都可能不同,所以每个PR实例都可能需要一套独立的环境配置,人工介入非常频繁。


SWE-smith的关键思路转变

SWE-smith反过来:先把当前最新版本的环境搭好,再在这个环境里批量制造bug。

这意味着一个仓库只需要搭一次环境,然后可以在这个环境里生成数百甚至数千个任务实例。摊下来每个实例的人工成本极低。


智能体轨迹是怎么来的?

这里用到了SWE-agent来自动完成安装。具体流程是:

  1. 给SWE-agent一个仓库,让它自动尝试安装这个代码库并运行测试套件,最多执行100步
  2. SWE-agent会一步一步地执行命令,比如pip install -e .pytest等,这一系列操作记录下来就是智能体轨迹(agent trajectory)
  3. 人工要做的只是看一眼这个轨迹,从中找到"哪几条命令是真正有效的安装步骤",大约7分钟

所以轨迹是SWE-agent自动生成的,人只是做最后的核查。


解析器又是什么?

安装完之后还需要运行测试,测试的输出(比如pytest的输出)需要被解析,以判断哪些测试通过、哪些失败。这个解析器需要人写一次,但因为很多仓库都用pytest,写一次可以反复复用,所以平均只要1分钟。


总结一下时间压缩的原因

步骤 SWE-bench SWE-smith
环境搭建 每个PR一套,人工密集 每个仓库只搭一次,SWE-agent自动完成
版本兼容 需处理多个历史版本 只用最新版本
人工核查 大量 每仓库约8分钟

本质上就是把"一个实例一套环境"变成了"一个仓库一套环境,批量产出实例",这是效率提升的根本原因。

2.2 Features 2.2 特性

我们将SWE-smith应用于128个Python代码仓库,共生成5万条任务实例。表1列出了关键统计数据。

平均每个仓库生成381条任务实例,其中pandas-dev/pandas仓库最多,达2277条。图3汇总了各仓库任务实例的分布情况,其中代码仓库被归入六个大类之一。SWE-smith的构建总花费为1360美元,其中生成缺陷花费1000美元,使用SWE-agent自动安装仓库花费160美元,为1万条缺陷生成议题描述花费200美元。平均每条议题的生成成本为2.54美分。

Bug generation strategies vary in cost and yield rate. 各缺陷生成策略在成本和产出率上存在差异。

在依赖语言模型的方法中,PR镜像成本较高,因为该任务需要重写整个文件,而LM Modify和LM Rewrite仅针对单个函数进行操作。产出率[Yield rates]受限于两方面原因:一是相关代码变更缺乏测试覆盖,二是缺陷候选实际上并未引入有意义的问题。例如,对于LM Rewrite,语言模型被要求重新实现函数,而并非明确要求引入缺陷。当明确要求引入缺陷时(LM Modify),产出率则更高。

How difficult are SWE-smith task instances? SWE-smith任务实例的难度如何?

为评估SWE-smith生成的任务实例是否真实且具有挑战性,我们基于Chowdhury et al.(2024)提供的1,699条人工标注(任务,标签)数据对Qwen 2.5 32B模型进行训练,使其能够将任务评定为(简单、中等、困难)三个难度级别。为量化难度,三个难度标签分别对应数值1/5/9。该模型在测试集上达到75.3%的准确率。

随后,我们对SWE-smith和此前SWE-bench风格数据集(Chowdhury et al., 2024; Jimenez et al., 2024b; Pan et al., 2024; Yang et al., 2024b)中的任务实例进行难度评估。SWE-smith任务实例涵盖了广泛的难度范围,与SWE-bench和SWE-gym相近。SWE-smith的平均难度得分(各缺陷生成策略介于5.27至5.72之间)与SWE-bench(5.01)和SWE-gym(5.62)相当。

这表明SWE-smith能够支持真实且难度适中的评估任务。关于各缺陷生成策略为何产生不同难度级别的讨论,以及各数据集难度分布的可视化结果,详见§E。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐