LogicPro: Improving Complex Logical Reasoning via Program-Guided Learning¶
会议: ACL 2025
arXiv: 2409.12929
代码: https://github.com/jiangjin1999/LogicPro
领域: LLM推理
关键词: 数据合成, 逻辑推理, 程序引导, LeetCode, 中间变量
一句话总结¶
提出 LogicPro 数据合成方法,利用 LeetCode 算法题和 Python 代码解作为逻辑源,通过"问题生成→代码中间变量提取→程序引导推理生成"三步流水线,从 2360 道算法题合成 540K 高质量文本推理数据,在 BBH27、LogicBench、DROP 等多个 OOD 基准上显著超越现有推理数据集。
研究背景与动机¶
- 领域现状:合成数据在提升 LLM 推理能力方面被广泛使用,数学和代码领域有 evol-instruct、back-translation 等成熟方法。但复杂逻辑推理领域的数据合成相对欠缺。
- 现有痛点:现有逻辑推理数据合成主要基于命题逻辑(RuleTakers、ProofWriter)或形式语言(FLD),逻辑模式单一(如 modus ponens),缺乏多样性,且与真实世界任务场景关联弱。
- 核心矛盾:算法题可以用代码轻松解决,但当同一问题被转化为自然语言推理问题时,LLM 往往会犯错。这个 gap 暗示了一种新的训练数据来源——用程序的逻辑来指导文本推理的学习。
- 本文要解决什么? 如何利用丰富的算法题+代码解来高效合成高质量、多样化、且带有标准答案和推理过程的逻辑推理训练数据?
- 切入角度:代码的中间变量输出天然对应人类推理的"中间步骤"——比如斐波那契数列的逐步计算对应爬楼梯问题的逐步推理。
- 核心idea一句话:算法题+Python 代码=天然的逻辑推理种子,代码中间变量=推理过程的骨架,据此可大规模合成带有准确答案和高质量推理路径的训练数据。
方法详解¶
整体框架¶
三步流水线: 1. 问题构造:LeetCode 算法题 + 特定测试用例 → 文本推理问题 2. 中间变量提取:Python 代码 + 测试用例 → 运行代码 → 获取最终答案 + 关键中间变量值 3. 程序引导推理生成:文本问题 + 中间变量输出 → LLM 生成完整推理过程
关键设计¶
- 数据收集与测试用例构造:
- 做什么:收集 2360 道 LeetCode 官方题目及其标准 Python 解,用 GPT-4 为每题生成 150 个测试用例(采样 3 次后去重过滤)
- 核心思路:每题最终有 ~300 个测试用例,每个测试用例可以生成一个不同的推理问题实例,实现极强的可扩展性
-
设计动机:算法题涉及递归、迭代、数据结构操作等多样逻辑模式,且天然关联真实场景(路径规划、资源分配等)
-
Step 1: 构造文本推理问题:
- 做什么:将算法题和具体测试用例结合,由 LLM 转化为自然语言推理問题并添加随机背景信息
- 示例:LeetCode-70"爬楼梯"+ 测试用例 n=17 → "一个人要爬17级台阶,每次可以爬1级或2级,有多少种不同的方法?"
-
质量控制:一致性检查(文本问题与代码是否对应)+ 可解性检查(过滤无意义问题),从 699K 过滤到 595K
-
Step 2: 代码中间变量提取:
- 做什么:修改 Python 代码,插入 print 语句输出关键中间变量,运行代码获取完整执行轨迹
- 核心思路:对于爬楼梯问题,打印斐波那契数列每一步的值 dp[1]=1, dp[2]=2, ..., dp[17]=1597
- 设计动机:中间变量天然对应推理的中间步骤,为后续推理生成提供"骨架"
-
质量控制:执行检查——过滤执行失败或有异常的代码(50K被过滤)
-
Step 3: 程序引导推理生成:
- 做什么:输入文本问题+中间变量输出,由 LLaMA3.1-70B 生成完整文本推理过程
- 核心思路:中间变量作为"锚点",确保推理过程的每一步都有代码执行结果的支撑
- 设计动机:避免 LLM 生成不准确的推理过程,程序执行结果作为 ground truth 引导
训练策略¶
- 最终数据集:540K 条问答对
- 训练混合:100K 通用数据 (OpenHermes-2.5) + LogicPro 数据
- SFT 训练:Megatron-LM,lr=1e-5,cosine schedule,3 epochs,32×A100
实验关键数据¶
主实验(Qwen2-7B, 基线对比)¶
| 合成数据 | BBH27 | LogicBench | DROP | AR-LSAT | BoardgameQA | FOLIO | GSM8K | 平均 |
|---|---|---|---|---|---|---|---|---|
| RuleTakers | 45.4 | 59.1 | 65.7 | 16.5 | 42.2 | 44.6 | 80.9 | 45.8 |
| LogicNLI | 43.3 | 71.3 | 67.4 | 17.8 | 45.3 | 41.7 | 81.6 | 45.0 |
| LogicBench | 44.7 | *95.9 | 67.4 | 17.8 | 41.4 | 38.7 | 82.1 | 46.6 |
| FLD | 42.0 | 69.5 | 68.3 | 14.8 | 34.9 | 45.6 | 80.0 | 43.8 |
| LogicPro | 50.9 | 73.5 | 68.3 | 19.1 | 48.1 | 46.1 | 81.5 | 51.2 |
大模型实验(Qwen2-72B)¶
| 合成数据 | BBH27 | LogicBench | DROP | AR-LSAT | 平均 |
|---|---|---|---|---|---|
| CLUTRR | 68.1 | 79.0 | 78.4 | 24.4 | 66.7 |
| LogicBench | 67.1 | *97.0 | 77.9 | 24.8 | 67.2 |
| LogicPro | 72.4 | 81.7 | 79.6 | 27.4 | 70.4 |
关键发现¶
- 全面OOD超越:LogicPro在所有10个基准上的7个指标中取得最优,且所有基准对LogicPro都是OOD(注意LogicBench的LogicBench分数是in-domain的*95.9,不公平对比)
- BBH27提升最大:这是最核心的复杂逻辑推理基准,LogicPro在Qwen2-7B上从基线最高的46.2提升到50.9(+4.7)
- 规模效应:72B模型上LogicPro的优势更加显著(平均70.4 vs 次优67.2)
- 数据效率:仅2360道算法题就合成了540K条数据,且随着收集更多算法题可持续扩展
亮点与洞察¶
- 代码→文本推理的桥接极为巧妙:代码中间变量天然对应推理中间步骤,这个洞察将代码执行的精确性引入了文本推理数据的合成
- LeetCode作为逻辑源是一个全新视角:此前的逻辑推理数据合成聚焦于命题逻辑/形式语言,LogicPro引入了算法逻辑(递归、数据结构、搜索等),大幅扩展了逻辑模式的多样性
- 三重质量控制(一致性检查+可解性检查+执行检查)确保了合成数据的高质量
局限性 / 可改进方向¶
- 依赖 GPT-4 生成测试用例和 LLaMA-70B 生成推理过程,合成成本不低
- LeetCode题目有限(~2360),虽然可扩展但需要新的算法题来源
- 代码中间变量的选择依赖LLM判断,可能遗漏关键步骤
- 未与最新的推理模型(如o1/R1)在合成数据上进行对比
相关工作与启发¶
- vs FLD (Morishita et al. 2023): FLD基于形式语言合成,逻辑模式较单一;LogicPro基于算法题,逻辑模式更多样
- vs ProofWriter (Tafjord et al. 2021): ProofWriter基于命题逻辑推导规则;LogicPro的逻辑来自实际算法
- vs evol-instruct: evol-instruct通过逐步增加复杂度合成数学问题,LogicPro通过不同算法题种子+不同测试用例实现复杂度和多样性
评分¶
- 新颖性: ⭐⭐⭐⭐⭐ 用算法题+代码执行结果合成推理数据的思路极其新颖,"代码中间变量=推理步骤骨架"的洞察非常精彩
- 实验充分度: ⭐⭐⭐⭐ 4个模型(7B-72B)、10个基准、多个基线对比
- 写作质量: ⭐⭐⭐⭐ 流水线描述清晰,质量控制模块完整
- 价值: ⭐⭐⭐⭐⭐ 提供了一种可扩展、高质量的逻辑推理数据合成方法,实用性极强