研究提案

[v2] 挖掘 GitHub Issues 中的论文复现踩坑记录:一类被忽视的高质量训练数据

提出一种从 GitHub Issues/Discussions 系统化采集论文复现诊断对话的方法,论证其作为训练数据的独特价值,并给出完整的采集、筛选与应用技术方案。

训练数据 论文复现 GitHub Mining SWE-bench 数据工程

挖掘 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% 会让模型学会一种重要的元认知:知道自己不知道,这比给出一个错误答案更有价值。


质量筛选策略

筛选的核心原则是优先完整推理链,具体评分维度:

  1. 已关闭 + 有明确解决方案(+3分):closed issue 且有 “resolved by” / “fixed in” 等标记
  2. 有代码片段(+2分):包含 ``` 代码块,说明诊断过程有可验证性
  3. 多轮对话(+1分):评论数 ≥ 3,说明有来回的假设-验证过程
  4. 高互动(+1分):reactions ≥ 5 或被引用,说明问题有普遍性
  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 个高质量偏好对,规模偏小。

扩展规模的三条路径:

  1. 加入 GitHub Discussions:部分高 star 仓库的技术讨论已迁移到 Discussions,预计可增量 +3,000–5,000 条
  2. 扩展到 star > 100 的仓库:仓库数量约翻 3 倍(~10,000 个),但质量会下降,需要更严格的筛选
  3. 加入版本标注后使用旧 Issues:对 2020 年前的 Issues 加版本标注,筛选出与框架版本无关的算法类讨论,预计可再增 +2,000–4,000 条

综合三条路径,最终可用规模约 15,000–20,000 条,这是更诚实的上限估计。


与论文代码复现 Benchmark 的关系

这类数据与「科研版 SWE-bench」构成互补关系:

  • SWE-bench 提供的是任务(给定一个失败的测试,修复代码)
  • 复现踩坑数据提供的是参考轨迹(一个真实专家是如何思考和诊断的)

具体应用路径:

  1. 作为 L1 任务(环境配置/依赖对齐)的诊断示例:框架版本类 issue 直接映射到「给定错误日志,定位版本冲突」任务
  2. 作为 L2 任务(性能复现)的推理链监督:超参数/评估协议类 issue 提供了「gap 分析 → 假设 → 验证」的完整范式
  3. 作为偏好对:同一问题的「正确诊断」vs「错误诊断」可以构造 DPO 训练对,教模型区分有效推理和无效猜测

下一步行动

  1. 小规模验证:选取 PWC NLP 榜单前 100 论文的代码仓库,手工标注 500 条 issue,验证规模估算和分类准确率
  2. 采集流水线:实现 GitHub API + GraphQL Discussions 的并行采集脚本,目标 2 周内完成 top-2000 仓库的全量采集
  3. 结构化提取:用 GPT-4o / Claude 对 raw issue 做 structured extraction,验证提取质量(与人工标注对比 F1)
  4. 数据集发布:整理为 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 的加入会在「难题识别」维度上带来额外增益,而不影响「常规诊断」维度的表现。如果这个假设成立,则证明「诊断过程数据」的独立价值。


原始版本:github-reproduction-issues-as-training-data