07.1.7|OPD 的工程实现:轨迹、对齐、缓存与评测
返回 OPD 专题导读 · 前置:分布、目标与梯度 · 方法比较:MiniLLM 与 GKD
训练能正常反传,仍可能在学习错误的位置。例如把回答的第一个 token 与第二个 token 的教师分布比较,损失可以下降;把补齐用的 PAD 当成终止符,模型也可能越来越喜欢提前结束。OPD 的工程核心,是把“学生在自己经过的位置接受反馈”落实为版本明确、前缀一致、位置对齐的一批张量。
本篇沿一批数据走完生成、评分、损失、缓存和评测。论文事实依据 GKD §3.1、MiniLLM §2 和 X-OPD §3—4;为连接这些事实而提出的张量接口、诊断顺序和评测设计,均为本站工程建议。代码是教学伪代码;实际执行的只有第三、四章的有限枚举验算,没有运行训练框架或复现模型基准。
1. 一批轨迹的版本与身份

图 1|生成版本、评分参数与更新顺序(教学示意)
图中蓝色的 先产生回答,右侧绿色的 是更新后的参数。两者之间的 token IDs 是固定数据;它们来自哪个参数版本,不会随优化器调用自动改变。GKD 对学生采样分布停止反传,仍对学生在已抽到前缀上的评分求梯度。因而,在实现中把生成放进 no_grad,只解决了采样不保留计算图这一部分;不能把随后的学生评分也包进同一段 no_grad。来源:GKD §3.1、Algorithm 1。
一个可排查的教学批次至少保留 prompt_id、rollout_policy_version、生成的 token IDs、真实回答长度和终止原因。涉及概率比时,再保留算法所需的旧策略对数概率及其定义。保存解码后的字符串仍不充分:重新编码可能改变空格、特殊 token 或聊天模板,评分就不再对应原来的离散轨迹。
图中从更新参数往左看的红箭头,也说明“新旧”必须落到具体对象。复用旧轨迹、复用旧概率和复用旧 KV 缓存是三件事。旧轨迹可以作为明确的离线数据;能否在所选 OPD 更新中多次复用、需要什么校正,应由目标决定。GKD 没有因此自动变成带概率比的算法;MiniLLM 的 teacher-mixed sampling 则显式改变行为分布,并讨论了精确重要性权重的高方差与实际近似。不能往所有 rollout 训练里加同一个 ratio,就称作通用修复。来源:MiniLLM §2.2。
还有一个容易藏在配置里的身份变化:温度、top-k、top-p 等采样变换会改变行为分布。若某目标使用 ,分子分母必须使用该目标约定的相同条件和分布定义;原始 softmax 概率与截断后采样概率不能只因数组长度相同就混用。这里是工程约束分析,不能据此推断 X-OPD 官方代码采用了哪一种具体概率实现。
2. 同一前缀的两路评分

图 2|复制的是学生轨迹,教师重新评分(原创教学图)
图中红圆和黄三角是已经生成的历史,绿色方块是当前候选 token。蓝色学生评分与紫色教师评分都站在这同一个位置。右下角另写的答案从第二格开始不同,即使两条回答长度相等,第 格也不再代表相同历史。OPD 所需的是教师读取学生的前缀;不必让教师重新生成一份答案再逐格相减。
在固定输出位置 ,用 表示学生已经生成的历史,用 表示共同输出词表中的候选 token。文本场景中两路可以同读输入 ;X-OPD 则让语音学生读音频 、文本教师读语义对应的文字 :
均为长度 的概率向量, 为输出词表大小;它们的输入模态可以不同,输出坐标必须有对应关系。X-OPD 的共同比较空间是文本输出,不是音频帧或音频码本。来源:X-OPD §3.1—3.3。
把这个条件落实到接口,可以要求评分模块返回 [B,L,V]: 为回答条数, 为对齐后的回答位置数。教师 prompt 比学生多几个 token,或者音频输入展开成另一种长度,都不意味着可以直接取两个原始 logits 张量的同一行。应分别按各自 prompt 长度,提取“预测第 个回答 token”的行,再组成共同的回答位置轴。
词表也有同样的问题。教师的 token ID 42 可能与学生的 ID 42 对应不同字符串;即使两者都能解码出同一完整答案,也不代表逐 token 的分解相同。跨 tokenizer 的两个概率数组不能直接按下标计算 KL。 本篇伪代码限定共同输出 tokenizer 与词表坐标。跨词表蒸馏需要额外的对齐方法,不能只用 padding 把两条向量补到同长。
3. 回答位置、EOS 与归一化
3.1 当前输入行预测下一格

