[v2] 挖掘 GitHub Issues 中的论文复现踩坑记录:一类被忽视的高质量训练数据
提出一种从 GitHub Issues/Discussions 系统化采集论文复现诊断对话的方法,论证其作为训练数据的独特价值,并给出完整的采集、筛选与应用技术方案。
挖掘 GitHub Issues 中的论文复现踩坑记录:一类被忽视的高质量训练数据
动机:合成数据的天花板
当前主流的代码推理训练数据生成路径是「合成」——用强模型写代码、自我验证、蒸馏。这条路有明显上限:模型生成的复现轨迹,本质上是它已经知道答案之后的反向还原,缺乏真实的试错张力。更关键的是,真实的论文复现失败往往不是代码 bug,而是细节理解偏差:tokenization 策略、数据集分割方式、评估协议的微妙差异——这些坑,模型几乎不会主动”合成”出来,因为它不知道自己不知道。
GitHub 上沉淀了十几年的论文复现讨论,是一座天然的专家诊断知识库。一个典型案例是:某用户在 fairseq 的 Issue 里描述”我按 BLEU 论文跑出 28.4,但论文报 32.7”,随后另一用户回复”你是不是用了 sacrebleu 默认的 tokenizer,原论文用的是 Moses tokenizer”,问题得到闭合。这条三轮对话,浓缩了:问题现象的精确描述、假设生成、根因定位、验证方法——完整的专家推理链,且完全是真实发生的。
这类数据有一个独特属性:它记录的是人类专家在不确定性下的诊断过程,而非已知答案的展示。这正是当前 LLM 在科研代码任务上最缺乏的能力。
数据分布:踩坑的类型学
基于对 Papers with Code 高引论文(BERT、ResNet、PPO、DeiT 等)对应代码仓库的初步调研,复现踩坑可归纳为以下几类:
| 错误类型 | 典型描述 | 占比估计 |
|---|---|---|
| 超参数差异 | 学习率 warmup 步数、batch size 缩放规则 | ~30% |
| 数据集版本/预处理 | 数据集年份版本、tokenization 方式、归一化参数 | ~25% |
| 评估协议差异 | beam size、后处理步骤、指标实现版本 | ~20% |
| 框架/依赖版本 | PyTorch 版本行为差异、CUDA 版本对结果的影响 | ~15% |
| 随机种子与硬件差异 | 多卡训练不确定性、FP16 精度差异 | ~10% |
这种分布意味着,这类数据覆盖了「超参数敏感性」「实验可重复性」「框架迁移」等科研代码任务的核心难点。一个能在这些类型上展示正确诊断推理的模型,在科研代码 Agent 场景中会有实质性优势。
系统化采集方案
第一步:确定目标仓库集合
以 Papers with Code(pwc)作为论文-代码仓库的索引入口。PWC 的 API 提供了论文与 GitHub 仓库的对应关系:
import requests
def get_pwc_repos(page=0, items_per_page=50):
url = f"https://paperswithcode.com/api/v1/repositories/"
resp = requests.get(url, params={"page": page, "items_per_page": items_per_page})
return resp.json()["results"]
目标仓库优先级:PWC 上 star 数 > 200、被引次数 > 50 的论文对应仓库,预计覆盖约 2 万个高质量仓库。
第二步:GitHub API 批量拉取 Issues/Discussions
from github import Github
import time
def fetch_issues_for_repo(repo_full_name: str, g: Github):
repo = g.get_repo(repo_full_name)
issues = repo.get_issues(state="all", labels=["reproduction", "results"])
# 同时拉取无 label 的,依赖后续关键词筛选
all_issues = repo.get_issues(state="all")
return [
{
"title": i.title,
"body": i.body,
"comments": [c.body for c in i.get_comments()],
"state": i.state,
"created_at": str(i.created_at),
"closed_at": str(i.closed_at),
"reactions": i.reactions.total_count,
}
for i in all_issues
if is_reproduction_issue(i)
]
def is_reproduction_issue(issue) -> bool:
keywords = [
"reproduce", "replication", "results don't match",
"reported in paper", "paper reports", "cannot reproduce",
"got X but paper says", "复现", "指标对不上"
]
text = (issue.title + " " + (issue.body or "")).lower()
return any(k in text for k in keywords)
GitHub API 有速率限制(5000 req/hour for authenticated),采集 2 万仓库约需 40–80 小时,建议分布式跑多个 token 轮换。Discussions API 需要 GraphQL 接口单独处理。
第三步:结构化提取对话链
一条高质量的训练样本应具备完整的推理链结构:
{
"repo": "facebookresearch/fairseq",
"paper": "Attention Is All You Need",
"issue_id": 1423,
"problem_statement": "我的 BLEU 是 28.4,论文报 32.7",
"hypothesis_chain": [
"可能是 beam size 不同",
"可能是 tokenizer 不同"
],
"root_cause": "使用了 sacrebleu 默认 tokenizer 而非 Moses tokenizer",
"resolution": "切换到 --sacrebleu --tokenizer moses 参数",
"has_code_snippet": true,
"is_resolved": true,
"error_type": "evaluation_protocol"
}
结构化提取可以用 LLM 辅助完成(对已有的 raw issue 做 structured extraction),但原始对话本身作为训练数据的价值不依赖提取质量。
🔄 [v2 改进] 时效性过滤机制
采集方案不能忽视数据的时效性问题。论文复现踩坑高度依赖具体框架版本,2018 年的 PyTorch 0.4 踩坑记录对今天的模型几乎没有指导价值,却会引入误导性知识。
优先策略:优先采集 2022 年后的 Issues(对应 PyTorch 1.12+ 时代),这批数据覆盖了当前主流的开发栈,技术上仍然适用。
旧 Issues 的处理策略: 对 2020 年前创建的 Issues,增加「版本标注」元数据字段:
{ "temporal_tag": { "created_year": 2019, "framework_version": "pytorch-1.1", "still_relevant": false, "historical_value": "medium" } }训练时可通过此字段选择性过滤,而不是直接丢弃——部分旧 Issues 描述的是算法本身的问题(如某篇论文的评估指标定义歧义),这类内容与框架版本无关,仍然有价值。
技术时效性分级标准:
等级 定义 训练策略 当前仍适用 2022+ 创建,或错误类型与框架版本无关 直接纳入 已过时但有历史价值 2020-2022,框架相关但诊断思路可迁移 加标注后纳入,训练时降权 已过时应过滤 2020 前,框架强依赖,信息无法迁移 过滤,不用于训练
数据来源
来源一:GitHub Issues(已解决)
最高价值的来源。已关闭 + 有明确解决方案的 Issue,提供了完整的「问题 → 诊断 → 解决」三段式推理链。这是占比最大的训练数据来源(目标约 70%)。
来源二:GitHub Discussions
部分仓库(如 HuggingFace、PyTorch Lightning)已将技术讨论迁移到 Discussions。Discussions 的线程结构与 Issues 类似,但往往更长、更开放式,包含更多的假设讨论过程。需要通过 GraphQL API 单独采集:
query {
repository(owner: "huggingface", name: "transformers") {
discussions(first: 100, categoryId: "...") {
nodes {
title, body, createdAt,
comments(first: 50) { nodes { body, author { login } } }
}
}
}
}
🔄 [v2 改进] 幸存者偏差:未解决 Issue 的价值
原方案隐含了一个假设:只有「已解决」的 Issue 才有训练价值。这是典型的幸存者偏差。
事实上,未解决但有诊断过程的 Issue 代表了一类独特的知识:困难问题的边界在哪里。一个 Issue 被专家反复讨论但未能解决,本身就传达了重要信息:这类问题超出了当时技术栈的诊断能力,需要更深层次的工具或知识。
这类数据应标注为「诊断过程数据」,而非「答案数据」:
- 训练目标:不是「解决问题」,而是「识别困难问题」和「知道何时求助」
- 典型场景:给定一个复杂的性能差距问题(如差距 > 5 个百分点),模型能够诊断出这超出了标准调参范围,需要联系原论文作者或查看内部实现
- 标注字段:在结构化数据中增加
"resolution_type": "unresolved_valuable"和"diagnostic_depth": "high"字段建议数据构成比例:
- 已解决 Issues(完整推理链数据):70%
- 有价值的未解决 Issues(诊断过程数据):30%
这个 30% 会让模型学会一种重要的元认知:知道自己不知道,这比给出一个错误答案更有价值。
质量筛选策略
筛选的核心原则是优先完整推理链,具体评分维度:
- 已关闭 + 有明确解决方案(+3分):closed issue 且有 “resolved by” / “fixed in” 等标记
- 有代码片段(+2分):包含
```代码块,说明诊断过程有可验证性 - 多轮对话(+1分):评论数 ≥ 3,说明有来回的假设-验证过程
- 高互动(+1分):reactions ≥ 5 或被引用,说明问题有普遍性
- 量化的性能差距(+1分):包含具体数值(“28.4 vs 32.7”),精确度更高
过滤掉:纯 feature request、环境配置问题(CUDA 安装等)、无任何回复的 issue。
目标是保留「问题描述清晰 + 诊断过程可见 + 解决方案明确」的三角完整案例。
规模估算
- Papers with Code 收录论文:~12 万篇(截至 2025 年),其中约 4 万篇有关联代码仓库
- 有 Issues 功能的活跃仓库:约 2 万个
- 每个仓库平均 Issues 数:~150 条(含 closed)
- 与复现相关的 Issue 比例:约 8–12%(基于对 50 个高引仓库的人工抽样)
- 通过质量筛选(分数 ≥ 4)的比例:约 30%
粗略估算:
20,000 repos × 150 issues × 10% relevance × 30% quality = ~90,000 条
加上 GitHub Discussions(部分仓库迁移到 Discussions),总量估计在 8 万–15 万条高质量复现诊断对话。这是一个可观的规模,足以支撑专项微调或作为 RLHF 的偏好数据对。
🔄 [v2 改进] 规模估算修正:真实筛选漏斗
上面的估算存在一个关键错误:将「有 Issues 的活跃仓库」设定为 2 万个,但实际上采集目标是 star > 200 的 Papers with Code 仓库,这个池子要小得多。
真实筛选漏斗:
Papers with Code star > 200 的仓库 ≈ 3,000–5,000 个 × 每仓库平均 Issues 数 × 150 条 × 复现关键词命中率 × 8–12%(取中值 10%) × 质量筛选通过率(已关闭+代码+多轮+量化)× 15–25%(取中值 20%) ──────────────────────────────────────────────────────── 结果:3,000 × 150 × 10% × 20% ≈ 9,000 条9,000 条,而非 8–15 万条。 这是一个数量级的差异,原估算严重高估了规模。
9,000 条是否足够?
对于专项微调(SFT),9,000 条高质量的领域数据是有意义的——参考 Alpaca(52K)、Code Alpaca(20K),领域专项数据往往不需要太大规模就能产生显著效果。但如果目标是支撑 RLHF 偏好对,9,000 条原始样本可能只能构造出约 2,000–3,000 个高质量偏好对,规模偏小。
扩展规模的三条路径:
- 加入 GitHub Discussions:部分高 star 仓库的技术讨论已迁移到 Discussions,预计可增量 +3,000–5,000 条
- 扩展到 star > 100 的仓库:仓库数量约翻 3 倍(~10,000 个),但质量会下降,需要更严格的筛选
- 加入版本标注后使用旧 Issues:对 2020 年前的 Issues 加版本标注,筛选出与框架版本无关的算法类讨论,预计可再增 +2,000–4,000 条
综合三条路径,最终可用规模约 15,000–20,000 条,这是更诚实的上限估计。
与论文代码复现 Benchmark 的关系
这类数据与「科研版 SWE-bench」构成互补关系:
- SWE-bench 提供的是任务(给定一个失败的测试,修复代码)
- 复现踩坑数据提供的是参考轨迹(一个真实专家是如何思考和诊断的)
具体应用路径:
- 作为 L1 任务(环境配置/依赖对齐)的诊断示例:框架版本类 issue 直接映射到「给定错误日志,定位版本冲突」任务
- 作为 L2 任务(性能复现)的推理链监督:超参数/评估协议类 issue 提供了「gap 分析 → 假设 → 验证」的完整范式
- 作为偏好对:同一问题的「正确诊断」vs「错误诊断」可以构造 DPO 训练对,教模型区分有效推理和无效猜测
下一步行动
- 小规模验证:选取 PWC NLP 榜单前 100 论文的代码仓库,手工标注 500 条 issue,验证规模估算和分类准确率
- 采集流水线:实现 GitHub API + GraphQL Discussions 的并行采集脚本,目标 2 周内完成 top-2000 仓库的全量采集
- 结构化提取:用 GPT-4o / Claude 对 raw issue 做 structured extraction,验证提取质量(与人工标注对比 F1)
- 数据集发布:整理为 HuggingFace Dataset,与科研版 SWE-bench 配套发布,推动社区验证
这类数据的价值在于它的不可合成性:它记录的是人类专家在真实不确定性中的推理,而不是事后的知识展示。用它训练的模型,将在科研代码任务上具备更接近真实专家的诊断直觉。
评估闭环
🔄 [v2 改进] 评估闭环:如何验证这批数据真的有效
一个研究提案如果没有可验证的评估方案,就只是一个信念陈述。以下是验证这批数据有效性的具体方案。
评估平台:TerminalBench 科研诊断子任务
TerminalBench 是面向 Agent 的终端操作 Benchmark,其中包含科研代码诊断子任务。用这批数据微调后的模型,在 TerminalBench 的科研诊断子任务上进行评估,是最直接的验证路径。
构造「复现诊断评测集」
为了更细粒度地验证,建议同步构造一个专用评测集:
输入格式:
环境:PyTorch 2.0, CUDA 11.8, A100 论文:DeiT(2021) 错误现象:Top-1 准确率 79.8%,论文报 81.8% 已尝试:默认超参数,ImageNet 标准预处理 问题:请给出可能的诊断方向(不需要给出解决方案)评估维度:
- 方向命中率:模型给出的诊断方向是否包含真实根因
- 假阳性率:模型给出了多少无关或误导性的方向
- 推理链质量:诊断方向是否有明确的推理依据(有理由 vs 无理由的猜测)
评测集规模:100–200 条,覆盖五种错误类型各 20–40 条。
基线对比设计
实验组 训练数据 预期效果 Baseline 无此类数据 方向命中率 ~40% +GH Issues (resolved) 9,000 条已解决 Issues 预期提升至 55–60% +GH Issues (full) 9,000 已解决 + 3,000 未解决 预期提升至 60–65%(更好的「识别困难」能力) 核心假设:未解决 Issue 的加入会在「难题识别」维度上带来额外增益,而不影响「常规诊断」维度的表现。如果这个假设成立,则证明「诊断过程数据」的独立价值。