SWE-bench 数据收集流水线:从 GitHub 仓库到可评估任务实例的完整构建指南
2026/9/17 7:14:19 网站建设 项目流程

SWE-bench 数据收集流水线:从 GitHub 仓库到可评估任务实例的完整构建指南

【免费下载链接】SWE-benchSWE-bench: Can Language Models Resolve Real-world Github Issues?项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-bench

本文以 SWE-bench 仓库swebench/collect目录的官方文档为主线,系统讲解评测基准构建流程中"仓库选择与数据抓取""基于属性的过滤"两大阶段:从 Top PyPI 包筛选仓库、镜像克隆、拉取全部 PR,到将 PR 转换为带 gold patch 与测试补丁的候选任务实例。读完本文,你将掌握如何在自己选定的 PyPI 仓库上跑通run_get_tasks_pipeline.sh全流程,理解每个输出文件(-prs.jsonl-task-instances.jsonl.all-task-instances.jsonl)的含义,并了解执行验证、版本标记与指令微调数据集的构建方法。

说明:SWE-bench 的数据收集流水线当前主要面向 PyPI 包(Python 生态)设计,官方表示未来希望扩展到更多仓库和语言。截至官方文档备注(2025-03-02),项目团队正推进任务实例生成过程的标准化与完全开源,并暂时不主动响应任务实例创建的查询;如需在私有场景生成实例,官方建议将仓库回退到包含最新验证代码的提交b4a40501b4d604dea28ad03418671cc597570bb9

SWE-bench 的评测任务由真实 GitHub 仓库中的 issue 与 PR 构造而成。如上图所示,整个收集流程分三个阶段层层递进:先从热门仓库批量抓取 PR(聚焦 Python 生态,官方论文使用的数据超过 90% 为 Python 代码),再通过属性过滤(PR 需"解决了一个或多个 issue"且"包含测试代码")筛选候选,最后由执行过滤("安装成功"且"PR 通过全部测试")把关质量。本文聚焦仓库代码中实现前两步的部分:swebench/collect/README.md及其配套教程 docs/assets/collection.md。

一、前置知识:收集流水线在 SWE-bench 中的位置

SWE-bench 论文将基准构建流程分为若干部分,而swebench/collect/目录承载其中前两部分:

  1. 仓库选择与数据抓取(Repo selection and data scraping):选定目标仓库,抓取其全部 PR 元数据。
  2. 基于属性的过滤(Attribute-based filtering):根据 PR 是否关联 issue、是否包含测试等属性,过滤出候选任务实例。

注意,官方强烈建议创建训练用任务的读者关注配套工具 SWE-smith(一个大规模创建执行环境与 SWE-bench 风格任务实例的工具包),它被设计为与 SWE-agent 高度兼容以生成训练数据,并与 SWE-bench 兼容以进行评测。而swebench/collect中直接可运行的核心入口是run_get_tasks_pipeline.sh脚本(其底层为 swebench/collect/get_tasks_pipeline.py)。

二、收集流水线的输出物

对每个以owner/name格式给出的仓库运行收集流水线,会依次生成三类文件:

输出文件内容用途
<repo>-prs.jsonl仓库中每一个 PR 的元数据(来自 GitHub REST API 的 List pull requests 接口),并附加解析出的resolved_issues字段中间产物,供build_dataset.py消费
<repo>-task-instances.jsonl.all全部"有效"任务实例(有关联 issue + 有 gold patch)可用于指令微调(fine tuning)数据构建
<repo>-task-instances.jsonl有效任务实例中同时带测试的那部分(候选评测实例)验证通过后可进入 SWE-bench 评测;.all文件同样包含这些实例

文件后缀很容易混淆,记住这个规律:.all是全集(所有带 gold patch 的实例),无后缀的是评测候选子集(额外要求带测试补丁)。

三、第一步:选择候选仓库

