用数据编程:面向自改进大语言模型的测试驱动数据工程 Programming with Data: Test-Driven Data Engineering for Self-Improving LLMs from Raw Corpora
把软件工程里的测试驱动思想搬到大模型领域微调上,让数据缺陷像代码 bug 一样可定位、可修复
前置知识
测试驱动开发 (Test-Driven Development, TDD)
一种软件工程方法论,核心是先用测试用例定义系统应该满足的需求规约,然后才编写实现代码。规约、代码、测试三者共享同一份结构化描述,使得测试失败时可以沿着共享规约追溯到具体代码缺陷,并通过最小化补丁修复。
本文的核心思想是把 TDD 的结构对应关系平移到 LLM 数据工程:如果训练数据和评测也由同一份知识结构派生,那么评测失败就能像单元测试失败一样回溯到训练数据里的具体缺陷。
知识图谱三元组 (Knowledge Triple)
形如 (subject, relation, object) 的有类型关系表达,例如 (钠通道失活, 导致, 动作电位不能重启)。三元组强调关系语义而不仅是共现, 可以编码 SPECIALIZATION、CAUSAL、PREREQUISITE、CONTRAST 等多种关系类型。
本文的 L2 层正是 L1 概念之间的有类型三元组, 是把 L1 概念串成 L3 推理链的最小结构单元, 也是构建可定位、可修补的训练数据的语义骨架。
推理链 (Reasoning Chain)
由多个推理步骤组成的序列, 每步调用若干原子概念, 通过关系类型连接, 形成从前提到结论的完整推导路径。多步推理链比单一事实更能考察模型组合知识的能力。
L3 推理链是评测基准的来源, 也是诊断的核心对象: 失败可以被分解为'缺哪个 L1 概念'或'缺哪个 L2 关系', 两种缺陷对应不同的修复策略。
LoRA 微调 (Low-Rank Adaptation)
在原始模型权重上注入低秩分解的可训练矩阵, 只更新少量参数即可适配下游任务。优点是显存开销小、可与不同基座组合, 缺点是表征能力受限于低秩瓶颈。
本文所有实验都用 LoRA 在 3B-32B 规模上微调, 不同规模使用不同的 rank 和学习率, 是理解实验规模与增益关系的基础。
灾难性遗忘 (Catastrophic Forgetting)
神经网络在下游任务微调时丧失先前学到的能力的现象。领域微调常常以损害通用能力为代价, 因此评测必须同时考察目标域和通用基准。
本文在 MMLU 和 C-Eval 上专门检验 V2 是否恢复 V1 微调带来的通用能力损失, 这是判断数据调试是否真的'修复而非替换'的关键证据。
研究动机
当前的领域微调普遍是开环流程: 先收集领域语料, 用 Self-Instruct、Alpaca 这类方法合成指令数据, 微调模型, 在通用基准或临时构建的基准上评测。当模型答错时, 工程师只能凭直觉'再加数据', 既不能定位是哪个知识点没学好, 也不能保证修补有效。这套从预训练沿袭下来的工作流在领域微调里并不合适: 领域语料往往是稀缺、不可再生的, 知识高度结构化而非统计分布, 每一个错误都隐含可定位的诊断信息。作者统计了 Alpaca、EasyDataset、DataFlow 这类基线, 即使在 5K-10K 数据规模下, 7B 模型在自家基准上的平均准确率也长期停滞在 56-68% 区间, 说明单纯加数据的边际收益已经坍缩。
本文的目标是本文提出要构建一个闭环的数据工程范式: 让训练数据和评测基准共享同一份结构化知识表示, 使得基准上的每一个失败都能像软件测试失败一样被精确归因到知识图谱中的某个或某些节点, 并通过定向补丁数据在下一轮训练中修复。终极目标是让 32B 开源模型在 16 个学科的领域评测上稳定超过 GPT-5.4、Gemini-3-flash、DeepSeek-v3.2 等闭源前沿模型, 同时不损失 MMLU、C-Eval 上的通用能力。
与已有工作不同的是,已有工作要么只关注数据合成质量 (Phi 系列、Alpaca、Self-Instruct), 要么关注评测本身的难度 (MMLU、GPQA), 要么关注自博弈/STaR 这类推理时自迭代, 但没人把'知识结构作为训练和评测的共享规约'这一点作为核心机制。本文的关键洞察是把软件工程里'规约—实现—编译—测试'的四元对应搬到大模型, 而规约角色由从语料里抽取的三层知识结构 (L1 概念 + L2 三元组 + L3 推理链) 扮演, 这是闭环得以成立的结构性前提。
核心方法
直觉上, 本文把训练 LLM 类比为编译软件: 原始语料相当于需求规约, 合成训练数据相当于源代码, 微调过程相当于编译器, 模型权重相当于二进制, 评测基准相当于单元测试。要让单元测试真正能驱动代码修复, 测试和代码必须由同一份规约派生。本文正是按这个对应关系设计: 先用一个三阶段流水线 (Builder, Tester, Debugger) 从原始语料中抽取共享的三层知识结构, 再用它同时合成训练数据和评测基准, 最后让基准失败回溯到知识节点并触发针对性补丁。
本文最核心的创新是把'共享知识结构'作为训练和评测之间的索引结构, 让评测失败具备可分解性。一个 L3 推理链上的失败要么是链上某个 L1 概念没学过 (concept_gap), 要么是概念都有但拼不出正确的推理顺序 (capability_deficit), 两种缺陷对应不同的修复策略: 前者用对比样本强化概念边界, 后者用显式中间步骤的思维链样本补足推理路径。这与之前所有'加更多数据'或'加更多 RLHF'的做法形成本质区别: 数据调试不是数据增广, 而是基于知识图谱定位的精准打补丁。同时, 训练数据和基准数据来源被结构性隔离 (训练来自 L1/L2, 基准来自 L3), 既保留了知识级连接 (保证可追溯), 又保证了实例级正交 (保证评测考的是泛化而非记忆)。
方法步骤详情
第一步是 Builder 阶段的知识抽取与训练数据合成。原文从 117,000 篇教材级文档出发, 经文档级四维分类 (学科、学术层级、推理类型、保留判定) 过滤到 48,000 高质量块, 再用六维质量矩阵 (推理深度、前置密度、场景适用性、反直觉指数、知识综合、断点平滑度, 各 1-5 分) 做块级筛选得到约 15 亿 token 的精炼语料。接下来是 top-down 三层抽取: 先用 LLM 从每个块抽取一条 L3 推理链 (包含步骤、前提、负向约束), 再用滑动窗口把相邻步骤分解成 L2 三元组 (其中指代必须被解析回前序步骤), 最后从 L2 的主客体中 harvest L1 概念并做跨块归一化与去重。重要的是抽取顺序是 top-down 而非 bottom-up, 保证每个 L1/L2 都能被某条 L3 链 reachability 覆盖, 即孤儿节点率为 0。Builder 同时基于 L1/L2 用 6:3:1 的开放题:多选:判断题比例合成 160K SFT 样本, 每个样本带 L2/L1 元数据实现完全可追溯。第二步是 Tester 阶段构建 ProDa-16 评测基准: 每条 L3 链都被改写成多选题 (主要是多选题), 并使用三种对抗性干扰算子生成干扰项: SUBSTADJ 用语义相邻 L1 概念替换链上节点, INVREL 反转关系类型 (例如'促进'变'抑制'), TRUNC 在中间步截断推理。第三步是 Debugger 阶段的失败归因与定向修补: 模型在 ProDa-16 上的每个错误被 LLM judge 分类为 concept_gap 或 capability_deficit, 对前者调用概念强化函数 $f_{\text{refine}}(\kappa_k, \mathcal{N}(\kappa_k), K)$ 生成与相邻概念对比的强化样本, 对后者调用思维链脚手架函数 $f_{\text{CoT}}(g_k, K)$ 生成显式中间步骤的样本, 两者各生成 20 条, 再按错误占比动态分配 160K 总预算, 剩余配额用 L2 ID 不相交的 Round 1 正确样本做经验回放以避免遗忘。
技术新颖性
和现有数据合成范式相比 (表 3 总结), Alpaca 和 EasyDataset 完全没有知识规约, DataFlow 有规约但无追溯, ProDa V1 加上了追溯但仍是单向编译, 只有 ProDa V2 形成完整闭环。技术上, 本文的 top-down 抽取 (而非传统 bottom-up NER) 是保证零孤儿节点的关键工程决策, 而三层结构 + 实例级正交 + L2-disjoint 回放是保证补丁精准且不破坏既有能力的组合设计。理念上, 把测试驱动开发作为类比框架而非比喻, 真正落地为可执行的 Builder-Tester-Debugger 三组件流水线, 是把软件工程 discipline 移植到 LLM 训练的少数系统化尝试之一。
实验结果
实验覆盖 9 个模型 (Llama-3.1-8B、Qwen-2.5 3B/7B/14B/32B、Qwen-3 4B/8B/14B/32B) 在 16 个学科的 ProDa-16 基准, 共三种评测状态: Base (原模型)、V1 (Round 2 首轮微调)、V2 (Round 3 调试修补)。在结构验证上, ProDa-16 与 11 个权威基准的平均 Spearman 相关系数达 $\rho = 0.847$, 与 GPQA 相关性最强 ($\rho = 0.943$), 与 MMLU-Pro 次之 ($\rho = 0.905$), 表明它是可靠的外部可对齐评测; 16 个学科的中位准确率都明显高于 25% 四选一随机基线, 且任何学科最高中位都低于 82%, 既无地板效应也无天花板效应。在首轮 V1 上, 仅靠 160K 自动合成数据训练的 Qwen-2.5-7B 就比官方 Instruct 高 +3.55 (65.86 vs 62.31), Qwen-3-4B 甚至比 Instruct 高 +11.17 (65.79 vs 54.62), Qwen-3-14B 超过了更大的 Qwen-3-30B-A3B-Instruct (+2.31), Qwen-3-32B 达到 77.35% 已超过除闭源外的所有 Instruct 模型。但 Llama-3.1-8B 在 V1 只拿到 30.35%, 主要因为不熟悉评测格式。在 V2 调试修补阶段, 全部 9 个模型在所有 16 个学科上几乎都取得正向增益 (Qwen-3-14B 在 Astronomy 上掉 -7.0 是极少数异常), 平均增益从 Llama-3.1-8B 的 +32.67 到 Qwen-3-32B 的 +2.17, 增益幅度与 V1 起点呈反比, 起点越弱补得越多。修补后 Qwen-2.5-32B-V2 达到 78.84%, Qwen-3-32B-V2 达到 79.52%, 都超过表 1 Panel A 中所有 Instruct 模型 (GPT-5.4 76.82、Gemini-3-flash 76.60、DeepSeek-v3.2 76.69、Claude Opus 4.6 71.99、Kimi K2.5 68.97)。Llama-3.1-8B-V2 从 30.35 飙到 63.02, 首次反超自家 Instruct (60.65)。通用能力上 (表 2), V1 在 MMLU 上中位下降 -0.48, C-Eval 上 -0.41, 但 V2 修补后 9 个模型中 7 个回到甚至超过 Base 水平, 中位变化为 +0.27 (MMLU)。在与 Alpaca、EasyDataset、DataFlow 的横向对比中 (图 5), ProDa V2 在 1K 样本规模就达到 68.72%, 已经超过 Alpaca 在 2K 规模的峰值 68.12%; 5K 规模上 ProDa V2 拿到 72.11%, 比 DataFlow Filter 的 56.18% 高出近 16 个绝对点, 说明高质量定向补丁远胜盲扩数据。
查看结构化数据
| 任务 | 指标 | 本文 | 基线 | 提升 |
|---|---|---|---|---|
| ProDa-16 16学科平均 (闭源前沿参考) | Accuracy (%) | Qwen-3-32B-V2: 79.52; Qwen-2.5-32B-V2: 78.84 | GPT-5.4: 76.82; Gemini-3-flash: 76.60; DeepSeek-v3.2: 76.69 | +2.70 到 +2.83 绝对点, 首次让 32B 开源模型在多学科上超过闭源前沿 |
| ProDa-16 16学科平均 (同源模型对比) | Accuracy (%) | Qwen-2.5-7B-V2: 70.79; Qwen-3-14B-V2: 77.21; Llama-3.1-8B-V2: 63.02 | Qwen-2.5-7B-Instruct: 62.31; Qwen-3-30B-A3B-Instruct: 74.13; Llama-3.1-8B-Instruct: 60.65 | +8.48 / +3.08 / +2.37, 证明数据调试可系统替代昂贵 RLHF |
| MMLU (12 子集) 通用能力保留 | Accuracy (%) | Qwen-2.5-32B-V2: 83.18; Qwen-3-32B-V2: 82.39 | Qwen-2.5-32B-Base: 82.50; Qwen-3-32B-Base: 82.29 | +0.68 / +0.10, V2 不仅没灾难遗忘还略升 |
| C-Eval (6 子集) 通用能力保留 | Accuracy (%) | Qwen-2.5-32B-V2: 92.28; Qwen-3-32B-V2: 87.93 | Qwen-2.5-32B-Base: 92.21; Qwen-3-32B-Base: 87.66 | +0.07 / +0.27, 几乎完美保留 |
| 样本效率 (1K 规模) | Accuracy (%) | ProDa V2 (1K): 68.72 | Alpaca (2K 峰值): 68.12 | 在数据少一半的情况下追平甚至超过 Alpaca 最优 |
| 样本效率 (5K 规模) | Accuracy (%) | ProDa V2 (5K): 72.11 | DataFlow Filter (5K): 56.18 | +15.93 绝对点, 体现定向补丁对盲目扩数据的碾压 |
| ProDa-16 与 11 个公开基准对齐 | Spearman $\rho$ | ProDa-16 平均 $\rho = 0.847$ | 最强 GPQA: 0.943; 最弱 IFEval: 0.800 | 证明 ProDa-16 与 GPQA/MMLU-Pro 等推理基准强对齐 |
局限与改进
作者明确指出几个局限: (1) 首轮 V1 的天花板问题, 即静态数据合成无法动态弥补模型特有的概念盲区, 因此 V1 在某些模型上 (如 Qwen-2.5-32B 的 Mathematics 仅 73.80) 仍弱于官方 Instruct; (2) Llama-3.1-8B 在 V1 阶段只能拿 30.35%, 因为 base 模型不会按要求输出选项字母, 调试补丁需要先修复'格式遵循'这种能力断层; (3) 即便在 V2 阶段, Qwen-3-14B 在 Astronomy 上掉 -7.0、Qwen-3-32B 在 Astronomy 上掉 -5.0, 提示诊断分类对极端小众学科仍有失效情况; (4) 修复策略目前只区分 concept_gap 和 capability_deficit 两类, 缺乏对更细粒度错误 (如检索错误、事实更新延迟) 的处理; (5) 在 1K-10K 横向对比里, ProDa V2 的 1K 数据是经过调试筛选的 1K, 不是 1K 随机, 严格意义上不是纯样本效率比较。我自己的观察: ProDa 对 LLM judge 的诊断质量依赖很强, 如果分类错误 (例如把推理缺陷误判为概念缺失), 补丁方向就跑偏; 此外, 0 孤儿节点并不等于 0 错误, 知识抽取的语义质量决定了诊断的可用性, 而这部分靠 LLM 抽取存在幻觉风险。
独立分析的弱点
(1) 对抽取器质量的强依赖: 三层知识结构是整个系统的脊柱, 而 L3 抽取目前是单条链输出, prompt 提示每个块只能选最重要的推理链, 这会丢失很多次级推理模式, 对跨段落推理尤其不利。改进方向: 允许多链抽取并按重要度排序, 或用结构化多跳 QA 数据集自动验证 L3 链质量。(2) 对闭卷 + LLM judge 的过度依赖: 诊断分类的准确性上限受限于 judge 模型能力, 当 judge 自己也无法识别错误模式时, 整个闭环失效。改进方向: 引入基于 mechanistic interpretability 的细粒度诊断 (例如注意力归因、电路级分析) 作为补充信号, 或者训练一个专门的诊断模型而非用通用 LLM。(3) 修补函数的条件设计粗糙: concept_gap 用对比样本、capability_deficit 用思维链脚手架, 但实际情况经常是混合缺陷 (既有概念模糊又有多步断裂), 当前补丁只针对单一类别。改进方向: 允许补丁生成器在同一节点上同时叠加多种修复策略, 或者根据诊断置信度做加权混合。(4) 数据总量天花板: 160K 的训练总量对 32B 模型偏小, Llama-3.1-8B 之所以能从 30 涨到 63, 一部分是因为 baseline 太弱而非方法多强。改进方向: 引入 RAG 让模型在评测时按需检索知识图谱, 或在 V3/V4 阶段做多轮调试迭代而不是只做一轮。(5) ProDa-16 的多选主导格式限制了开放式推理考察, 思维链被截断到 15 token, 模型基本不能展示过程, 这削弱了'评测 = unit test'的类比力度。改进方向: 引入开放式长答题 + LLM judge 的混合评测, 把推理过程纳入考核。
未来方向
作者在 Discussion 中明确点名了几个方向: 与 RAG 结合让合成数据始终 grounding 在权威源, 与 mechanistic interpretability 结合做更细粒度诊断, 让每个模块 (Builder/Tester/Debugger) 都可以被独立替换和升级。基于本文成果, 我能想到的延伸包括: (a) 把 ProDa 范式用到 RLHF/RLVR 中, 让偏好数据也来自同一份知识结构, 从而把对齐与领域适配合二为一; (b) 多模态知识结构, 把 L1/L2/L3 扩展到图像、表格、公式, 让领域微调跨模态; (c) 跨语种知识共享, 用英语教材抽取 L3 链后再合成中文训练数据, 缓解非英语领域的高质量语料稀缺问题; (d) 把诊断循环做成在线学习, 模型部署后持续收集失败案例并自动触发新一轮补丁, 实现真正的 self-evolving。
复现评估
本文开源程度相当高: ProDaLib (227K L1 概念 + 187K L2 三元组 + 44K L3 推理链 + 16K 评测题 + 160K SFT 样本) 已发布在 HuggingFace (OpenRaiser/ProDalib), ProDa Studio IDE 的源码已发布在 GitHub (OpenRaiser/ProDa), 所有 prompt 模板 (知识抽取、训练合成、诊断、补丁生成) 都在论文附录 B/C/D 中完整给出 (图 8、12-26)。训练配置公开: 使用 LLaMA-Factory 框架 + LoRA, bf16 混合精度, 6 个超参表 (Table 14) 给出不同规模下的 rank/alpha/lr。评测使用 OpenCompass + 贪婪解码 + 15 token 上限, 严格 EM 评分。算力方面, 单个模型一轮微调的时间没有明确披露, 但 LoRA + bf16 + 1024 batch + 1 epoch + 160K 样本在 8 张 A100/H100 上一般可以在数小时到一天内完成, 对大多数学术实验室都可负担。复现难度中等偏低: 主要门槛在 L3 链抽取对 GPT-4 级 LLM 的依赖 (普通实验室需要调用 API), 以及 Judge 模型自身的能力 (若用 Qwen-2.5-7B 做 judge, 自身 V1 才 65%, 诊断质量可能受限)。
论文图表
左侧是软件工程: 用户写代码、编译器、单元测试、调试; 右侧是 ProDa: 用户从领域语料合成 SFT 数据、训练得到领域模型、用基准测试、失败时数据调试。中间由双向箭头连接, 强调'规约—实现—编译—测试'的四元对应。
这是论文的纲领性图, 把整个 ProDa 范式凝缩成一图, 不理解这张图就无法理解后续所有设计选择背后的理念来源。
上半部分 a/b/c/d 四个子图: a 是预训练剧本在领域微调中的失效 (没有共享结构导致失败不可追溯), b 是软件工程用共享规约解决同类问题的历程 (传统 vs TDD), c 是 ProDa 用共享知识结构关闭领域微调环路的对应, d 是两侧范式抽象的正式对应表。
把核心论点 (为何闭环必要 + 如何闭环) 用四联图同时展示, 是论证'为什么 pre-training playbook 不适用于 fine-tuning'的关键证据。