GLM Post-Training Beyond SFT
导言
部门要突破 GLM 模型的 NPU 原生训练,真正困难的不是把一个 GRPO loss 搬到 NPU,而是让 Actor 训练、推理 Rollout、Teacher Prefill、Verifier、权重同步和低精度数值形成闭环。
本文以 GLM-5 技术报告为主线,并补充 GLM-5.2 已公开的 SAO、CompactionRL 和十多个专家的并行 OPD。重点解释非 SFT 后训练中的 RL、OPD/MOPD,同时单独澄清 QAT 与量化:GLM-5 明确把 INT4 QAT 放在 SFT 阶段,它对 NPU 后训练很重要,但不是非 SFT RL 的一个阶段。
先给结论:什么才是 NPU 原生¶
截至 2026 年 8 月,GLM-5 有完整技术报告;更新的 GLM-5.2 有官方博客,并由 SAO 与 CompactionRL 两篇论文补充后训练方法,但还没有一份同等完整的新技术报告。公开证据可以还原出下面这条演化线:
- GLM-5:SFT 之后依次执行 Reasoning RL、Agentic RL、General RL,最后用 Cross-Stage OPD 合并各阶段能力。1
- GLM-5.2:继续用 slime 承载更大规模、更复杂的 Agentic RL;官方披露并行 OPD 合并了十多个专家模型,整个 OPD 约两天完成。2
- GLM-5.2 的方法补充:SAO 用单轨迹异步优化消除组采样屏障;CompactionRL 把上下文摘要变成可训练动作,两篇论文都称方法用于 GLM-5.2 的 RL pipeline。34
这意味着“原生”至少有三层含义:
- 算子原生:Attention、DSA Top-k、MoE、log-softmax、fake quant、collective 等核心算子运行在 NPU 上。
- 框架原生:训练、rollout、teacher、reward、权重同步不依赖 GPU 侧的隐藏补丁或中转。
- 数值闭环原生:同一 token、同一前缀、同一量化规则下,训练策略、rollout 策略和教师策略的概率可比较;偏差能被观测、校正和回归测试。
第三层才是 RL/OPD 是否真的成立的分界线。如果 NPU rollout 重新分词、DSA 选中了另一组 token、低精度 GEMM 改变了采样分布,训练端即使成功反向传播,也是在优化另一个行为策略。
本文的范围
本文先解释为什么这些方法成立、优化了什么对象、可能在哪里失效。它不是 GLM-5.2 NPU 复现手册,也不把论文方法公开等同于官方训练 recipe 已经开源。
一条统一主线¶
后面的算法名称很多,但都可以放回四个问题:
| 问题 | 典型对象 | 方法如何回答 |
|---|---|---|
| 状态从哪里来 | prompt、学生 trajectory、环境 observation、compacted history | RL/OPD 都尽量在当前学生会访问的状态上学习 |
| 信号从哪里来 | rule reward、ORM、LLM judge、Critic value、teacher log-prob | GRPO 用组内奖励;PPO/SAO 用 Critic;OPD 用教师逐 token 信号 |
| 策略是否可比较 | π_train、π_rollout、π_old、π_teacher |
IcePop/DIS 约束概率比;TITO 保存 exact token ID |
| 数值是否一致 | Top-k index、BF16/FP8/INT4、scale、zero-point、KV Cache | 确定性 Top-k、bitwise-identical quant kernel、精度分层 |
在传统的同步 RL 中,一批 prompt 先完成 rollout,再一起打分和更新。到了长程 Agent 任务,不同 trajectory 的长度可能相差几个数量级,最慢样本会让整批等待;一旦训练与推理解耦,吞吐变高,却又出现 policy lag:生成样本时的策略已经落后于当前训练策略。
因此 GLM 的核心矛盾不是“同步还是异步”二选一,而是:
允许系统异步前进,同时只让仍然可信的 token 产生梯度。
GLM-5 报告的原始训练流程图如下。它支持“多阶段后训练 + 最终 OPD”这一流程关系,但不能单独证明其中某一组件带来多少收益。
四层一致性:从状态到梯度¶
IcePop、Token-In-Token-Out(TITO)、Direct Double-Sided Importance Sampling(DIS)和 DSA Indexer 并不是四个互相替代的优化器。它们共同回答一个更基础的问题:训练端反向传播的动作,是否真的是 Rollout 端在同一状态下执行的动作。
可以沿着一条 token 的因果链理解四者:DSA 决定模型看见什么,TITO 固定模型做了什么,IcePop 判断同一组权重在训推引擎中是否表达同一策略,DIS 判断异步旧行为对当前策略是否仍可用。
| 层次 | 被固定或比较的对象 | 防止的错位 | 失败后的直接后果 |
|---|---|---|---|
| DSA Indexer:状态一致性 | 被选中的历史位置集合 \(\mathcal I_t\) | 训练与 Rollout 关注不同的 key/value | 同一 token 前缀产生不同 hidden state 和 logits |
| TITO:动作一致性 | exact token ID \(a_t\) 与 action/observation 边界 | 文本往返后重新分词得到另一个动作 | 训练概率指向的不是实际采样事件 |
| IcePop:实现一致性 | 同权重下 train 与 infer 的 token 概率 |
kernel、精度、Top-k、KV 等训推数值路径不同 | mismatch token 被当成可信 on-policy 数据 |
| DIS:版本一致性 | 当前策略与实际 Rollout 行为策略的概率 | 异步轨迹完成时策略已经更新多次 | 过旧行为产生高方差或错误方向的梯度 |
概念、机制与 GLM 实现¶
这四个名字需要分三层理解,避免把一般原则与 GLM 的具体补丁混在一起:
| 方法 | 一般概念 | 可复用机制 | GLM-5 公开实现 |
|---|---|---|---|
| TITO | RL 的动作事实是 token ID,不是解码文本 | Rollout 传 exact IDs、mask、log-prob 和版本元数据 | TITO Gateway 拦截生成请求并记录 token IDs 与 metadata |
| DSA Indexer | 稀疏模型的状态还取决于离散路由结果 | 让训练与 Rollout 重放或确定性重算 Top-k index | 训练端使用确定性 torch.topk,\(k=2048\),RL 默认冻结 Indexer |
| IcePop | 同参数的两个引擎也可能实现不同分布 | 用同权重训推概率比筛掉实现 mismatch 过大的 token | \(\beta=2\);GLM-5 版本移除了原 IcePop 的 KL 正则项 |
| DIS | 异步队列中的行为策略会落后于当前策略 | 保存 Rollout log-prob,直接构造双边 token ratio | 不维护大量历史策略;再用 policy version 丢弃整条过旧轨迹 |
这组机制并不“修好”底层差异。DSA 的确定性 Top-k 和 TITO 尽量消除差异来源;IcePop 与 DIS 则是证据准入门,在仍有差异时拒绝不可信 token。若 mask 比例持续升高,训练可能表面稳定但有效样本率不断下降,因此必须同时监控 trusted_tokens / action_tokens。
关键对象¶
一条可训练 trajectory 至少要能把下面这些物理对象重新对齐:
| 对象 | 生产者 | 形态 | 消费者与生命周期 |
|---|---|---|---|
response_token_ids |
Rollout engine | [T] 整数 token ID |
Actor 重算概率;随 trajectory record 保留到更新完成 |
topk_indices[t] |
DSA Indexer + Top-k | [k] 历史位置,GLM-5 中 \(k=2048\) |
Sparse Attention 当前 token 使用;GLM-5 训练方案选择确定性重算而非全量跨进程保存 |
rollout_log_probs |
Rollout forward | [T] 浮点数 |
IcePop/DIS 构造 ratio;是行为策略凭证 |
response_mask / observation_mask |
TITO Gateway 或 trajectory builder | [T] 布尔值 |
policy loss 只保留模型动作;工具和环境 token 不产生梯度 |
policy_versions |
权重同步与 Rollout engine | 每段或每条轨迹的版本序列 | trajectory-level staleness filter 判断整条样本是否过旧 |
trust_mask |
IcePop 或 DIS | [T] 布尔值 |
policy loss 的最后准入条件;完成本次 backward 后释放 |
其中 sampling_config、tokenizer_revision 和显式 observation_mask 是本文建议 NPU 系统纳入的可重放字段;GLM-5 报告只公开到“token IDs 与 metadata”,没有披露完整字段 schema。
Reasoning RL:相对奖励与可信 token¶
GRPO 在优化什么¶
给定一个 prompt \(x\),策略为它采样一组 \(G\) 个回答 \(y_1,\ldots,y_G\),并得到序列级奖励 \(R_1,\ldots,R_G\)。GRPO 不训练 Critic,而是用组内均值和标准差构造相对优势:
直觉上,同一个题目中比同伴更好的回答获得正优势,更差的回答获得负优势。它消除了跨题难度尺度差异:一道所有回答都失败的难题,不会仅因为奖励绝对值低就主导梯度。
若 \(r_{i,t}(\theta)=\pi_\theta(y_{i,t}\mid s_{i,t})/\pi_{\mathrm{old}}(y_{i,t}\mid s_{i,t})\),常见 clipped objective 是:
其中 \(s_{i,t}=(x,y_{i,<t})\) 是第 \(t\) 个 token 的状态。奖励是序列级的,概率比和梯度却是 token 级的。因此,一个回答只要通过验证,其中每个生成 token 默认共享同一个方向,真正的 token 级差异来自概率比与 mask。
GLM-5 的 Reasoning RL 使用 GRPO + IcePop,组大小和 batch size 均为 32,训练数据混合数学、科学、代码和 Tool-Integrated Reasoning,并主要使用可验证的二值结果奖励。1
IcePop 为什么有两层 ratio¶
RL 解耦训练和推理后,至少存在两种偏差:
- 训练更新偏差:当前参数 \(\theta\) 相对旧训练策略 \(\theta_{\mathrm{old}}\) 改了多少,对应 PPO ratio \(r_t\)。
- 训推实现偏差:在相同旧参数 \(\theta_{\mathrm{old}}\) 下,训练引擎重算的概率与 Rollout 引擎实际生成概率差了多少,对应 mismatch ratio
第一类 ratio 回答“参数更新走了多远”,第二类 ratio 回答“两个引擎是否还在表达同一个策略”。把二者混成一个 ratio,会让优化步长和系统数值误差失去各自的诊断指标。
例如 Rollout 引擎给实际 token 的概率是 0.10,同权重训练引擎重算得到 0.35,则 \(\rho_t=3.5\)。这不是普通的 PPO 更新过大,而是两个执行路径对同一个离散动作意见不同。原因可能是 BF16/FP8 精度、DSA Top-k、位置编码、KV Cache、并行 vocabulary reduction 或权重切换时机不同。
IcePop 的核心不是把离群 ratio 裁到边界,而是将超出可信区间的 token 直接移出梯度。GLM-5 报告给出的 mismatch 阈值为 \(\beta=2\),即保留 \(\rho_t\in[1/2,2]\);PPO 的上下裁剪为 \(\epsilon_l=0.2,\epsilon_h=0.28\)。1
当 \(\beta=2\) 时,1.2 和 1.9 会被保留,0.3 和 3.5 会被屏蔽。这里是 mask,不是 clamp:clamp 会把 3.5 改写成一个仍参与训练的边界值,mask 则承认这条证据无法可靠归因。最终把 \(m_t\) 乘到 token loss 上;当两个引擎意见相差太大时,继续反向传播比丢掉样本更危险。
# Rollout / forward path
for prompt in batch:
responses, infer_logp, exact_ids = rollout_policy.sample(prompt, group=32)
rewards = verifier(responses)
group_adv = normalize_within_prompt(rewards)
# Train / backward path
old_train_logp = old_actor.logprob(exact_ids)
train_logp = actor.logprob(exact_ids)
mismatch = exp(old_train_logp - infer_logp)
trust_mask = (1 / beta <= mismatch <= beta)
ppo_ratio = exp(train_logp - old_train_logp)
loss = masked_clipped_policy_loss(ppo_ratio, group_adv, trust_mask)
loss.backward()
optimizer.step()
数据形态与所有权:exact_ids、infer_logp、reward、policy version 属于 Rollout record;old_train_logp 由同权重旧训练策略重算,train_logp 和训练激活属于当前 Actor worker;group advantage 由 trainer 生成。Rollout 激活不应跨阶段保存,只有可重放的 token 与最小概率元数据进入训练队列。
DSA Indexer 的确定性为什么是 RL 问题¶
GLM-5 使用 DSA indexer 为每个 query 选择 Top-2048 key。报告指出,直接存下所有 replay index 成本太高,因此训练侧重算 Top-k;而非确定性的 CUDA/TileLang Top-k 曾导致 RL 明显退化和熵坍缩,最终训练使用确定性的 torch.topk,并默认冻结 indexer。1
Indexer 不是最终 Attention 权重,而是正式稀疏 Attention 之前的候选历史位置选择器。对第 \(t\) 个 token,Indexer 根据当前 query \(q_t\) 和历史 key 表示 \(K_{<t}\) 产生长度为 \(L_t\) 的相关性分数,再返回 \(k\) 个位置:
其中 \(L_t\) 是当前可访问的历史长度,\(k\) 是稀疏预算,\(H_i\) 是 Indexer 特征宽度。若 query head width 为 \(H_q\),选中 key/value 的宽度分别为 \(H_k,H_v\),则正式 Attention 只读取 \(K_{\mathcal I_t}\in\mathbb R^{k\times H_k}\) 和 \(V_{\mathcal I_t}\in\mathbb R^{k\times H_v}\)。因此 \(\mathcal I_t\) 是一个离散控制对象:边界附近一个位置的排名发生交换,可能让某段错误日志被看见、另一段修复要求完全不可见。这与连续 tensor 出现 1e-3 误差不同,是模型状态的离散跳变。
query_t = current_query(hidden_t) # [H_q]
historical_key_features = index_features(key_cache) # [L_t, H_i]
index_scores = indexer(query_t, historical_key_features) # [L_t]
topk_indices = deterministic_topk(index_scores, k=2048) # [2048]
selected_keys = gather(key_cache, topk_indices) # [2048, H_k]
selected_values = gather(value_cache, topk_indices) # [2048, H_v]
attention_scores = matmul(query_t, transpose(selected_keys)) * scale
attention_probs = softmax(apply_mask(attention_scores))
context_t = matmul(attention_probs, selected_values)
attention_output_t = attention_output_projection(context_t) # [H_model]
hidden_after_dsa = residual_update(hidden_t, attention_output_t)
logits_t = downstream_layers_and_lm_head(hidden_after_dsa) # [V]
上面是语义展开,不声称 GLM kernel 会逐个物化所有中间 tensor。需要追踪的物理边界是:Indexer score 的生产者、Top-k 的归并与 tie 规则、gather 后 KV 的布局,以及最终 token log-prob。
这件事很容易被误认为普通算子精度问题。实际上,如果训练与 rollout 选择了不同的稀疏注意力集合,即便参数相同,二者也实现了不同的策略:
假设位置 1024 是错误日志、位置 8096 是修复要求,而位置 7731 的 Indexer 分数与 8096 几乎相同。Rollout 端选择 {1024, 8096},训练端因低精度舍入或跨卡归并顺序选择 {1024, 7731};训练端即使使用同一 token 前缀,也已不再重放 Rollout 的状态。
因此 NPU 迁移不能只验证 index_scores 的平均误差,还要逐级检查:
- 集合一致性:Top-k 选中了哪些位置;
- 顺序一致性:同一集合的排列是否会影响后续 gather 或 kernel;
- 边界稳定性:tie、NaN、正负零、index dtype 和跨卡归并规则;
- 概率一致性:最终 sampled-token log-prob 的差异,而不只看 Indexer;
- 行为一致性:固定随机数和采样配置后,最终 token 是否相同。
阅读这张五联图时,应依次看:物理视图中的稀疏位置选择、因果视图中的 Top-k 偏差传播、流程视图中的重算与 mask、时序视图中的 Rollout/Trainer 所有权,以及数据视图中 indices → logits → log-prob 的路径。它解释一致性机制,不提供某个 NPU kernel 的性能收益数字。
迁移到 NPU 时
Top-k 只要“集合大致相同”仍不够。相同分数、边界 tie、排序稳定性、NaN 处理和 index dtype 都可能改变选中集合。需要比较 index 集合、顺序、最终 log-prob 与采样结果,而不仅是 kernel 输出的平均误差。
Agentic RL:异步之后先处理策略滞后¶
Agentic RL 的 rollout 不再是一段纯文本,而是交替出现模型动作与环境观察:
其中 observation 由编译器、终端、搜索引擎或浏览器产生,模型不对 observation token 负责。长程 coding/search 让不同 trajectory 的耗时非常不均匀,GLM-5 因此将训练和 rollout 完全解耦,并使用中央 Multi-Task Rollout Orchestrator 调度。1
TITO:token ID 是动作事实¶
TITO 是 Token-In-Token-Out。若 Rollout 先输出文本,训练端再 tokenize,空格、特殊 token、工具协议或 tokenizer 版本的差异会让训练动作与真实动作不一致。TITO 保留 Rollout 引擎产生的 exact token IDs,使训练端在实际被采样的离散动作上重算概率。
这不只是避免工程 bug。策略梯度中的动作 \(a_t\) 就是 token ID;一旦 ID 改了,公式中的 \(\pi(a_t\mid s_t)\) 已经指向另一个事件。
例如 Rollout 实际采样的动作序列是:
文本往返后,训练端可能因空格、Unicode 规范化或工具特殊 token 重新分成:
两条序列长度和动作边界都不同,reward、advantage 与 log-prob 已无法逐 token 对齐。TITO 的“in/out”强调训练管线消费推理引擎的原始 token 流,而不是说系统不保留可读文本;文本可用于日志和环境交互,但不能成为重建策略动作的唯一凭证。
一条面向 NPU 闭环的 trajectory record 建议至少包含:
prompt_token_ids
response_token_ids
rollout_log_probs
response_mask
observation_mask
policy_versions
sampling_config
tokenizer_revision
observation_mask 尤其关键:终端日志、搜索结果、编译器报错等 observation 是环境给模型的状态,不是模型动作,不能进入 policy loss。GLM-5 报告直接披露的是 TITO Gateway 记录 token IDs 与 metadata;上面列出的完整字段是本文为可重放 NPU 系统给出的工程 schema,不代表官方逐字段 recipe。
TITO 的实现所有权通常跨越 Rollout gateway、trajectory schema 和 trainer data loader。迁移新 tokenizer、chat template 或工具协议时,必须同步更新边界生成和回归样例;只在 trainer 里加一个 input_ids 字段并不能保证 TITO 成立。
Direct Double-Sided Importance Sampling¶
异步系统中,一个 trajectory 生成期间 rollout 权重可能更新多次,精确维护每个 token 对应的旧训练 checkpoint 代价很高。GLM-5 直接把 rollout 时保存的概率当作行为策略代理:
然后使用双边可信区间:
这里的“0”表示该 token 不产生梯度。相比只在特定优势方向裁剪的 PPO,它更激进地拒绝不可信 token;相比维护历史模型集合,它用可控的 off-policy 偏差换取系统可实现性。
“Direct” 指分母直接使用生成当时保存的 rollout_log_probs,不再重建大量 \(\pi_{\theta_{\mathrm{old}}}\) checkpoint;“Double-Sided” 指 ratio 过大和过小都会被拒绝,而不是只限制提高某个动作概率的一侧。例如 1.1 可保留,1.8 与 0.3 都应屏蔽,具体边界由 \(\epsilon_l,\epsilon_h\) 决定。
可以用一条长轨迹理解 policy lag:Rollout 从版本 v17 开始,生成期间 trainer 已更新到 v18、v19,轨迹到 v19 才进入队列。DIS 的 token ratio 判断其中每个动作对 v19 是否仍可用;policy version 阈值则先判断整条轨迹是否已经旧到不值得逐 token 检查。
GLM-5 还用版本差 \(v_{\mathrm{train}}-v_{\mathrm{rollout}}>\tau\) 丢弃过旧样本;权重每 \(K\) 次更新同步到推理侧,并在推理权重更新后重置 optimizer。环境失败样本也单独过滤:若组内仍有一半以上有效样本则补齐,否则整组丢弃。1
IcePop 与 DIS 不要混用¶
两者都有概率比和双边 mask,但分子、分母及回答的问题不同:
| 方法 | 典型比较 | 主要偏差来源 | 控制粒度 | 不能替代什么 |
|---|---|---|---|---|
| IcePop | 同一旧权重的 train 概率 / infer 概率 |
kernel、精度、DSA、KV、并行归约等实现差异 | token | 不能修复底层 kernel,也不能单独表达长时间 policy lag |
| DIS | 当前训练策略 / 实际 Rollout 行为策略 | 参数版本滞后,同时叠加训推实现差异 | token,并配合 trajectory 版本过滤 | 不能证明两个引擎在同权重下数值一致 |
因此,IcePop 更像同版本执行一致性检查,DIS 更像异步旧证据的可用性检查。在异步系统里,DIS ratio 同时吸收了版本变化和引擎差异;若想定位 NPU 数值问题,仍应额外做同 checkpoint 的 train/infer mismatch 回归,而不能只看 DIS mask。
# Asynchronous rollout workers
sample = environment.run(policy_version=v_rollout)
sample.store(exact_ids, rollout_logp, observations, v_rollout)
queue.push(sample)
# Trainer consumes completed samples without waiting for a whole task batch
sample = queue.pop_ready()
if current_version - sample.v_rollout > tau:
discard(sample)
train_logp = actor.logprob(sample.exact_ids)
ratio = exp(train_logp - sample.rollout_logp)
token_mask = (1 - eps_l < ratio < 1 + eps_h)
loss = -mean(token_mask * ratio * advantage * train_logp)
loss.backward()
optimizer.step()
if step % K == 0:
sync_and_reshard_weights(actor, rollout_engines)
这张五联图把 TITO 与 DIS 放在同一条生命周期里:物理视图对比文本往返与 exact token,因果视图展示 policy lag,流程视图执行版本过滤和 token mask,时序视图标出 Rollout/Queue/Trainer/Weight Sync 的先后关系,数据视图则跟踪 IDs、log-prob、version 和最终梯度。它不意味着四个对象必须由同一个进程持有。
DP-aware routing 进一步把同一多轮会话稳定路由到同一个 rollout DP rank,以复用 KV Cache。它是性能优化,但同时改变了 KV 的 owner 和生命周期:路由表、会话 version 与 cache eviction 必须一致,否则“复用”可能变成读取错误状态。
General RL:奖励不是一个标量来源¶
Reasoning RL 的二值可验证奖励适合数学和代码,但事实性、情商、指令遵循和写作质量难以用同一规则描述。GLM-5 的 General RL 混合三类信号:1
- 规则奖励:格式、长度、引用、工具协议等可以确定判断的约束。
- Outcome Reward Model(ORM):预测回答最终是否满足目标。
- 生成式奖励模型:读取上下文与回答,生成分析或评分,覆盖开放式质量。
它们通常都先落成 trajectory-level reward,再进入优势估计。混合奖励的本质不是“把分数相加”这么简单,而是选择一个标量化函数:
权重 \(w_k\) 定义能力之间的交换率,惩罚 \(P_j\) 定义不可接受行为。若 Reward Model 学会利用数据偏差,策略会放大这种偏差。因此 GLM-5 还使用人工编写的 anchor 保持目标不漂移,但公开报告没有披露完整奖励权重和数据配比。
General RL 与 NPU 的关系
Reward worker 可以不在 NPU 上,但它输出的 sample ID、版本、reward 分量和失败原因必须可追溯。否则训练端只看到一个标量,无法区分模型退化、环境失败、judge 漂移或解析错误。
OPD:把教师变成逐 token 优势¶
多阶段 RL 会产生一个常见问题:后一阶段强化新能力时,前一阶段能力可能被覆盖。GLM-5 最后使用 On-Policy Cross-Stage Distillation:把之前各阶段的最终 checkpoint 当作教师,从各教师原来的 RL 数据中采 prompt 并混合,学生生成自己的轨迹,再由对应教师在这些前缀上打分。1
为什么是 on-policy¶
给定 prompt \(x\),学生先采样:
教师不是给一条固定答案,而是在学生已经走到的每个状态 \(s_t=(x,y_{<t})\) 上计算概率。GLM-5 用下面的 log-ratio 直接替换 RL advantage:
sg 是 stop-gradient。若教师比学生更偏好学生刚采到的 token,优势为正,学生提高该 token 概率;反之为负。它等价于 sampled reverse-KL 的 policy-gradient 形式:只需教师返回学生实际采样 token 的 log-prob,不必传输 [tokens,vocab] 全词表 logits。
# Forward: student owns the state distribution
exact_ids = student_rollout.sample(prompt)
teacher_logp = teacher.prefill_and_score(exact_ids)
student_logp = actor.logprob(exact_ids)
# Backward: teacher gap becomes dense token advantage
opd_adv = stop_gradient(teacher_logp - student_logp)
loss = -mean(opd_adv * student_logp)
loss.backward()
optimizer.step()
由于教师差值已经提供 token 级方向,不需要同一 prompt 采 32 个回答做组内比较。GLM-5 报告把 OPD 的 group size 设为 1,batch size 提高到 1024。教师 logits 由推理引擎计算;报告也指出后续可切到训练引擎或 MQA mode。1
OPD 和 RL 的关系¶
OPD 的核心是学生 rollout 上的教师信号,不是某个特定优化器。至少有三种实现维度必须分开:
- 分布传输:full vocab、teacher top-k、或只传 sampled token log-prob。
- 损失形式:直接 KL/cross entropy,或把 log-ratio 写成 policy-gradient advantage。
- 任务奖励:可以纯蒸馏,也可以在 OPD advantage 上叠加 task advantage。
当前 slime 的 OPD 实现已经把 OPD 作为与 advantage estimator 正交的项:读取 teacher log-prob,并把 student-teacher reverse-KL 差加入 advantage。6
MOPD:能力整合发生在策略空间¶
MOPD(Multi-Teacher On-Policy Distillation)把多领域能力整合拆成三步:5
- 从同一个通用 SFT checkpoint 出发;
- 各领域独立做最适合自己的 RL,得到数学、指令、SWE、工具等教师;
- 学生仍从通用 SFT 初始化,自己生成多领域 trajectory,再按领域把每条 trajectory 硬路由到一个对应教师。
其完整 reverse KL 是:
其中 \(d(x)\) 是 prompt 的领域,\(T_{d(x)}\) 是被路由到的教师。工程上可用 sampled-token PG 形式,也可传教师 Top-k。MOPD 的 Top-k 目标额外加入 \(\pi_T(v)-\pi_\theta(v)\) 修正截断偏差,使 top-k 区域的最优点仍位于师生分布相等。5
为什么强调同源教师¶
同源不是组织关系,而是优化条件:教师与学生从同一个 SFT checkpoint 分叉,初始策略分布接近。MOPD 的受控实验中,Qwen3-30B-A3B 的三领域归一化得分为 0.9373,高于 Mix-RL 的 0.8818;而把数学教师换成更强但异源的 Qwen3-235B-A22B 后,初始 per-token KL 约从 0.04 升到 0.19,训练出现熵收缩甚至 Top-k 版本崩溃。5
GLM 与 MOPD 的准确关系¶
GLM-5 报告称 Cross-Stage OPD:上阶段 checkpoint 是教师,教师各自的 RL prompt 被混合。GLM-5.2 官方博客进一步披露并行 OPD 合并了十多个专家。二者都具有“多教师、路由或分源数据、学生 on-policy trajectory、策略空间整合”的结构。
但 GLM 官方没有把这套方法命名为 MOPD。因此更准确的说法是:
- GLM-5 的 Cross-Stage OPD 是多阶段教师整合;
- GLM-5.2 的十多个专家并行 OPD 在结构上接近 MOPD;
- MOPD 论文提供了更完整的多领域同源教师原理与消融证据,但不是 GLM recipe 的直接证明。
缩写冲突
文献中 MOPD 也可能指 Multi-Rollout On-Policy Distillation。本文只使用 Multi-Teacher On-Policy Distillation,判断时应看全称而不是缩写。
GLM-5.2:SAO 与 CompactionRL¶
GLM-5.2 没有简单沿用 GLM-5 的全部公开配方。两篇后续论文分别针对长程 Agent RL 的两个结构性瓶颈:组采样等待和上下文耗尽。
SAO:一条轨迹完成就训练¶
GRPO 的 group baseline 需要同一 prompt 的 \(G\) 条轨迹全部完成。长程任务中,最快样本会等待最慢样本;异步系统里,这段等待还会增加 policy staleness。SAO(Single-Rollout Asynchronous Optimization)把 group size 降到 1,每条完成的轨迹立即进入训练。3
但 \(G=1\) 后无法计算组内相对奖励,SAO 必须重新引入 Value Model \(V_\phi\) 来降低 REINFORCE 方差,并使用三个稳定机制:
- DIS:直接用 rollout log-prob 计算双边 ratio,超出区间的 token 不产生梯度。
- Critic 更快更新:每次 policy 更新前做 \(K>1\) 次 value update,论文设置 \(K=2\)。
- 冻结 Critic Attention:论文观察到 Value Model 的 Full Attention 梯度更不稳定,因此冻结 attention,只更新 MoE 投影。
对 Agent trajectory,observation 不是模型动作。SAO 的 Skip-Observation GAE 直接把当前动作末尾连接到下一动作开头:
这样不会强迫 Critic 为外部 observation token 学一个虚假的自回归价值过渡。
trajectory = async_rollout.one(prompt)
values = critic(trajectory.action_tokens)
adv = skip_observation_gae(values, trajectory.rewards)
for _ in range(K):
value_loss(critic, returns).backward()
critic_optimizer.step()
ratio = exp(actor.logprob(ids) - trajectory.rollout_logp)
mask = inside_double_sided_trust_region(ratio)
policy_loss(mask, ratio, adv).backward()
actor_optimizer.step()
SAO 论文在 Qwen3-30B-A3B 上报告:SWE-bench Verified 从 GRPO+DIS 的 27.0 提高到 SAO 的 29.8;数学任务也优于对照。这个实验支持 SAO 组件组合,但不是 GLM-5.2 的独立组件消融。3
CompactionRL:摘要也要为任务结果负责¶
长程 Agent 即使有 1M context,也会遇到 KV Cache、调度和上下文预算限制。CompactionRL 在剩余预算低于阈值时,让同一个可训练策略生成摘要:4
随后用系统提示、摘要和最近 \(k\) 个原子化的 action-observation 对重建上下文:
摘要不是外部预处理器。它和普通执行 token 一样由 Actor 生成,并共享最终任务奖励 \(R(\tau)\)。如果摘要漏掉文件路径、失败命令或未解决错误,后续执行失败会反向惩罚摘要行为。
压缩会把一条 trajectory 切成数量和长度都不固定的 \(K\) 个 segment。若按 segment 平均 loss,压缩次数多的轨迹会被重复加权。CompactionRL 因此在全部可训练 token 集合 \(\mathcal M\) 上归一化 PPO loss:
第二个问题是信用距离。若每个 segment 独立做 GAE,早期摘要会“看起来”离终局奖励很近。设后续 segment 还有 \(N_{>s}\) 个可训练 token,跨轨迹修正为:
这恢复了早期 token 到最终结果的大致时间距离,同时保留 segment 独立训练的系统并行性。
CompactionRL 的 GLM-4.5-Air 实验中,80K 峰值上下文下的压缩推理,SWE-bench Verified 从 base 的 59.8、普通 RL 的 62.5 提高到 66.8;去掉 token-level loss 后降至 60.0,去掉 cross-trajectory GAE 后为 63.0。4
QAT:让模型在量化误差里学习¶
先纠正阶段归属:GLM-5 报告原文明确写道,INT4 QAT 应用于 SFT stage,并开发了同时适用于训练和离线权重量化的 kernel,以保证训练与推理逐比特一致。1
因此它不属于本文的“非 SFT 方法序列”,但它直接决定 NPU 上低精度后训练能否保持分布一致,必须单独理解。
Fake quant 的前向¶
对一组浮点值 \(x\),仿射量化可写成:
\(s\) 是 scale,\(z\) 是 zero-point。QAT 前向并不一定真的把模型状态长期存成 INT4;它通常执行 quantize → dequantize,让后续 GEMM 看到离散化后的 \(\hat x\),从而把舍入、截断和动态范围误差暴露给训练。
量化粒度决定多少元素共享一组 qparam:
- per-tensor:整个 tensor 共用一组 scale,开销小、误差大;
- per-channel/per-row:一行或一个输出通道一组;
- per-group/per-block:例如每 32 或 128 个权重一组,在误差与元数据间折中;
- per-token activation:每个 token 的激活独立求 scale。
torchao 的 INT4 fake quant 代码明确使用 quant_min=-8, quant_max=7 的有符号范围;其通用 fake-quant op 等价于量化再反量化但不做实际 dtype cast。7
STE 的反向¶
round 几乎处处梯度为 0,直接求导会让训练停止。Straight-Through Estimator 在反向把离散算子近似成恒等映射:
torchao 的 _Round.backward 直接返回上游梯度 gy,就是最直白的 STE。8
# QAT forward
scale, zero_point = choose_qparams(weight, granularity=group_size)
q = clamp(round(weight / scale) + zero_point, qmin, qmax)
fake_weight = scale * (q - zero_point)
output = matmul(input, fake_weight)
loss = task_loss(output, target)
# QAT backward
# round is replaced by identity in the gradient path
grad_weight ~= grad_fake_weight
loss.backward()
optimizer.step() # update the floating master weight
物理对象必须分清:浮点 master weight 由 optimizer 更新;q 是临时整数语义;fake_weight 仍是浮点 tensor;部署 checkpoint 则可能是实际 packed INT4 加 scale/zero-point。只看 Python dtype 很容易误判究竟在哪一步获得了内存收益。
为什么强调 bitwise-identical¶
若 QAT 前向和离线转换使用不同的 rounding mode、group 划分、scale 精度、饱和范围或 packing 顺序,训练适应的是误差 \(e_{\mathrm{train}}\),部署面对的却是另一个误差 \(e_{\mathrm{deploy}}\):
即使两者平均误差相近,MoE router、DSA indexer 或采样 logits 的边界 token 也可能改变。GLM-5 的“逐比特一致”要求,本质上是在消除这一隐藏的第二量化器。
MindSpeed-LLM 的固定提交已经暴露 w4a16-mxfp4、w4a16-mxfp4-moe-only、w4a4-mxfp4、w4a8-moe-only 等 QAT scheme,并允许 W4A8 使用 32/128 block size。9 这说明昇腾侧已有 QAT 算子积木,但仍不能据此断言 GLM-5.2 的官方 INT4 QAT 配方已复现。
量化:三件事不要混为一谈¶
围绕 GLM 的公开材料,至少存在三条低精度路径:
| 路径 | 训练参数 | 前向数值 | 主要目的 | 是否产生适应量化误差的梯度 |
|---|---|---|---|---|
| QAT | 通常保留浮点 master weight | fake quant 或低精度训练 kernel | 让模型适应目标量化误差 | 是 |
| 量化 Rollout | Actor 可继续 BF16 训练 | 推理侧 FP8/INT8/INT4 权重或 KV | 降低采样显存、带宽和时延 | 否,除非同一误差也进入训练前向 |
| 离线部署量化 | 训练已结束 | packed W8A8/W4A8/INT4 | 降低部署成本 | 否 |
slime 当前推荐的大型 MoE 路径是 Megatron BF16 训练 + SGLang FP8 rollout:同步时把更新后的 BF16 权重按 rollout checkpoint 的量化配置转换成 FP8 后发送;FP8 KV Cache 是另一个独立开关。固定提交把 INT4 rollout/QAT 标为 beta,FP8 训练 + rollout 标为 experimental。10
这条路径最容易产生误解:Actor optimizer 并没有在 FP8 参数上更新,但行为数据由 FP8 rollout 策略产生,所以必须继续测量:
IcePop/DIS 可以屏蔽 \(\Delta_t\) 过大的 token,却不能替代量化校准。如果大量 token 被屏蔽,训练虽然不崩,有效样本率也会下降。
另一方面,GLM-5.2 的官方 Ascend 部署文档使用 QuaRot、Flex SmoothQuant 和 SSZ 组合的混合 W8A8;这是部署推理方案,不是 QAT 证据。11 MindSpeed-RL 还公开了基于 Flash-RL 的 NPU INT8 online-quantized rollout 示例,通过 BF16/INT8 profile 决定更新权重如何在线量化;同样不能把它写成 GLM-5.2 官方 recipe。12
判断一个 low-precision 声明
依次问五件事:量化谁、在哪个进程、何时量化、以什么粒度、梯度是否穿过量化误差。只说“支持 INT4/FP8”几乎没有技术含义。
NPU 原生的数值契约¶
把前面的方法压缩成 NPU 研发对象,可以得到六份不能破坏的契约。
动作与概率契约¶
- rollout 交付 exact token IDs、response mask、rollout log-prob、采样配置和 tokenizer/chat-template revision;
- train、rollout、teacher 必须对同一 token ID 和同一前缀计算 log-prob;
- observation、prompt、工具返回和复制的 compacted tail 不进入 policy loss;
- sampled log-prob 的精度、logsumexp 和 vocabulary parallel reduction 必须有对照测试。
稀疏与版本契约¶
- DSA Top-k 记录 tie、排序、NaN、index dtype 与跨卡归并规则;
- rollout sample 携带 policy version,trainer 定义可接受的最大 staleness;
- 权重同步包含训练分片 → 推理分片 → 量化 → 发送 → 原子切换 → 确认,不把“传输完成”等同于“新策略已生效”;
- 多轮会话的 DP routing 与 KV Cache owner 同步迁移或显式失效。
Teacher 与量化契约¶
- 每个 prompt 的 teacher route 可追溯,教师 tokenizer 和 action space 与学生兼容;
- teacher prefill payload 明确是 sampled log-prob、Top-k IDs/logits 还是 full vocab;
- QAT 与离线量化共享 rounding、scale、zero-point、group/block、饱和和 packing 语义;
- BF16/FP8/INT8/INT4 分别标注为 model state、GEMM compute、rollout weight、KV Cache 或 checkpoint format。
内存不是“参数量乘位宽”¶
RL/OPD 峰值显存至少应写成:
其中 Actor、Reference、Teacher、Critic、rollout KV、DSA index、teacher logits、weight-reshard buffer 可能在不同 NPU、不同进程或不同时间段驻留。必须为每个对象记录:
- 逻辑形状与物理布局;
- producer、consumer 与 owner;
- 创建、跨进程传输、复用和释放时间;
- 属于持久模型状态、保存激活、算子 workspace、通信 buffer 还是 live IO。
现有昇腾栈到了哪里¶
固定到本文核验的提交,开源状态可以概括为:
| 能力 | 已有证据 | 仍缺的 GLM-5.2 闭环证据 |
|---|---|---|
| GLM-5.2 模型训练 | MindSpeed-LLM 有 744B-A40B、32 节点、每节点 16 NPU 的预训练脚本,含 DSA/MoE/MTP | GLM-5.2 SFT/RL/OPD 的公开 NPU recipe |
| 通用 RL | MindSpeed-RL 支持 GRPO/PPO/DAPO、异步队列、训推重分片、vLLM-Ascend | IcePop、GLM TITO/DIS、Cross-Stage OPD 的 E2E 示例 |
| 量化训练 | MindSpeed-LLM 有多种 W4/A4/A8 QAT scheme | 与 GLM 报告逐比特一致要求对应的公开验证 |
| 量化 rollout | MindSpeed-RL 有 Qwen INT8 online-quantized rollout 示例 | GLM-5.2 DSA/MoE 的概率 mismatch、吞吐和收敛证据 |
| 昇腾推理 | GLM-5.2 官方文档支持 vLLM-Ascend/SGLang/xLLM 与混合 W8A8 | 训练 Actor、Teacher Prefill、Verifier、权重原子切换的统一 recipe |
因此当前最准确的判断不是“昇腾不支持 GLM RL”,而是:模型、通用 RL、QAT 与推理积木已经存在;等价于官方 GLM-5.2 的端到端 NPU 原生后训练配方仍是公开缺口。
证据能说明什么¶
本文把证据分成四层,避免把模型级结果误写成算法因果:
- 流程证据:GLM-5 报告和 GLM-5.2 博客说明哪些阶段、框架和方法被使用。
- 方法证据:MOPD、SAO、CompactionRL 在各自受控模型和任务上的结果,说明机制有实验支持。
- 代码证据:固定提交证明某个 flag、loss、QAT scheme、backend 或示例存在。
- 缺口证据:没有找到 GLM-5.2 NPU E2E recipe,只能表述为“截至固定版本未找到”,不能推断内部或未来一定不存在。
尤其要保留三个边界:
- GLM-5/5.2 的总体 benchmark 不能隔离某个 RL、OPD 或 QAT 组件的收益;
- SAO 的主实验是 Qwen3-30B-A3B,CompactionRL 的主实验是 GLM-4.x;“用于 GLM-5.2 pipeline”是部署陈述,不是 GLM-5.2 消融;
- GLM-5 报告没有给 INT4 QAT 的独立精度/吞吐消融,不能编造“QAT 提升了多少”。
总结¶
GLM 的非 SFT 后训练可以记成一条清晰主线:
- Reasoning RL 用 GRPO 获得组内相对方向,用 IcePop 和确定性 DSA 只保留可信 token;
- Agentic RL 用异步 rollout 提升吞吐,再用 exact token、rollout log-prob、双边 IS 和 policy version 控制滞后;
- General RL 把规则、ORM 和生成式 judge 组合成开放任务的目标;
- Cross-Stage OPD 用教师 token 分布恢复前序阶段能力,GLM-5.2 的十多个专家并行 OPD 在结构上接近多教师 MOPD;
- SAO 消除组内等待,但以 Critic 和 Value Model 稳定机制换取单轨迹更新;
- CompactionRL 把摘要纳入策略,让上下文压缩也对最终任务负责;
- QAT 用 fake quant + STE 让模型适应低比特误差,但 GLM-5 明确把它放在 SFT,而 FP8/INT8 rollout 与 W8A8 部署是另外两条量化路径。
对 NPU 团队而言,最需要掌握的不是更多算法缩写,而是动作、概率、索引、版本、量化和对象生命周期。这些契约守住以后,RL、OPD、SAO 或 QAT 才能在 NPU 上保持它们原本的数学含义。
参考文献¶
-
GLM Team, GLM-5: from Vibe Coding to Agentic Engineering, 2026。后训练方法见 Section 3;INT4 QAT 的 SFT 阶段归属见 Section 2.5.4。 ↩↩↩↩↩↩↩↩↩↩
-
Z.ai, GLM-5.2: Built for Long-Horizon Tasks, 2026-06-16。官方披露 slime、十多个专家并行 OPD 与约两天训练时间。 ↩
-
Hou et al., Single-Rollout Asynchronous Optimization for Agentic Reinforcement Learning, 2026。 ↩↩↩
-
Li et al., CompactionRL: Reinforcement Learning with Context Compaction for Long-Horizon Agents, 2026。 ↩↩↩
-
Ma et al., MOPD: Multi-Teacher On-Policy Distillation for Capability Integration in LLM Post-Training, 2026。 ↩↩↩
-
THUDM, slime on-policy distillation documentation 与 loss implementation, 固定提交
f655e13。 ↩ -
PyTorch AO, fake_quantizer.py, 固定提交
623c463。 ↩ -
PyTorch AO,
_Roundwith STE backward, 固定提交623c463。 ↩ -
Ascend, MindSpeed-LLM QAT quant engine, 固定提交
79afbee。 ↩ -
THUDM, slime low-precision training and rollout, 固定提交
f655e13。 ↩ -
Z.ai, Using Ascend NPU to Deploy GLM-5.2, 固定提交
436efa0。 ↩ -
Ascend, MindSpeed-RL Online Quantized Rollout, 固定提交
26c21e6。 ↩