SWE-bench 的任务实例来自 issue 与 PR,因此理想的源仓库应当拥有大量 issue 和 PR。官方给出的参考来源是 Top PyPI packages 网站(按下载量排序的 PyPI 包榜单)。仓库 swebench/collect/get_top_pypi.py 提供了自动化的仓库初筛工具:

python get_top_pypi.py

该脚本通过 Selenium 打开 Top PyPI 页面并点击show(8000)展开完整榜单,随后用 BeautifulSoup 解析 HTML,对每个包抓取以下信息:

  • PyPI 页面 URL:通过包名链接定位;
  • GitHub URL:从 PyPI 页面中类名为vertical-tabs__tab--with-icon且文本包含 Source / Code / Homepage 的链接中提取(要求 href 含github);
  • Star 数与 Issue + PR 数:通过 GitHub API(api.repos.getapi.issues.list_for_repo)获取。

每行输出一个 JSON,形如{"rank": ..., "name": ..., "url": ..., "github": ..., "stars": ..., "pulls": ...},写入pypi_rankings.jsonl文件。脚本支持--max-repos参数(默认 5000)控制抓取数量;运行前必须设置GITHUB_TOKEN环境变量。拿到榜单后,即可从中挑选适合做任务实例源的高活跃仓库。

选定仓库后,官方教程建议先用make_repo.sh创建仓库的镜像副本:

./collect/make_repo/make_repo.sh scikit-learn/scikit-learn

镜像的作用是:将目标仓库完整复制到swe-bench-repos组织下(私有仓库),同时自动清理 GitHub 自动化文件(.github/workflows、Dependabot 配置、.devcontainer、Issue/PR 模板、CODEOWNERS等),避免镜像仓库的定时工作流打扰与 token 关联邮箱、或引入无关模板噪音。脚本流程为:校验目标仓库可访问 → 创建私有镜像仓库(名为owner__name)→git clone --bare+git push --mirror全量复制 → 克隆镜像 → 删除自动化文件并提交推送 → 清理本地目录。批量镜像场景可借助 swebench/collect/make_repo/call_make_repo.py,在脚本顶部的repos列表填入仓库名即可逐个调用。

四、第二步:收集候选任务实例

4.1 一键流水线:run_get_tasks_pipeline.sh

官方推荐直接用run_get_tasks_pipeline.sh完成"仓库 → 候选任务实例"的流水线。脚本本身是示例性质,需要你按需修改其中的参数:

# swebench/collect/run_get_tasks_pipeline.sh python get_tasks_pipeline.py \ --repos 'scikit-learn/scikit-learn', 'pallets/flask' \ --path_prs '<path to folder to save PRs to>' \ --path_tasks '<path to folder to save tasks to>'

从 swebench/collect/get_tasks_pipeline.py 的 argparse 定义看,get_tasks_pipeline.py支持以下参数:

参数类型说明
--reposlist要创建任务实例的仓库列表,如sqlfluff/sqlfluff,可用逗号分隔
--path_prsstr保存 PR 数据文件的文件夹路径
--path_tasksstr保存任务实例数据文件的文件夹路径
--max_pullsint(默认 None)最多记录的 PR 数量上限
--cutoff_datestr(默认 None)PR 截止日期,格式YYYYMMDD,早于该日期的 PR 不处理

底层逻辑(main函数)会:

  1. --repos--path_prs--path_tasks转为绝对路径并打印确认;
  2. 读取环境变量GITHUB_TOKENS(多个 token 用逗号分隔)。注意是复数GITHUB_TOKENS,缺失时直接抛异常,提示可用GITHUB_TOKENS=$(gh auth token)填充。官方脚本注释也提到:如需并行,在本目录创建.env文件并声明GITHUB_TOKENS=token1,token2,token3...
  3. 调用split_instances把仓库列表按 token 数均匀切分(n个子列表长度差不超过 1),随后用multiprocessing.Pool(len(tokens))并发执行construct_data_files——每个 token 处理一组仓库,实现多 token 并行抓取;
  4. construct_data_files对每个仓库(自动去除逗号与首尾空白,取repo.split("/")[1]作为文件名)执行两个步骤:
    • <repo_name>-prs.jsonl(或带-<cutoff_date>后缀的文件)不存在,则调用print_pulls(repo, path_pr, token, max_pulls=..., cutoff_date=...)抓取 PR;已存在则跳过(便于断点续跑);
    • <repo_name>-task-instances.jsonl不存在,则调用build_dataset(path_pr, path_task, token)转换任务实例;同样支持跳过;
    • 单个仓库出错会打印 traceback 后继续处理下一个仓库,不影响整体流水线。

