
推理训练这几年最大的变化不是模型参数越堆越大而是数据构造思路从“堆答案”转向了“堆过程”。Reasoning Core 这个方向把注意力放在一类很值得研究的数据上程序化数据。它的核心价值不是让模型多背一条知识而是让模型在补全训练中真正学会拆步骤、按规则推理、在中间过程里自我纠错。这篇文章会围绕程序化数据的设计、补全监督训练的组织方式、数据生成时的边界条件以及训练过程中常见的失败模式展开。适合正在做推理训练、SFT 数据构造、过程监督数据清洗的算法工程师也适合刚接触推理数据但对合成数据有兴趣的研究者。先给一个整体判断Reasoning Core 这类方案最值得借鉴的不是某个具体数据集有多大而是“程序化数据”这种数据形态。它把推理过程拆成可验证、可补全、可监督的中间步骤让模型在训练时不是只看到最终结论而是看到一步步的推导轨迹。这种设计对模型推理能力的提升往往比单纯加大指令数据量更直接。1. 先理解程序化数据在推理训练里的位置1.1 为什么不能只靠“答案监督”早期指令微调最常见的做法是给模型一堆问题和标准答案训练目标就是让模型学会输出答案。这个模式对短回答、知识问答够用但对数学证明、逻辑推理、代码推演这类任务有一个很明显的短板模型不知道答案是怎么来的。如果训练数据里只有“最终结果”模型能学到的就是把输入映射到输出。中间一旦有多个可行路径模型没有先验来判断哪条路是对的也没有机会在中间步骤上获得纠正信号。结果就是训练集里的题能做对稍微换个数字、换个问法就崩掉。补全监督的思路是用中间步骤作为监督信号。模型不再只补全最终答案而是补全每一步推理。这样梯度信息就不再只在最后一个 token 上传播而是分布在整个推理轨迹上。Reasoning Core 里强调的 Completion-Supervised本质上就是把“补全”这个动作从答案层下沉到步骤层。1.2 程序化数据解决了什么问题程序化数据的定义可以很直接它不是人工一句句写出来的自然语言推理而是由规则、模板、逻辑结构组装出来的半结构化数据。这类数据有几个共同特点每一步推理都有明确的前置条件和输出结果。步骤之间是强依赖关系不是并列堆砌。错误可以被定位到具体某一步。数据可以批量生成天然适合规模扩展。在补全监督训练里程序化数据的优势非常明显。因为它每一步都可验证所以当你把一条推理轨迹切分成多个补全点时每个点上的监督信号都是可靠的。如果是自然语言长文本推理你很难判断某一句中间结论是不是唯一正确但程序化数据里中间结论往往可校验甚至可以直接通过执行结果确认。1.3 这类数据适合哪些任务从实际训练来看程序化数据最适合以下任务形态数学题每一步化简、每一步方程变换都能单独验证。逻辑推理多重条件判断每一步都有明确的前件和后件。算法题伪代码、状态变化、复杂度分析都可以拆成程序化步骤。表格问答单元格引用、过滤条件、聚合步骤都是结构化操作。工具调用链每一步调用的输入输出格式固定适合监督轨迹。反过来写作文、开放问答、创意生成这类任务不适合强行套程序化结构。强行把开放任务拆成“步骤”得到的往往是机械连接对模型没有正向帮助。2. 程序化推理数据的设计框架2.1 数据最小单元单步推理记录设计程序化推理数据先要确定最小单元。我一般建议把最小单元定义为“一条可验证的推理记录”它至少包含四个字段当前状态这一步开始时已知什么条件、已经得到什么中间结果。操作类型这一步做了什么动作比如化简、代入、排除、计算、调用函数。操作参数这一步用到的关键数值、变量、规则或函数。输出状态这一步完成后状态变成什么。举个例子。假设题目是“三个连续整数之和为 42求最大整数”程序化数据可以拆成状态未知数 x三个数分别是 x、x1、x2和为 42。操作建立方程 x (x1) (x2) 42。参数无特殊参数。输出3x 3 42。下一步就是另一个最小单元。这样每条记录独立后可验证组合起来就是完整推理链。2.2 推理链的组织方式拿到最小单元后要把它们串成推理链。串的方式有三种常见结构我建议根据任务性质选择。第一种是线性链。每一步只依赖前一步适合方程求解、数值计算、简单规则推导。这种结构最简单也最适合训练初期。第二种是分支链。某一步有两个候选操作其中一个正确、一个错误模型需要在分支处做选择。这比线性链更有训练价值因为模型被迫在关键节点上做判断。第三种是收敛链。多个前置条件汇聚到一个结论或者从多个候选中筛选出唯一正确结果适合逻辑排除、条件过滤这类任务。补全监督训练可以在这三种结构上分别设置补全点。线性链在每个步骤之后设置补全点分支链在分支判断处设置补全点收敛链在最终收敛前设置补全点。补全点的选择直接影响训练效果后面单开一节细说。2.3 状态表示怎么写才能让模型好读程序化数据如果不注意表示方式很容易变成“机器能读但模型学不动”的格式。我踩过的主要坑有三个第一个符号过密。把所有中间状态都压缩成公式和变量名模型很难学到语义关联。更好的做法是在关键步骤旁边保留一句自然语言说明比如“合并同类项后方程变为”让模型知道这一步在做什么。第二个状态变量不一致。前一步输出的变量名下一步突然换了一个别名模型读起来会非常困惑。程序化数据生成时要专门做变量一致性校验同一个对象全程使用同一标识符。第三个缺少“无效信息”过滤。不是所有中间状态都值得放进监督信号。有些步骤只是转写题目条件没有实际推理价值放在数据里反而会稀释监督信号。我会在生成后加一层过滤规则把纯转写、无信息增益的步骤删除或合并。3. 补全监督训练的设计要点3.1 补全点怎么选补全监督最核心的设计决策是在哪里让模型停下来补全。这里没有万能答案但有一个基本判断标准补全点的位置应该落在“模型如果不做这一步后续就无法正确推进”的位置。具体来说我会按以下优先级选择补全点分支判断点。模型必须决定走哪条路这类点是最高价值补全点。状态转换点。从前一个中间状态推导出下一个中间状态这是推理链的主干。结论推导点。从多个中间结果得出最终答案考验模型的信息汇聚能力。不要在每个最小单元后都设置补全点。补全点太多训练序列会变得支离破碎模型反而学不到完整流畅的推理。我的经验是一条 8 到 12 步的推理链设置 3 到 5 个补全点比较合适。如果推理链更长可以按语义段分批补全而不是逐 token 补全。3.2 补全监督和下一个 token 预测的关系补全监督不是要替换标准的语言建模目标而是在语言建模目标上叠加一层规律性的“停顿-补全”结构。训练时推理链会分成两部分已经给定的一段上下文和需要模型补全的一段内容。模型在给定上下文上正常计算注意力但在补全段上损失会额外加权。这样一来模型既拥有完整推理链的全局信息又在关键步骤上获得更强梯度。实现时要注意补全段不能太短。如果只补全一个数字模型很容易学会猜答案。如果补全一整段推导监督信号又太粗。我一般控制补全段在 2 到 4 个句子之间保证里面有完整的一个操作环节。3.3 和过程监督、结果监督的区别过程监督通常是指给每一步推理都标注好坏然后用一个奖励模型或分类器来判断步骤质量。结果监督则是只判断最终答案对不对。Completion-Supervised 介于两者之间它不做显式的好坏标注而是通过“给定上文补全下文”这个任务隐式地让模型学会中间步骤的生成。这种设计有一个很实际的好处数据构造成本低。过程监督需要对每一步做质量标注人工成本很高补全监督只需要把推理链切分好成本集中在切分策略上不用逐步骤打分。另一个好处是训练目标更统一。模型在预训练阶段已经在做“预测下一个片段”这件事补全监督只是把这种能力用到推理链上迁移阻力更小。4. 程序化数据生成与清洗的具体流程4.1 基于模板生成初版数据程序化数据最直接的来源是模板生成。先把任务类型抽象成模板再往模板里填充不同的条件、数字和规则。以数学题为例模板可以写成变量生成随机生成初始数值范围。规则定义生成一个可复合的运算规则。正向推导按规则一步步生成推理链。反向出题把推导链中某一步设为未知反推题目条件。反向出题是程序化数据生成里很关键的一步。它能保证题目在数学上成立因为所有条件都是从已知推导链反推出来的。人工出题经常出现条件冲突反向生成能从根本上避免这个问题。4.2 用规则引擎做一致性校验模板生成出来的数据必须过一道一致性校验。校验重点包括变量是否一致同一个变量名是否始终指向同一个对象。条件是否可满足题目的初始条件是否能推出至少一条完整推理链。步骤是否可执行每步操作是否能从前置状态下发执行。结果是否唯一答案本身不应有多义性。规则引擎是实现这些校验的好工具。把题目、推理链、中间状态都结构化后用规则引擎逐条检查。如果某一步无法执行就丢弃这条数据而不是修补因为修补往往会让数据产生噪声。我还建议在数据生成管线上保留每条数据的生成参数。这样当你发现某类错误率偏高时可以直接回溯到生成参数调整数值范围或规则复杂度而不是手工修数据。4.3 利用“错题”构造负样本程序化数据的另一个优势是可以系统地生成带错误步骤的负样本。这在推理训练里非常有用。构造负样本的方法很简单在推理链的某个分支点把正确的操作换成错误的操作同时保留后续步骤的推导一致性。也就是说这个错误不是胡乱编造而是“如果模型选错接下来它看到的世界会是什么样”。负样本的价值在于它能让模型看到从错误前置条件出发的完整后果。这样模型在推理时能更早地识别出“这个状态不对劲”。如果训练数据里只有正样本模型学到的是匀速推理加上结构化的负样本后模型才学会“发现问题并返回修正”。不过负样本比例不宜过高。我测试下来的经验是负样本占整个推理数据集的 10% 到 20% 比较合适。比例过低模型不容易形成纠错意识比例过高模型会变得畏手畏脚频繁推翻自己的推理。4.4 人工抽查与分层抽样程序化数据生成虽然自动化程度高但不能完全省略人工检查。我的建议是分层抽样不要随机抽样。按题目复杂度分层简单题抽 5%中等题抽 2%难题抽 10%。按推理链长度分层短链抽 1%中链抽 3%长链抽 8%。按操作类型分层每一类操作单独抽几条检查。人工检查时重点看三样东西推理链是否流畅、中间步骤是否有多余或跳跃、补全点的位置是否合理。如果人工检查发现某类数据系统性有问题先停掉生成管线修模板或校验规则不要继续生产。5. 训练时要注意的边界条件5.1 数据规模和学习率的关系程序化数据有一个容易被忽视的问题它比自然语言数据更容易过拟合。因为模板生成的推理链结构高度相似模型训练十几个 epoch 后可能开始死记模板而不是真正理解推理规则。我的建议是程序化数据的训练 epoch 数要比通用 SFT 数据少。通用指令数据可以训练 3 个 epoch程序化推理数据训练 2 个 epoch 甚至更少就够。如果发现验证集上 loss 持续下降但推理能力没有提升先怀疑是不是过拟合到模板了。学习率方面程序化数据适合用较低的学习率。这类数据的信息密度高梯度方向比较一致学习率太高会让模型在推理能力上过度偏向新数据从而遗忘原有能力。5.2 混入通用数据防止能力退化纯程序化推理数据训练出来的模型推理能力可能很强但通用对话能力会退化。这不是理论猜测是实践里很容易遇到的现象。解决方法是按比例混入通用 SFT 数据。常见的做法是程序化推理数据占 30% 到 50%通用指令数据占 50% 到 70%。这个比例没有绝对标准要看模型的基座能力和目标场景。如果你的模型已经部署在问答产品里我更建议先做小规模混入实验从 10% 推理数据开始逐步上调观察推理能力提升和通用能力下降的拐点。找到拐点后把推理数据比例控制在拐点之前。5.3 补全段的损失加权补全监督训练里损失加权是一个可以调但不要调太猛的超参数。把补全段损失权重设为普通段的 2 倍通常就能看到明显的训练引导效果。但如果设到 10 倍模型会牺牲流畅性变成一步步机械拼接整体输出观感很差。另一个要注意的是补全段在整个序列里的位置。靠近序列开头的位置补全监督效果通常较弱因为模型还没建立起足够的上下文。靠近关键结论的位置补全监督效果最强但也容易让模型跳过中间推理直接猜结论。我建议在序列中间和后半段多设置补全点。6. 评估程序化推理训练效果的方式6.1 用逐步正确率替代最终正确率很多团队训练推理模型评估时只看最终答案正确率。这个指标在程序化推理数据训练里不够用。最终答案正确率只能告诉你模型有没有到终点不能告诉你模型在哪个环节出了问题。更有效的做法是计算逐步正确率把模型生成的推理链切分成步骤和标准推理链逐段比对看哪一步开始偏移。逐步正确率能帮助定位训练数据的薄弱环节。比如模型在前两步正确率很高到第三步大量失败这说明第三步对应的程序化数据质量不高或补全点设置不合理。这种诊断信息只靠最终正确率永远得不到。6.2 复杂度外推测试程序化数据训练最容易出现的问题是“训练数据里的题会做新题不会做”。为了更早发现这个问题我会在评估集里加入复杂度外推测试。具体做法是把训练数据里的数值范围、推理步数、分支数量都比训练集提高一档。比如训练集里最多 8 个条件测试集里出 12 个条件训练集里推理链最长 10 步测试集里出 15 步。如果模型在复杂度外推测试上明显崩溃说明推理能力还停在记忆模板层面。如果模型能平滑处理更高复杂度的任务说明确实学到了可组合的推理规则。这个测试是判断推理训练是否真正有效的重要标准。6.3 错误分布分析训练结束后我会把模型在验证集上的错误聚成几类条件漏读模型漏掉了题面中的某个关键条件。步骤跳跃推理链缺了一步但结论碰巧对了。分支误判模型选择了错误分支。计算错误推理逻辑正确但计算过程出错。回答格式错误推理正确但最终答案格式不被解析器接受。不同错误类型对应不同的数据策略。条件漏读需要增加信息定位类数据步骤跳跃需要在跳跃点附近增加补全点分支误判需要增加分支数据的多样性计算错误需要增加数值范围变化格式错误则需要统一输出模板。7. 常见报错和排查思路7.1 训练 loss 下降但推理能力不涨这是推理训练里最让人困惑的现象之一。loss 在降说明模型确实在拟合训练数据但推理能力没有同步提升。先排查是否过拟合到模板。把训练集里的题目的数值全部换掉让模型重新推理如果准确率大幅下降基本就是过拟合。再排查数据多样性。程序化数据如果只靠有限的模板生成模型学到的是模板匹配不是推理规则。需要扩充模板类型、操作类型和条件组合的多样性。最后排查补全点分布。如果补全点集中在同一类操作上模型只在这类步骤上获得监督信号其他步骤仍然只靠普通语言建模学习推理能力自然提升有限。7.2 模型输出中间步骤但最终答案出错这类问题通常出在“中间步骤正确但最后没有正确汇聚”。模型能一步一步推进却无法从多个中间结果中提取出最终答案。我建议在当前评估集上做一次“带提示的推理”在最后几步上显式给出汇聚提示比如“根据上面得到的三个关系式现在写出最终方程”。看模型能否正确回答。如果在提示下能回答说明模型的问题不是推理能力缺失而是缺少“汇聚动作”的训练。对应的数据策略是在收敛链结构的末尾补更多补全点让模型反复学习“从多个中间状态推出结论”这个动作。7.3 推理结果对输入微调过于敏感换个数字就不会做换个变量名也不会做这是程序化数据训练时的典型毛病。原因在于模型记住了训练数据里的具体数字模式没有抽象到变量层面的规则。解决方案有两个路径。第一在数据生成时增大随机范围不要集中在固定数值区间。第二加入“符号替换”增强。把同一道题的变量名、数字、条件顺序进行随机化让模型学习到模式而不是记住表面。我在实际项目中通常会对程序化数据生成两到三个等价变体。同一个逻辑结构用不同的变量名和数字生成多条数据训练效果会明显好于单条数据复制十遍。7.4 补全监督训练中遇到重复生成模型在补全点处生成的内容和上文完全重复或者反复生成同一个步骤。这通常是补全段和监督段边界设置不合理导致的。先检查补全点的位置如果剪裁边界在一个步骤的中间模型很难判断该生成什么。我建议补全段永远从一个完整步骤的开头开始到该步骤结尾结束中间不做截断。再检查训练时的注意力掩码补全监督要注意不要让模型直接看到补全段的目标内容。虽然这是基础要求但在长序列训练时注意力掩码偶尔会因为拼接逻辑出错而泄漏信息一旦泄漏模型就会学到“重复上文”这种偷懒策略。8. 从单任务到批量化生产的落地建议8.1 先建小规模验证集再大规模生成程序化数据生成管线一旦写好跑几万条很容易。但我不建议直接进入大规模生成。正确的顺序是先手工构造 50 条高质量推理链作为金标准。把模板生成的数据和这 50 条做结构比对看看覆盖率。用一条最小训练集验证训练流程能跑通。逐步扩大数据规模每扩大一倍抽样检查一次。这个流程看起来慢实际上能避免最可怕的场景生成了几十万条数据训练完才发现数据有问题所有实验全部作废。8.2 把数据生成管线做成可追溯的程序化数据生成有一个天然优势每一条数据的源头是哪个模板、用了哪些生成参数都是可以记录的。我强烈建议把这份记录保存下来格式可以用 JSON Lines。当训练效果不理想时这份记录能帮你快速定位问题。比如你发现模型在“整除求余”这类操作上容易出错直接查生成记录里这个操作对应的模板看它的条件分布是否太窄、参数范围是否太集中、推理链长度是否太短。没有追溯能力的数据管线遇到问题只能靠猜效率极低。8.3 和 Base Model 能力的匹配程序化数据的复杂程度要匹配基座模型的能力。Base 模型如果连基本指令遵循都做不好直接上复杂推理训练效果不会好。我一般会用一组基础推理测试题先给 Base 模型摸底。如果基础测试正确率低于 30%先不要急着加复杂程序化数据应该先做基础指令微调把模型拉到一个正常水平再进入推理训练。如果基础测试正确率已经超过 60%可以考虑加入中等复杂度的程序化数据。只有当模型在中等复杂度数据上能稳定提升时才去挑战更高阶的分支、收敛和长链推理数据。9. 几个值得继续保持关注的方向9.1 长推理链的程序化数据目前的程序化数据多数集中在 10 步以内的推理链。这个长度对大多数训练目标够用但真实世界的推理任务往往更长。长链推理的主要难点在于错误累积每一步有小概率出错链越长整体正确率下降越快。要生成高质量长链程序化数据我建议采用分段构造加拼接的策略不要一次从头生成到尾。先分别构造几个短链再用高层次的推理步骤把它们连接起来。这种自底向上的构造方式能更好地保证每段内部的正确性。9.2 跨域程序化数据的格式统一数学题、表格问答、工具调用链这三种任务虽然都属于程序化推理但文本格式差异很大。如果直接混在一起训练模型可能会学到格式上的混淆。我建议在构造阶段为不同任务约定统一的推理链骨架。骨架只包含状态、操作、输出三大类信息具体内容按领域填充。这样模型在不同领域间切换时能够复用相同的推理模式而不是为每个领域单独学习一套结构。9.3 用程序化数据做推理能力探测除了做训练数据程序化数据还有一个用途作为推理能力探测集。因为程序化数据的每一步都可验证你可以设计一组由易到难、由短到长的诊断任务在模型训练的各个阶段快速评估推理能力的变化。这比用几十道竞赛题做基准更精细也更容易定位到具体能力维度。把探测集做成自动化脚本每次训练结束后自动跑一遍输出逐步正确率和错误分布长期积累下来你会对自己模型的推理能力边界有非常清晰的认识。Reasoning Core 所代表的程序化数据方向真正值得投入的地方在于它让推理训练从“看答案猜过程”变成“过程本身有监督、有验证、有纠错”。这个方向能不能发挥全部价值取决于数据构造是否规范、补全点设计是否合理、评估指标是否足够细。先把单条推理链做扎实再谈规模是我个人最推荐的实践路径。