图 3|预测 a 的 logits 位于最后一个 prompt token 那一行
沿图 3 从上往下读。输入为 [x₀,x₁,a,b,EOS,PAD,PAD],前两格是 prompt。第 1 行索引处已经看完 x₀,x₁,它的 logits 预测 a;下一行预测 b,再下一行预测 EOS。若对 logits 做 [:, :-1],目标做 [:, 1:],监督回答的 mask 就是 [0,1,1,1,0,0]。
最下面的 attention mask 是 [1,1,1,1,1,0,0]。它决定哪些输入格属于有效上下文,不能直接拿来当回答损失 mask。两者混用,会把 prompt 的预测也纳入目标,或者错过最后一个 prompt token 对第一个回答 token 的预测。
EOS 还要按终止元数据判断。若真实生成到 EOS,这个终止决策可以是有效回答目标;若达到最大生成长度后被截断,不应凭空增加一个“模型选择了 EOS”的监督位置。如果 tokenizer 共用 EOS 与 PAD 的 ID,仅以 token_id != pad_id 构造 mask 会误删真实 EOS。图中用不同名称区分两种角色,实际代码应保留真实长度,而不只比较整数 ID。
给这六个预测位置设置教学损失 [9,0.1,0.2,0.6,8,7],有效三格的均值为:
把 prompt 与 padding 上的大数故意放大,可以快速检查它们是否泄入平均值。不过,实际 logits 若产生 NaN 或无穷值,事后乘零并不可靠,因为 仍是 NaN;应先确保评分行有效,并在正确的位置选择和归约。
3.2 平均的单位也是目标的一部分

图 4|回答内部平均与回答之间平均(原创教学图)
图 3 中三个绿色位置先合成一条回答的损失。对变长 batch,下一步可以等权平均回答,也可以把所有有效 token 一起平均,两者给长回答的权重不同。GKD 的序列差异先按长度平均;X-OPD §3.4 也保留先轨迹内平均、再轨迹间平均的结构。GKD Eq. (2),X-OPD §3.4。
用两条教学回答检查:A 的有效损失为 [0.1,0.3],B 为 [0.9]。等回答平均得到 ;合并 token 后为 。它们都可以计算,但已经在优化不同的加权目标。有关两层平均的视觉推导,可接着读 X-OPD 的轨迹归一化。
4. 完整词表与采样信号
4.1 一个负的采样值不等于负的 KL

图 5|同一前缀下,完整分布与采样值是不同对象
图 5 左侧教师概率为 ,学生为 ,三个位置对应 token 。两组概率均严格为正,以下使用自然对数;数值没有物理单位。前向与反向 KL 分别为:
两者都非负,但某个 token 的对数比可以是负数。学生这次若采到 ,观测到 。这个值是一份采样信号,不是该前缀上完整词表求和得到的 KL。 在固定前缀下,按 对全部可能采样求期望,才得到上面的反向 KL 数值;不能把一次采样值与完整 KL 的非负性作直接比较。
4.2 数值估计相同,不代表直接反传相同
图 5 右侧三个箭头也可以用来检查梯度。令学生由 logits 经 softmax 得到,教师固定;对完整反向 KL,有:
遍历三个候选 token; 是第 个无单位 logit。代入后,梯度为 ,三项之和为零。若只把抽到 token 的 logp-logq 直接当可微损失,求得的是另一个梯度;固定前缀下,未加系数的 按 的期望甚至为零。
在这个固定前缀、固定教师的教学问题里,一种匹配完整反向 KL 梯度的采样估计器是:
stopgrad 使括号内的对数比只作为系数,不再从那里额外反传。对 的三种可能分别算梯度,再按 加权,可回到上面的完整梯度。这只是单个固定前缀的等价性;序列中前缀本身的分布还会随策略改变。MiniLLM 的序列反向 KL 推导包含未来回报和方差控制,不能以这里的单步公式代替。来源:MiniLLM §2.1—2.2、Eq. (1)—(4)。
教学验算使用 Python 3.12.14 枚举三种 token,并以步长 做中心差分,解析梯度与差分的最大绝对误差为 ;采样估计器的枚举期望也相符。该检查验证上面的教学计算,不证明任何训练系统的实现正确。
kxzxvbk 的中文解读从采样 token 的 reverse-KL 写法走向完整词表,是理解图 5 的另一条入口。实际看实现时要分三层:这次抽到的 log-prob 差、按采样分布取期望的数值目标、以及由自动微分或策略梯度估计得到的更新。第二层数值表达相同,不说明第三层可以随意把采样值直接反传。上面的停止梯度系数和三候选枚举,正是检查这一点。
中文介绍偶尔把该差值口语称作“logit 距离”。此处比较的是同一条件下归一化概率的对数;原始 logits、log-probability 与完整词表 KL 应在接口中明确区分。文章同时提到 tokenizer 难点:自蒸馏通常容易满足共同词表,却仍需处理额外教师 prompt、学生原轨迹与回答位置偏移,不能省掉图 2、图 3 的对齐检查。
| 材料中的简写 | 本篇对应对象 | 实现时补什么条件 |
|---|---|---|
| token 级蒸馏信号 | 图 5 的采样值或完整词表分布 | 明确支持集、期望和梯度估计器 |
| 教师给出更好答案 | 原前缀评分,或独立教师生成 | 先确定是哪条流程;不能只按两条回答的序号相减 |
| 自蒸馏解决词表问题 | 同模型往往共用输出坐标 | 仍核对 prompt 长度、mask、模型版本和教师额外条件 |
4.3 一段职责明确的教学主干