4.2 底层第一环:print_pulls.py 抓取 PR 元数据

print_pulls.py是流水线抓取层:

python print_pulls.py <repo name> <path to PRs .jsonl file> --token <GitHub Token>

它接受位置参数repo_nameowner/name格式)和output(输出文件路径),可选参数--token--max_pulls--cutoff_date(格式YYYYMMDD)与--pull_number(只抓取指定编号的单个 PR,用于定向补充数据)。

核心行为(swebench/collect/print_pulls.py):

  • 未显式传 token 时回退读取环境变量GITHUB_TOKEN
  • log_all_pulls调用repo.get_all_pulls()逐条遍历仓库 PR,并对每条 PR 调用repo.extract_resolved_issues(pull)解析其解决的 issue 编号,然后以 JSON 行格式(json.dumps(obj2dict(pull)))写入输出文件;
  • 支持max_pulls限制数量、cutoff_date限制最早时间(内部先转为%Y-%m-%dT%H:%M:%SZ格式再与pull.created_at比较,遍历按创建时间降序,一旦命中截止日期即 break)。

extract_resolved_issues的实现值得展开(见 swebench/collect/utils.py):它会拼接 PR 的标题、正文和全部 commit message,剔除 HTML 注释,然后基于正则匹配<keyword> #123<keyword> https://github.com/owner/repo/issues/123形式的引用,keyword属于PR_KEYWORDSclose/closes/closed/fix/fixes/fixed/resolve/resolves/resolved)时记录对应 issue 编号。这意味着"PR 是否解决了 issue"是可以通过文本解析自动判断的。

此外,Repo类(swebench/collect/utils.py)封装了所有 GitHub API 调用,并通过call_apiget_all_loop内置了速率限制(rate limit)处理:遇到 403 或分页中断时,每 5 分钟轮询一次rate_limit接口,待剩余配额恢复后继续,确保长时间抓取不会因限流失败。

4.3 底层第二环:build_dataset.py 转换任务实例

build_dataset.py是流水线的转换层:

python build_dataset.py <path to PRs .jsonl file> <path to output .jsonl file> --token <Github Token>

它逐行读取 PR 文件,按两条过滤规则筛选(swebench/collect/build_dataset.py):

  • is_valid_pull:PR 必须已合并merged_at非空)且解析出至少一个 resolved issue
  • is_valid_instance:构造出的实例必须同时具备非空的patch(gold patch)与非空的problem_statement

每个通过校验的 PR 被转换为一个任务实例,核心字段定义在create_instance中:

