多跳推理任务要求模型连续执行多个相互依赖的推理操作,例如先定位文档中的关键实体、再根据该实体检索对应属性、最后结合属性完成比较或计算。这类任务里,模型暴露出的常见问题不是最后一步不会做,而是推理链在中间某个环节发生静默断裂。一个典型的例子是:模型在第一步正确识别了时间范围,第二步却把不同时间段的数据混在一起,第三步虽然使用了正确公式,但基于错误中间量得出了看似合理的答案。这种断裂比明显错误更难发现,因为它不会触发语法异常,最终答案的格式和置信度可能都很正常。

从训练目标看,传统指令微调往往只对最终输出计算交叉熵损失,模型在中间步骤上的偏差不会受到直接惩罚。即使使用结果奖励模型,反馈信号也要经过整条链反向传播,信用分配非常粗糙。一个中间步骤的错误可能在最终奖励中被后续步骤偶然修正,也可能被另一个错误掩盖。因此,为了让模型学会在每一步都保持推理的有效性,需要引入中间监督机制,将验证信号直接作用到每个推理状态上。
多跳推理链断裂的成因与表现
多跳推理的每个步骤通常依赖前一个步骤的输出。可以把一条推理链写成 s0 到 s1 到 s2 一直到 sn,其中 s0 是问题,sn 是最终答案。链断裂指的是存在某个中间状态与它的前一个状态之间缺乏有效的逻辑承接关系,或者该中间状态本身包含事实错误、概念混淆、重复计算等问题。例如在三个文档中分别找到某公司2020年、2021年和2022年的营收后,需要计算平均增长率,模型可能在第二步错误地使用了2021年数据替代2020年数据,后续计算完全正确但答案错误。
这种错误的隐蔽性在于,单独看每一步都可能没有明显的语法或格式问题。如果只看最终答案,甚至会和正确答案非常接近。从概率角度分析,若每步正确的概率为 p,经过 k 步后,整条链正确的概率约等于每一步正确概率的连乘。即使 p 达到0.95,经过8步后整体正确率也会降到约0.66。而实际多跳任务中单步正确率往往低于0.9,因此长链推理的整体可靠性会迅速下降。中间监督的目标就是提高每一步的条件正确率,并允许模型在生成下一步之前先验证当前步骤。
下面这段伪代码模拟了一个未加中间验证的推理链生成过程,可以看到即使中间步骤置信度不高,模型仍会继续生成,最终积累出错误结果。
steps = []
confidence = []
current_state = encode(question)
for i in range(max_steps):
# 模型基于当前状态生成下一步推理
step, step_conf = model.generate_step(current_state)
steps.append(step)
confidence.append(step_conf)
current_state = update_state(current_state, step)
# 没有中间验证,即使 step_conf 很低也不会停止或修正
answer = model.generate_answer(current_state)
print(answer)
中间监督如何把验证信号压到每一步
中间监督的核心思想是:不再只给最终答案一个全局奖励,而是为每个推理步骤提供局部监督信号。这通常通过两种方式实现。第一种是训练一个独立的过程奖励模型(Process Reward Model,PRM),它接收当前问题、历史推理步骤和当前步骤作为输入,输出一个0到1之间的分数,表示该步骤正确且有助于最终答案的概率。第二种是在微调阶段直接使用步骤级标签,例如人工标注每个中间步骤是否有效,然后对每一步的生成概率施加加权损失。
与结果奖励模型相比,过程奖励模型能够更精确地定位错误。结果奖励模型只回答“最终答案对不对”,当答案错误时,它无法告诉模型是哪一步出了问题。而过程奖励模型对每个步骤分别打分,错误步骤会被单独标记为低分,即使后续步骤“看起来合理”,也不会把奖励错误地分配过去。这种逐步骤的奖励信号在强化学习训练中尤其重要,因为它可以为PPO等算法提供密集的反馈,避免奖励稀疏导致的训练不稳定。
下面是一个简单的过程奖励模型示例,它使用一个编码器获取当前步骤的表示,并通过线性层输出分数。实际系统中编码器通常与策略模型共享部分参数。
import torch
import torch.nn as nn
class ProcessRewardModel(nn.Module):
def __init__(self, hidden_size):
super().__init__()
self.encoder = nn.LSTM(hidden_size, hidden_size, batch_first=True)
self.score_head = nn.Linear(hidden_size, 1)
def forward(self, step_hidden_states):
# step_hidden_states: (batch, seq_len, hidden_size)
lstm_out, _ = self.encoder(step_hidden_states)
# 取最后一个时间步作为该步骤的表示
step_repr = lstm_out[:, -1, :]
score = torch.sigmoid(self.score_head(step_repr))
return score
工程实现中的三种中间监督方案
方案一是在推理阶段使用PRM进行步骤筛选或加权。生成一条完整链后,用PRM对每个步骤打分,将分数低于阈值的步骤视为断点,触发重新生成或回溯搜索。这种方式不改变模型训练,但推理成本会上升,因为需要额外的前向计算和可能的多次采样。它的优势是灵活,可以快速在已有模型上验证中间监督的价值。
方案二是在监督微调数据中引入步骤级标签。构建数据时,除了最终答案,还要求标注每个中间步骤是否正确。训练时,损失函数被拆成两部分:一部分是最终答案的交叉熵损失,另一部分是每个中间步骤的二元分类损失或加权生成损失。这样模型在生成每个步骤时都会收到“这一步对不对”的梯度信号。这种方法的难点在于标注成本较高,但可以通过自动标注或规则校验来降低。
方案三是把过程奖励模型集成到强化学习流程中。在PPO训练时,每个时间步的奖励由PRM给出,而不是只在序列末尾给一个整体奖励。训练策略模型时,每个生成的token都会根据其所在步骤的PRM分数获得奖励,从而鼓励模型生成每一步都经过验证的推理链。下面这段伪代码展示了如何把步骤奖励叠加到token奖励上。
def compute_dense_rewards(generated_ids, prm_model, tokenizer):
rewards = []
step_boundaries = detect_step_boundaries(generated_ids, tokenizer)
current_step_start = 0
for boundary in step_boundaries:
step_ids = generated_ids[current_step_start:boundary]
# 获取该步骤隐状态并送入PRM
hidden = get_hidden_states(step_ids)
step_score = prm_model(hidden).item()
# 将该步骤分数分配给步骤内所有token
for _ in step_ids:
rewards.append(step_score)
current_step_start = boundary
return rewards
每步验证带来的收益与需要注意的代价
实验层面,加入中间监督后,模型在多跳问答、数学推理和逻辑推理任务上的长链准确率通常会有明显提升。原因是错误在早期步骤被拦截后,后续步骤不会在错误前提上继续堆积。一个典型的对比是,在同一个基座模型上,使用结果监督时模型在8步推理任务上的平均错误步数为2.3,而使用过程监督后降至1.1,最终答案准确率相应提高。虽然具体数值会因任务和标注质量变化,但趋势一致。
不过中间监督并不是零成本方案。首先,过程奖励模型本身需要大量人工标注或自动构造的步骤级数据,标注质量直接影响效果。如果自动标注的步骤标签存在噪声,模型可能学到错误的分步标准。其次,推理时的步骤验证增加了计算量,尤其是在使用回溯搜索时,延迟会成倍增加。最后,步骤粒度的选择很关键:粒度太粗,验证信号仍然稀疏;粒度太细,例如对每个token都验证,会引入过多噪声并加重标注负担。通常以自然语言句子或推理步骤为边界比较合适。
总体来看,多跳推理链断裂问题的根源在于模型缺少对中间状态的显式校验机制。中间监督通过对每一步施加验证信号,使模型在生成过程中具备自我检查和修正能力。针对不同场景,可以根据标注预算和推理延迟要求,选择训练过程奖励模型、微调步骤级标签或强化学习密集奖励等方案。随着推理模型在复杂任务中的应用越来越广,这种从最终结果监督向过程监督的转变,是提升推理可靠性的关键方向之一。