来源:GKD Algorithm 1(截图裁切,CC BY 4.0)
原算法把“取得本批数据”与“计算差异梯度”分成两个阶段;图 2 确定两阶段的数据流,图 3 确定回答位置,图 5 确定完整词表损失。把三者连接起来,可得到下面的 GKD 风格固定轨迹、完整词表前向 KL 教学伪代码。它没有实现原图的数据混合分支、MiniLLM 的序列策略梯度或 X-OPD 的双路代理目标,不能直接作为这些论文的复现代码。
# common output tokenizer; response axis is already position-aligned
with no_grad():
rollout = sample(snapshot(student), prompts, generation_config)
batch = pack(prompts, rollout.token_ids, rollout.true_lengths)
# Return aligned [B, L, V] log-probabilities, not raw input-row logits.
with no_grad():
logq = score_response(teacher, batch.teacher_inputs, logprob_dtype="float32")
logp = score_response(student, batch.student_inputs, logprob_dtype="float32")
mask = batch.response_loss_mask # [B, L], including real EOS
assert every_sequence_has_target(mask)
assert same_output_coordinates(logq, logp)
assert finite_on_valid_positions(logq, logp, mask)
per_token = (exp(logq) * (logq - logp)).sum(axis=-1)
per_sequence = masked_sum(per_token, mask) / mask.sum(axis=-1)
loss = per_sequence.mean()
optimizer.zero_grad()
loss.backward() # teacher detached; student score differentiable
optimizer.step()
score_response 要负责模型各自的 prompt 偏移与下一 token 错位;logprob_dtype 指定计算 log-softmax 时的精度,不能先在低精度下 softmax、取对数后再转 float32,就视为等价;masked_sum 表示选择有效项后求和,不能依赖零乘 NaN。这些辅助步骤都属于主计算。首个诊断样本宜只有一个 prompt 和一条短回答,逐行打印 (response_index, target_token_id, student_row, teacher_row, mask),人工确认后再扩大 batch。教师 eval 模式与教师停止梯度也各有职责:前者通常关闭 dropout 等训练行为,后者切断自动微分;二者不能互相替代。比较固定输入下的 logits 时,应先让相关随机行为、精度和评分配置一致。
5. 语音与文本配对的语义边界

图 6|少一个否定词,两路输入可能要求相反的动作
图中音频说“不要关灯”,上方文本保留否定词,下方转写丢掉“不”。灯的亮暗只是两种指令含义的示意,没有展示模型执行动作或实验结果。若把下方文本交给教师,它更偏向“关灯”相关输出,分数差就不再只表示学生的语音理解能力弱,也包含教师正在回答另一个问题。
X-OPD 实验使用口语化文本、TTS 合成语音与 ASR 回转写过滤,丢弃 WER 大于 5% 的样本。这个阈值是论文的数据流程,不能自动变成全部真实录音任务的通用标准。整体错误率较低时,一个否定词、数量、实体或单位仍可能改变答案。来源:X-OPD §4.1。
本站建议为配对样本保留原始问题、口语改写、音频来源、回转写文本、过滤原因及同源分组 ID。遇到跨模态分数差突然变大,先抽查这些字段是否指向同一语义。文本题“把 15 改成 50”被合成成另一个数字,或者问句在截音后失去条件,都可能让优化器忠实地学习错误的对应关系。这里需要修数据身份,而不是先增大 KL 权重。
音频输入的 padding 长度、采样率与实际有效帧,也应来自预处理约定。X-OPD 报告的 24 kHz 合成条件不能说明任意模型可直接接收 24 kHz 波形。训练前将一条样本的音频时长、重采样结果、有效帧数与对应文本一起读出,比只检查文本端 batch shape 更容易发现截断或单位错误。更完整的模态路径与实验边界见 X-OPD:语音 LLM 的跨模态能力对齐。
上下文与经验内化的共同模板还提醒防止特权信息泄漏。对本篇的批次而言,额外材料应有明确身份:学生生成时用什么、教师重评时多读什么、评测时又移除了什么。若把参考答案同时塞入学生 rollout,训练访问的条件已经改变;随后去掉材料,不能再只凭“同一个模型”认为差异自动消失。SDFT 所观察的引用“上文”风格残留,就是需要另外检查的现象之一。
6. 缓存、显存与计时边界