{ "repo": "owner/repo", # 实例来源仓库 "pull_number": 123, # 来源 PR 编号 "instance_id": "owner__repo-123", # 唯一 ID(斜杠替换为双下划线) "issue_numbers": ["42"], # 该 PR 解决的 issue 编号 "base_commit": "<SHA>", # PR 基于的 base commit "patch": "<gold patch>", # 参考解法补丁(应用在 base commit 上) "test_patch": "<test patch>", # 测试补丁(应用在 base commit 上) "problem_statement": "...", # 问题陈述(关联 issue 标题+正文) "hints_text": "...", # 提示文本(首提交之前的评论) "created_at": "...", # PR 创建时间 }

关键派生逻辑(均在 swebench/collect/utils.py 中):

  • patch 与 test_patch 的拆分extract_patches,swebench/collect/utils.py):下载 PR 的diff_url得到完整 diff,用unidiff.PatchSet解析后按文件路径是否包含testtestse2etesting等关键词拆分为两部分——含测试文件的 hunk 归入test_patch,其余归入patch(即模型需要生成的 gold patch)。
  • problem_statement 与 hintsextract_problem_statement_and_hints,swebench/collect/utils.py):对每个 resolved issue,通过 API 拉取其标题与正文拼接成问题陈述;hints 则来自该 issue 在 PR 首个 commit 之前发布的评论(_extract_hints,swebench/collect/utils.py),确保只使用"开发者在写代码前已知的信息",避免信息泄漏。
  • Django 特例repo.name == "django"时走extract_problem_statement_and_hints_django(swebench/collect/utils.py),从 Django 自建的 code.djangoproject.com ticket 系统抓取问题描述与时间线评论。

输出策略(main函数):

  • 全部有效实例写入<output>.jsonl.all
  • 其中has_test_patch为真的实例(测试补丁非空)额外写入<output>.jsonl
  • 支持断点续跑:若.all文件已存在,会先扫描其中已有instance_id集合,新运行跳过这些 PR(写模式相应切换为追加a),这在处理上万 PR 的仓库时非常实用。

4.4 断点续跑与并发设计小结

get_tasks_pipeline.py的"先查文件存在性再决定是否执行"设计,加上build_dataset.pyseen_prs去重,使整条流水线天然支持中断后重跑而不产生重复数据;而多 token +multiprocessing.Pool的并发架构则让大规模抓取(如 Top 5000 包中的几十个活跃仓库)可以在速率限制允许的范围内大幅提速。

五、第三步:指定执行参数(版本标记 + 安装配置)

官方教程明确指出,这一步是整个流程中最手工、最容易反复的部分。要为来自新仓库的任务实例创建合适的执行环境,必须做两件事:

Part A:为每个任务实例标记版本(Versioning)

判定每个任务实例对应的仓库版本号(如1.2),官方给出三种可行途径:

  1. 从代码中抓取:PyPI 包通常在__init__.py_version.py中显式声明版本号;
  2. 从网页抓取:有官方网站的仓库(如 xarray)通常有 "Releases" 或 "What's New" 页面,可爬取版本信息;
  3. 从代码构建:某些版本相关文件(如_version.py)会被开发者刻意省略(可用.gitignore验证),此时需要对每个任务实例在本地构建源码,从构建产物中提取版本号。

版本管理工具现已迁移到任务数据仓库的src/versioning目录,不再位于本仓库的harness/constants.py(后者已不再存放这些配置)。

Part B:按版本提供安装配置(Installation Configurations)

每个仓库、每个版本都需要提供独立的安装指令。官方文档给出了配置结构:先在MAP_VERSION_TO_INSTALL中声明<repo owner/name>: MAP_VERSION_TO_INSTALL_<repo name>键值对,再定义一个MAP_VERSION_TO_INSTALL_<repo name>,键为版本字符串,值为安装字段字典:

