Files

141 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CodeI/O:通过代码输入-输出预测凝练推理模式
> **原文标题**:CodeI/O: Condensing Reasoning Patterns via Code Input-Output Prediction
> **arXiv**:[2502.07316](https://arxiv.org/abs/2502.07316) | **发布**:2025-02-11(v1),最后修订 2025-05-21(v4)
> **作者/机构**:Junlong Li(上海交通大学,于 DeepSeek-AI 实习期间完成)、Daya Guo、Dejian Yang、Runxin Xu、Yu Wu(DeepSeek-AI / 深度求索)、Junxian He(HKUST)
> **原文 PDF**:[03-CodeIO-2502.07316.pdf](./03-CodeIO-2502.07316.pdf)
## 一、摘要(全文翻译)
推理是大语言模型(Large Language Model, LLM)的一项基础能力。尽管此前的研究主要聚焦于增强数学或代码生成这类较窄的技能,但由于训练数据稀疏且碎片化,提升许多其他推理任务的性能仍然充满挑战。为解决这一问题,我们提出 **CodeI/O**,一种新方法:它把原始代码转化为「代码输入-输出预测」格式,从而系统性地凝练(condense)那些本就内嵌于有上下文语境的代码(contextually-grounded code)之中的多样化推理模式。通过训练模型在给定代码与测试用例的情况下、完全以自然语言作为思维链(Chain-of-Thought, CoT)推理过程来预测输入/输出,我们让模型接触到通用的推理原语——例如逻辑流程规划、状态空间搜索、决策树遍历与模块化分解——同时将结构化推理与代码特有的语法解耦,并保留过程的严谨性。实验结果表明,CodeI/O 在符号推理、科学推理、逻辑推理、数学与数值推理以及常识推理任务上都带来了一致的提升。通过将预测结果与已有标准答案比对,或使用预测出的输入重新执行代码,我们可以验证每一条预测,并通过多轮修订进一步增强 CoT,由此得到 CodeI/O++,并取得更高的性能。我们的数据与模型发布于 https://github.com/hkust-nlp/CodeIO 。
## 二、核心贡献
1. **提出「代码输入-输出预测」任务**:把原始代码改写为可执行函数,让模型完全以自然语言 CoT 预测「给定输入的输出」或「给定输出的可行输入」,将推理流程从代码语法中剥离而不失严谨。
2. **构建可扩展数据集 CodeI/O**:由约 810.5K 个代码文件筛出 454.9K 个可执行函数,执行代码自动生成输入-输出对,再由 DeepSeek-V2.5 合成 CoT,得到 3.5M 条样本(输入/输出预测约各半)。
3. **CodeI/O++ 兑现代码可验证性**:对第一轮预测错误的回答追加执行反馈并要求重写,把两轮回答与反馈拼接为更长响应,不丢弃任何错误样本即提升数据质量。
4. **跨模型、跨领域普适增益**:四个 7B–30B 基座、14 个基准上的平均分全面超过单阶段指令微调基线,以及 WebInstruct、OpenMathInstruct2、OpenCoder-SFT-Stage1、Python-Edu 等强基线。
5. **均衡而非偏科**:其他数据集常在某任务领先、别处回退,CodeI/O 几乎全基准一致提升,说明收益来自学到推理模式而非数据量堆积。
6. **系统性分析**:消融证明输入预测与输出预测缺一不可、拒绝采样反而有害;13-gram 泄漏检测表明提升不能归因于数据泄漏。
## 三、方法与技术要点
### 3.1 动机:为什么做「代码输入-输出预测」
论文指出的悖论是:数学解题与代码生成已有充足的结构化数据,而逻辑推导、科学推断、符号推理等领域只有稀疏、碎片化的监督。真实代码天然汇聚多样推理模式,但两条常规路径都不理想:在原始代码上做持续预训练(continual pre-training)时推理信号隐式且与噪声纠缠;文本到代码生成虽目标更干净,却被迫产出代码特有语法,难以迁移到代码之外。因此作者「逆用」代码:给定函数与文字 query,让模型用自然语言推理出输出或可行输入。其价值在于**解耦**——推理流程脱离语法外壳——与**重复暴露**:原代码的多样语境让模型反复接触逻辑流程编排、状态空间探索、递归分解、决策等基础技能,从而内化。该任务与代码持续预训练类似,被置于通用指令微调之前。
### 3.2 原始代码收集(§2.1)
三大来源各有侧重,共计约 810.5K 个代码文件(见下表):CodeMix 补充算法内容,PyEdu-R 刻意剔除算法类文件以与其错开,其他来源提供高质量难题与竞赛代码。
| 数据源 | 筛选方式 | 文件数 |
|---|---|---|
| CodeMix | 取自内部代码预训练语料,用 DeepSeek-Coder-V2-Lite-Inst 做函数补全,保留成功率 10%–90% 的文件(滤除过简/过难) | 约 427K |
| PyEdu-R(reasoning) | Python-Edu 子集,先分类为算法/逻辑谜题/数学/科学计算/系统建模/其他复杂推理/非推理,剔除算法与非推理以避免与 CodeMix 重叠 | 约 369K |
| 其他来源 | 综合算法仓库(TheAlgorithms/Python)、Project Euler、LeetCode、CodeWars、Edabit、Codeforces、AtCoder、CodeChef | 约 14.5K |
### 3.3 转换为统一格式(§2.2)
原始代码缺少结构、难以自包含执行,故用 DeepSeek-V2.5 重构为五部分:①**清洗后的参考代码**——核心逻辑抽取为函数,剔除绘图(print、plot)与文件读写;②**主入口函数**——概括整体逻辑,可调用其他函数或导入外部库,须有非空输入与有意义的返回值,且输入输出均可 JSON 序列化;③**输入/输出描述**——明确数据类型、约束(如输出范围)或更复杂的要求(如字典的键);④**输入生成器**——不直接产出测试用例,而是生成基于规则的 Python 函数,在约束下引入随机性以可扩展地产出「非平凡」输入;⑤**Query**——描述代码预期功能的简洁问题陈述。
### 3.4 采集输入-输出对(§2.3)
对每个函数采样多个输入并执行代码取得真实输出;为保证确定性,含随机性的函数(如使用 `import random`)全部跳过。执行约束见下表(附录 A),对象复杂度检查递归作用于所有子对象,以确保结果落在通用 LLM 可预测的范围内。
| 约束项 | 阈值 |
|---|---|
| 单样本运行时限 | 5 秒 |
| 输入/输出对象总大小 | < 1024 字节 |
| 列表 / 字典长度 | < 20 |
| 字符串长度 | ≤ 100 字符 |
| 其他类型对象大小 | ≤ 128 字节 |
过滤不可执行、超时与超复杂度样本后,得到来自 454.9K 个代码文件的 3.5M 条实例,输入/输出预测大致均衡(50%/50%)。各来源采样密度不同(附录 C.2):CodeMix 每函数至多 3 对(300K 样本,平均 2.78/2.80,共 1,674,345 条);PyEdu-R 至多 6 对(141K 样本,平均 5.77/5.79,共 1,630,716 条);其他来源至多 10 对(13.9K 样本,平均 7.70/7.87,共 216,159 条)。
### 3.5 构建训练样本:CodeI/O 与 CodeI/O++(§2.4)
每条样本由 prompt 与 response 组成:prompt 用模板组合函数、query、参考代码与一个具体输入或输出;response 应是自然语言 CoT,说明如何推出正确输出或可行输入。作者未用自动执行轨迹作答案:输入预测无法得到确定性的「逆函数」,且模板化轨迹缺乏自由语言推理的表达力与泛化性。故全部响应由 DeepSeek-V2.5 合成(性能顶级、成本低),这构成 **CodeI/O**。
**CodeI/O++** 放弃常见的拒绝采样:既然能重新执行代码验证回答,本可丢弃错误预测,但实测性能反而次优(§4.1)。作者改为把执行反馈作为第二轮输入追加并要求重写:输出预测只告知答案错误;输入预测额外给出「基于错误输入实际执行得到的输出」;执行失败(格式错误、参数不匹配或其他运行时错误)也显式告知。最终响应拼接为「第一轮回答 + 第一轮反馈 + 第二轮回答 + 第二轮反馈」;第一轮已正确时反馈仅为「Success」且无第二轮内容。第一轮约 50% 回答正确,错误回答中约 10% 可在第二轮修正;对错一律保留。
### 3.6 两阶段训练策略(§3.1)
第一阶段在 CodeI/O(++) 上训练,第二阶段在约 1.18M 条内部指令数据(多领域、多语言)上做通用指令微调。之所以分阶段而非直接混合:CodeI/O(++) 样本量远大于指令数据,混合会造成分布偏置、令指令跟随能力学习不足。超参数见下表(附录 E)。
| 阶段 | 训练量 | 批大小 | 学习率 | 其他 |
|---|---|---|---|---|
| 第一阶段 | 1 epoch | 1024 | 1e-5(三个较小模型)/4e-6(Gemma 2 27B),恒定 | 无 warmup,最大序列长度 4096 |
| 第二阶段 | 700 步(约指令数据 3 epoch) | 1024 | 3e-5/1e-5,余弦调度衰减至 1e-6/3e-7 | 无 warmup,最大序列长度 4096 |
## 四、主要实验结果
评测覆盖 14 个基准(名称见下表):其中 LeetCode-O 为自建,只给文字 query 不给函数、中英双语、按问题级准确率计分;BBH-ZH 由 9 个 BBH 子任务翻译而来。除 BBH-EN/-ZH 用 3-shot 外,其余均为零样本、greedy 解码。
| 基座模型(平均分 AVG) | 单阶段基线(仅指令微调) | 第一阶段最强对比数据集 | CodeI/O | CodeI/O++ |
|---|---|---|---|---|
| Qwen 2.5 Coder 7B | 54.8 | 56.0(OpenMathInstruct2 全量 14.0M) | 57.2 | **57.7** |
| LLaMA 3.1 8B | 49.3 | 50.6(OpenMathInstruct2 3.5M) | 51.2 | **52.1** |
| DeepSeek Coder v2 Lite 16B (MoE) | 51.6 | 52.1(Python-Edu 7.7M / OpenMathInstruct2 3.5M) | **53.6** | 53.5 |
| Gemma 2 27B | 59.5 | 60.4(WebInstruct 3.5M / OpenMathInstruct2 3.5M) | 60.9 | **61.5** |
以 Qwen 2.5 Coder 7B 为例的分项对比:
| 基准 / 任务 | 单阶段基线 | CodeI/O | CodeI/O++ | 说明 |
|---|---|---|---|---|
| WinoGrande | 66.9 | 67.9 | 66.9 | 常识推理,持平 |
| DROP | 70.7 | 76.4 | **79.1** | 阅读理解中的数值推理,+8.4 |
| GSM8K | 83.4 | 86.4 | 85.7 | 小学数学,约 +2 |
| MATH | 71.6 | 71.9 | 72.1 | 竞赛数学,小幅提升 |
| GPQA | 41.5 | 43.3 | 40.6 | 学科问答,++ 反而回退 |
| MMLU-STEM | 77.2 | 77.3 | 77.9 | 学科知识,持平 |
| LeetCode-O | 20.7 | 23.7 | **24.2** | 自建输出预测,+3.5 |
| CRUXEval-I | 61.3 | 63.6 | 62.5 | 输入预测 |
| CRUXEval-O | 60.0 | 64.9 | **67.9** | 输出预测,+7.9 |
| BBH-EN | 68.3 | 69.3 | **71.0** | +2.7 |
| BBH-ZH | 70.6 | 72.8 | **74.2** | +3.6 |
| ZebraLogic | 10.9 | 10.7 | 10.7 | 逻辑网格谜题,略降 |
| KorBench | 38.7 | 44.3 | **45.7** | 规则泛化推理,+7.0 |
| LiveBench | 26.0 | 28.5 | **29.1** | 综合基准,+3.1 |
CodeI/O 在四个基座上普遍带来增益,且增益是「均衡」的:对比数据集常绿红混杂,它却几乎全绿——仅用代码类数据便提升了符号、逻辑、数学、科学与常识任务,说明学到的是可迁移的推理模式。而在原始代码语料(Python-Edu 7.7M)上训练相对基线只有微小甚至负向提升,证明收益不来自数据规模,而来自训练任务的设计。少数任务(如 ZebraLogic)性能几乎不变甚至下降,并非每项必然提升。
主要分析结论:
| 分析维度 | 结论 |
|---|---|
| 输入预测 vs 输出预测 | 单独训练总体相近(各约 56.1/56.4,全量 57.2)。输入预测在 KorBench 更强但略损 GPQA,输出预测更利于 BBH 等符号推理;CRUXEval-I 与 -O 分别偏好输入预测与输出预测。 |
| 拒绝采样 | 丢弃错误回答会删掉 50% 数据,总体性能下降,作者归因于多样性损失;把错误回答替换为执行得到的真值(无 CoT)虽提升 LeetCode-O/CRUXEval-O,却在别处下降、拉低平均(56.6),且与样本量相当的 ~50% 子集(56.7)相比无优势,故保留全部错误回答。 |
| 合成模型的影响 | 用 DeepSeek-V2.5 重新合成 3.5M WebInstruct 子集(WebInstruct-DS25)优于原版,但仍不及 CodeI/O,说明收益超出「从强模型蒸馏知识」。 |
| 规模效应 | 随机采样显示训练实例越多越好;在 I/O 对维度放大(固定代码样本、增加每样本测试用例)也有清晰收益,尤其从 1/6 增至 6/6,说明某些推理模式需多个测试用例才能完整学到。 |
| 数据格式 | query 与参考代码放 prompt、CoT 放 response 时平均分最高且最均衡;最差格式为 query 在 prompt 而参考代码在 response(类似标准代码生成任务),凸显 CoT 与测试用例扩展的重要性。 |
| 多轮修订 | 第 0→1 轮提升一致,第 1→2 轮收益极小(LLaMA 3.1 8B 略升、Qwen 2.5 Coder 7B 回退),模型常重复同样的错误 CoT,故主实验止步单轮修订。 |
| 两阶段 vs 混合 | 所有两阶段变体均优于单阶段混合训练;Qwen 2.5 Coder 7B 上最优为完全分离 CodeI/O 与指令数据,LLaMA 3.1 8B 则混入数据更好,为简化方法主实验采用完全分离。 |
| 数据泄漏 | 严格 13-gram 检测(去标点、数字、空白后比对)显示多数基准无风险或远低于增益:LeetCode-O 21.5%、KorBench 5.1%、MMLU 0.1%、MATH 0.1%、CRUXEval 0.1%、其余 0.0%。重叠仅为「数独规则」等通用描述或共享描述的姊妹题(Two Sum I/II);完整集与去泄漏子集的样本级增益几乎一致(如 Qwen 在 LeetCode-O 为 3.8/3.9),故提升不是数据泄漏所致。 |
## 五、结论、局限与影响
- **结论**:论文提出 CodeI/O,让模型用纯自然语言 CoT 预测代码的输入与输出,借代码结构化、可扩展、可执行验证的特性学习符号、逻辑、数学与常识等推理模式。在四个 7B–30B 基座、14 个基准上,CodeI/O 与 CodeI/O++ 一致优于现有基线,跨基准均衡提升而几乎不牺牲任何领域性能。作者强调该方向与推理时扩展(o1、DeepSeek-R1)正交,可为激发 LLM 推理能力提供更好的基础。
- **局限性**:论文未设专门的 Limitations 章节,但正文与附录自述了若干不足:① 少数任务(如 ZebraLogic、CodeI/O++ 的 GPQA)不升反降,提升并非在所有基准上成立;② 多轮修订第二轮收益甚微、Qwen 上甚至回退,故只做到单轮;③ PyEdu-R 样本多集中于非平凡浮点计算、缺少高层推理流程,模型难以有效学习,提纯该数据源被列为未来工作(附录 C.3);④ 训练数据与测试基准的模式重叠不可避免,只能以 13-gram 检测与去泄漏子集论证影响有限;⑤ 最优数据混合策略尚未确定;⑥ 换成公开指令数据 Tulu-3 时 CodeI/O++ 略逊于 CodeI/O,说明效果依赖指令数据的类型覆盖。
- **影响**:该工作把代码从「生成目标」转化为**推理监督的来源**,给出不依赖数学/代码标注、可自动扩展与验证的通用推理能力提升路径;「用执行反馈修订而非丢弃数据」与「先强化基座推理、再指令微调」的配方亦具借鉴意义。
## 六、关键术语对照表
| English | 中文 |
|---|---|
| Code Input-Output Prediction | 代码输入-输出预测 |
| Reasoning Pattern | 推理模式 |
| Chain-of-Thought (CoT) | 思维链 |
| Contextually-grounded Code | 有上下文语境的代码 |
| Input / Output Prediction | 输入预测/输出预测 |
| Main Entrypoint Function | 主入口函数 |
| Input Generator | 输入生成器 |
| Unified Format | 统一格式 |
| Rejection Sampling | 拒绝采样 |
| Multi-turn Revision | 多轮修订 |
| Execution Feedback | 执行反馈 |
| Code Execution Verification | 代码执行验证 |
| Continual Pre-training | 持续预训练 |
| Two-stage Training | 两阶段训练 |
| Instruction Tuning | 指令微调 |
| Data Leakage (13-gram overlap) | 数据泄漏(13-gram 重叠) |