图 7|缓存对应模型、条件、位置与前缀的共同身份
图 7 上方教师权重固定,同一输入前缀的 KV 才具备复用前提;仍需保证 attention mask、位置编码、模态条件和精度等配置相符。下方学生已经更新,旧 KV 是用 计算的,不能仅因为 token 字符串相同,就当作 的缓存。对有模态条件的模型,两个不同录音共享一份转写,也不能据此共享全部音频条件缓存。
这是缓存正确性的工程推论,不是对某个框架性能的测量。相同固定输入下,先分别跑“全量评分”和“缓存评分”,比较有效位置的 logits 或 log-probability;报告绝对误差、容差、精度和缓存边界。两次独立随机生成的文本相似,无法证明缓存等价;文本不同,也可能只是采样随机性。
完整词表监督的存储量可以先做量纲检查。一个 [B,L,V] 的 float32 张量需 字节。取教学配置 ,单个张量为 字节,约 GiB;这还不包含另一侧 logits、激活、梯度和优化器状态。分块计算词表求和、按回答长度分桶等是可研究的工程方案;只保留 teacher top-k 则会改变可获得的分布信息,不能默认与完整 KL 精确等价。
计时也要沿图 1 分开:rollout、自回归生成之外的教师评分、学生前向反向、优化器与数据传输,分别记录后再报端到端训练步耗时。若生成后的一整条学生轨迹已经确定,教师可以按因果 mask 对它做并行的 teacher-forced 评分;这减少了再生成答案的需要,并不消除教师前向计算或完整词表输出的成本。
语音服务还存在另一条计时路径:音频接收与预处理、首个文本 token、完整回答,以及若有语音输出时的声学生成。训练更快、教师打分更少、文本质量更好,均不能直接推出用户听到回答更早。本文没有测量这些延迟;比较速度时应固定硬件、batch、长度、精度、预热和计时起止点。
7. 独立评测与故障定位

图 8|先定义独立样本,再切训练与测试
图 8 左侧的问题在于,同一个问题的文字版进入训练,合成语音版进入测试;模型可能已经记住答案。右侧把一个来源的全部视图放在同一侧。具体按原始问题、说话人、录音会话还是数据来源分组,取决于要验证的问题:要验证没见过的说话人,就不能只按问题文本分组。这是建议的评测设计,不能写成 X-OPD 论文已经完成的全部对照。
对语音输入、文本输出的 OPD,建议在同一组独立问题上分别测语音输入表现和文本输入表现,保留各自原始指标,再看二者差距。文本能力下降、语音能力上升,与两路一起上升,是不同结果。合成干净语音、真实录音、噪声与口音也应按条件报告;不将一个条件下的结果直接外推到全部场景。
故障定位可以从最靠近数据的证据向目标推进:
| 观察到的现象 | 先比较的具体对象 | 这一步能排查什么 |
|---|---|---|
| loss 在下降,回答却爱提前结束 | 真实 EOS、PAD 的长度与 mask;生成终止原因 | 错把补齐位置当成终止监督,或遗漏真实 EOS。 |
| 更新前 ratio 已明显偏离 1 | 同一 token 的旧、新 log-probability 定义;采样配置与模型版本 | 版本、温度、截断或条件混用;若评分随机,先固定随机行为。 |
| batch size 改变后目标数值异常 | 同一批固定样本的逐序列损失与有效 token 数 | sum/mean 位置改变,或长回答获得额外权重。 |
| 只有语音侧异常 | 图 6 的原音频、改写、回转写、时长与文本教师输入 | 错配、截音、否定词或数字改变;不能只根据该现象断定音频塔损坏。 |
| 单 token “KL” 为负 | 图 5 的完整词表 KL 与采样 log-ratio 分别输出 | 记录项命名混淆;负采样值本身不证明实现错误。 |
| 缓存版与全量版的固定输入评分不同 | 图 7 中权重、位置、mask 与模态条件身份 | 缓存失效或评分配置不一致。 |
每个修复先回到一条固定短轨迹,再扩大到变长 batch 和独立评测。有限枚举检查能证明某个公式或归约写对了;小样本 loss 能下降,只能说明系统可以拟合这些样本。能力、泛化和用户延迟仍分别需要对应测量。
本文的三条论文来源分别是 GKD v3(2024-01-17)、MiniLLM v6(2026-01-31) 与 X-OPD v3(2026-06-12)。本文采用上述论文的方法与指定实验范围,未验证官方框架实现。继续阅读 MiniLLM 的序列目标与未来回报,可以看到为何单步数值一致仍不足以确定整套训练算法;返回 专题导读 可按目标选择后续分支。
正在连接 GitHub 评论…