{ "python": "3.x", # 必填:Python 版本 "packages": "numpy pandas tensorflow", # conda 依赖包列表 "install": "pip install -e .", # 必填:安装命令 "pip_packages": ["pytest"], # pip 安装的额外包(通常为测试依赖) }

这些安装指令通常可以从仓库的配套网站或CONTRIBUTING.md中推断出来。配置按版本组织的含义是:同一仓库的不同历史版本可能有不同的依赖与安装方式,只有为每个base_commit所在的版本配好环境,后续执行验证才能正确还原当时的运行环境。

注意:官方文档提到这类配置过去位于harness/constants.py,现已迁至对应的任务数据仓库(如swe-bench-tasksswe-bench-multilingual-tasksswe-bench-multimodal-tasks)的src/sb_dockerfile_gen/下。

六、第四步:基于执行的验证(Execution-based Validation)

完成版本标记与安装配置后,需要验证两件事:任务实例能否正确安装,以及该任务解决的问题是否非平凡。这一步由验证代码完成,通过运行./harness/run_validation.sh并提供以下参数执行:

参数说明
instances_path已标记版本的候选任务实例路径
log_dir存放每个任务实例执行日志的文件夹
temp_dir执行工作目录
verbose是否将日志打印到标准输出

实践要点:这一步与上一节"安装配置"通常需要来回迭代数次。如果安装指令错误或描述不足,会导致候选任务实例无法正确安装。SWE-bench 的评测与验证 harness 依赖 conda 创建多个虚拟环境来加速评测,因此长期运行后会产生大量以同一前缀命名的 conda 环境——swebench/collect/cleanup/remove_envs.py 就是为此准备的清理工具(见下文第七节)。

七、第五步:转换为最终任务实例

验证通过后,即可判断任务实例能否用于 SWE-bench 评测并保存。官方提供validation.ipynbJupyter notebook 简化收尾步骤,其三个核心环节为:

  • Monitor Validation:检查./run_validation.sh的执行结果;
  • Get [FP]²[FP] Tests(Get FP2FP Tests):判定哪些任务实例是非平凡的(至少能解决一个测试);
  • Create Task Instances.jsonfile:做最终预处理并将任务实例保存为.json文件。

八、指令微调数据集构建(Fine Tuning Dataset Construction)

除了评测实例,swebench/collect还提供了构建指令微调数据集的工具 swebench/collect/build_dataset_ft.py,用于把多个.jsonl.all文件合并为单个可用于构造指令微调数据集(基于「问题陈述 + 原始代码 → 代码 Δ」配对)的.jsonl

# swebench/collect/run_build_dataset_ft.sh python build_dataset_ft.py \ --instances_path "<path to folder containing task instance (raw) files>" \ --output_path "<path to folder to save finetuning dataset to>" \ --eval_path "<path to folder containing all evaluation task instances>"

参数与行为(可对照脚本中 argparse 定义):

参数说明
--instances_path存放所有候选任务实例(*-task-instances.jsonl.all)的目录
--output_path微调数据集输出目录
--eval_path存放所有评测任务实例的目录(用于去重剔除)
--seed随机种子(默认 42)

处理逻辑:

  1. 输出文件命名为SWE_PRS_FT_DATASET_<YYYYMMDDHH>_<seed>.jsonl
  2. 扫描eval_path下所有*-task-instances.jsonl,将评测实例行构成集合,随后遍历instances_path下的所有*-task-instances.jsonl.all剔除出现在评测集合中的行(防止训练/评测数据泄漏),再按seed打乱顺序;
  3. 每个仓库最多保留 500 行,并删除每行的test_patch字段(微调样本不应包含测试答案),最终逐行写入输出文件并打印统计信息(实例总数与仓库数)。

九、配套清理工具

9.1 删除镜像仓库中的 GitHub Workflows

镜像仓库中的周期性 workflow 会不断向 token 关联邮箱发送通知。给定仓库 URL,swebench/collect/cleanup/delete_gh_workflows.py 会自动化地从所有分支删除.github/workflows文件夹:

python delete_gh_workflows.py <repo URL>

其实现为:git ls-remote --heads列出所有远程分支 → 克隆到temp_repo→ 逐分支 checkout 并检查.github/workflows是否存在 → 存在则删除、commit、push → 最后清理临时目录。注意该脚本使用了仓库内rm -rf逻辑来删除临时目录,请按需使用。

9.2 并行删除同前缀 conda 环境

SWE-bench 的评测与验证 harness 会依赖 conda 创建大量虚拟环境以加速基准评测,日积月累可能占用大量磁盘。可使用以下命令并行清理以同一前缀命名的环境:

python remove_envs.py <prefix> --conda_path <path to conda installation>

实现要点(swebench/collect/cleanup/remove_envs.py):先source <conda_path>/etc/profile.d/conda.sh && conda env list枚举环境名,解析出名称以<prefix>开头的环境,用 25 个进程的multiprocessing.Pool并行执行conda remove -n <env> --all -y,最后在 conda 安装目录的envs文件夹下用find -type d -name "<prefix>*" -exec rm -rf清理残留目录。注意两个脚本均属仓库内的清理实现,执行前请确认目标路径。

十、文件与职责速览

下表汇总swebench/collect目录各脚本的职责与用法(依据 swebench/collect/README.md):

阶段脚本用途用法
🧐 仓库选择get_top_pypi.py获取 Top 5000 PyPI 包的 PyPI/GitHub URL、Star 数与 Issue+PR 数python get_top_pypi.py
⛏️ 数据收集print_pulls.py将某仓库全部 PR 的原始信息写入单个.jsonlpython print_pulls.py <repo> <output> --token <TOKEN>
⛏️ 数据收集build_dataset.py将 PR 文件转换为任务实例(有 issue 写.all,有测试再写主文件)python build_dataset.py <prs.jsonl> <output.jsonl> --token <TOKEN>
⛏️ 数据收集get_tasks_pipeline.py自动化多仓库的 PR 抓取 + 实例构建流水线./run_get_tasks_pipeline(参数见脚本)
🎵 微调数据build_dataset_ft.py合并多个.jsonl.all为指令微调数据集./run_build_dataset_ft(参数见脚本)
🪞 镜像仓库make_repo.sh/call_make_repo.py创建既有仓库的镜像副本并清理自动化文件python call_make_repo.py(参数见脚本)
🧹 清理delete_gh_workflows.py删除镜像仓库所有分支的.github/workflowspython delete_gh_workflows.py <repo URL>
🧹 清理remove_envs.py并行删除指定前缀的 conda 环境python remove_envs.py <prefix> --conda_path <path>

十一、完整实操路径回顾

把以上所有环节串起来,从零为一个新仓库构建 SWE-bench 候选任务实例的完整路径是:

  1. 选仓库:用get_top_pypi.py抓取 PyPI 榜单,挑选 issue/PR 活跃的 Python 仓库;
  2. 建镜像./collect/make_repo/make_repo.sh owner/name创建干净镜像(批量可用call_make_repo.py);
  3. 跑流水线:配置run_get_tasks_pipeline.sh--repos / --path_prs / --path_tasks后运行,得到-prs.jsonl-task-instances.jsonl.all-task-instances.jsonl三类文件;大规模场景可设置GITHUB_TOKENS=token1,token2,...启用多 token 并行与断点续跑;
  4. 定版本:按仓库情况从代码、网页或构建产物中为每个实例标记版本;
  5. 配安装:在任务数据仓库的安装配置中按「版本 → 安装字段字典」提供pythonpackagesinstallpip_packages
  6. 执行验证:运行./harness/run_validation.sh并传入instances_path / log_dir / temp_dir / verbose,与第 5 步迭代直至全部实例可安装;
  7. 转成任务:用validation.ipynb监控验证结果、筛选非平凡实例、导出最终.json
  8. (可选)构建微调数据:用run_build_dataset_ft.sh合并.all文件、剔除评测集并抽样生成指令微调数据集;
  9. (日常维护)清理:用delete_gh_workflows.py清理镜像仓库 workflow 通知,用remove_envs.py按前缀并行回收 conda 环境占用的磁盘空间。

掌握这套流程后,你便拥有了从真实 GitHub 仓库出发、端到端生产 SWE-bench 风格评测与微调数据的能力;如需大规模生成带执行环境与任务实例的训练数据,官方建议评估 SWE-smith 工具包。仓库相关参考文档还包括完整的端到端教程 docs/assets/collection.md 与 API 文档 docs/reference/cli.md。

【免费下载链接】SWE-benchSWE-bench: Can Language Models Resolve Real-world Github Issues?项目地址: https://gitcode.com/GitHub_Trending/sw/SWE-bench

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询