Skip to content

[Feature] Freeze native MTP parameters while preserving load, save and rollout publication - #2292

Draft
xs1997zju wants to merge 4 commits into
InternLM:mainfrom
xs1997zju:rl/native-frozen-mtp-minimal
Draft

xs1997zju wants to merge 4 commits into
InternLM:mainfrom
xs1997zju:rl/native-frozen-mtp-minimal

Conversation

@xs1997zju

@xs1997zju xs1997zju commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Keep native MTP weights in the actor while freezing their dedicated parameters, so existing load/save/weight-publication paths can continue supplying speculative decoding. MTPConfig(num_layers=1, frozen=True) excludes dedicated MTP parameters from the optimizer and skips MTP training forward/loss; the main model and shared embedding/output head continue training. Default frozen=False behavior is preserved.

Base: main f1fddc506a49b7d0aa71554e26908885b37211cc. Unchanged code head: 80a72703464e2c813def1a1b2b610df379b0cc05. This standalone PR does not include the Agent lifecycle stack (#2294–#2299), Lagent or recipe changes.

Configuration and code entry points

  • Configure MTPConfig(num_layers=1, frozen=True) in the native model.
  • Set outer model_cfg.dcp_ignore_frozen_params=False for a self-contained native DCP; the existing default can omit frozen parameters.
  • Speculative decoding still uses existing LMDeploy settings: lmdeploy_speculative_algorithm="qwen3_5_mtp" and a positive draft length in the Qwen setup. Freezing alone does not enable speculation or establish speedup.
  • Start with xtuner/v1/module/mtp/config.py, model/moe/moe.py, rl/trainer/actor_worker.py, and utils/loader.py. Feature documentation.

Source and loading repair

The minimal native-freezing patch is extracted from xs1997zju/xtuner#3, fixed at 76f2dfdbecff27a10ca53e39e04c3079651282ea; source authorship is retained. Full-model validation also exposed Qwen3.5 HF checkpoints storing fused MTP expert tensors. A narrow safetensors alias/slice resolver maps those BF16/FP16/FP32 tensors to native per-expert load specs. Direct keys take precedence; malformed shape/index/dtype fails explicitly. Quantized fused-source aliases are unsupported; bin and non-MTP behavior is preserved.

Validation and boundaries

Evidence Result and scope
Standalone loader CPU checks 13 passed, using real safetensors/index/bin I/O; targeted lint/format/whitespace checks passed.
Qwen native integrated training Two real optimizer updates on eight H200s; per-rank dedicated MTP hashes unchanged, no optimizer membership or training MTP forward, changing main/shared parameter witnesses. Earlier integrated runs include actual multi-turn tools, HF export, IPC/NCCL components and full Trainer cold restore; component topologies differ.
Reassembled Agent stack + this patch Fresh eight-H200 quick regression: two real updates, IPC synchronization, request versions 0/1/2, the same controlled task continuing across an update, session affinity, full Trainer DCP cold restore and a real post-restore response. Recorded training data and controlled tool waiting are used; this is not natural CyberGym reward learning.
GLM-5.3-Flash The author confirms compatibility. Independently recorded controlled validation used a five-layer GLM model, with two replay updates and two controlled online updates, frozen dedicated MTP, and generation after the first publication. This does not establish full-size training, natural task quality, GLM full-checkpoint restoration, draft acceptance or speedup.
Review Original real Kimi XT Review and the documentation-only follow-up are posted in comments. The navigation finding was fixed; no functional model/loader defect was confirmed.

GPU evidence was collected on explicitly recorded integrated candidates containing the corresponding native runtime patch, not by executing every exact standalone public branch tree. Cold restore evidence stops after restored state and a real response: no third optimizer update or independent elementwise comparison of all optimizer moments is claimed. No convergence, memory-superiority, speedup or general failure-recovery claim.

Delivery relationship

Current delivery selects native #2292 only. External-source #2289 is not included or selected; older historical comments/documents may describe it as an alternative. This update does not close or modify #2289.

The Agent lifecycle work is split from #2257 into #2294–#2299. Lagent #385 targets v1.0.0. CRG !78 provides the separate CyberGym recipe; its published recipe currently selects native wiring explicitly, while the separately tested local simplification constructs the native config directly. XTuner does not read that recipe's route-selection environment variable.

Developer guide with feature-to-PR mapping, diagrams, single-node scripts and quick-GPU method.

Keep Draft; no automatic merge. This publication update changes only title/description/comments, preserving the code head.

@xs1997zju

Copy link
Copy Markdown
Collaborator Author

Independent Kimi XT Review — native frozen MTP

The original report reviewed base f1fddc506a49b7d0aa71554e26908885b37211cc to 10d89ad113b8081980a58047ef18ee1ceaf0024a. The follow-up below reviewed the documentation-only change to the published head 80a72703464e2c813def1a1b2b610df379b0cc05; it resolved the navigation finding without production-code changes.

Real CLI model: kimi-code/kimi-for-coding. Original session session_b40a7f55-e359-4fef-8b71-5e1003fabb19; follow-up session session_a5b47ea3-deb1-480e-bcd1-e2349289ec84; both exited 0 with persisted sessions verified. No model/loader functional defect was confirmed. These are the retained independent reports, not a new review of unmodified code.

Current delivery chooses native #2292 only. The older reports describe #2289 as an alternative because that was the review-time context; it is no longer part of the selected delivery. Current recipe and combined-test status is summarized in the updated PR body and developer guide.


Review — XTuner #2292 Native frozen MTP + fused MTP expert loader

  • PR: XTuner [Feature] Freeze native MTP parameters while preserving load, save and rollout publication #2292(独立 PR,base f1fddc5,head 10d89ad,merge-base = base)
  • 范围: 8 个文件(3 源码 + 1 配置 + 1 文档 + 3 测试),258+/9-。仅审此 diff 并结合未改消费者追踪。
  • 关系声明(已核对): 本 PR 与 [Feature] Preserve external frozen MTP across RL updates and checkpoints #2289(外置 WorkerConfig.frozen_mtp adapter)是互斥备选,文档已明确禁止同时开启;本 PR 不含 [Draft] Retain native Agent tasks across complete-turn weight publications #2257 的 Agent lifecycle 改动。证据索引(VALIDATION_EVIDENCE_INDEX.md)指出:公开 10d89 的 6 个原有源码/测试文件与集成 7b 逐字节相同,新增 loader 测试与文档;运行栈 = core4876(生产代码同 2257 之 43d62)+ 最小原生 9bdb + loader 修复,运行栈不含外置 2289。因此运行栈 GPU 证据对本 PR 的生产代码有参照价值,但不能记作"公开 10d89 树完整验收"。
  • GLOSSARY/ADR: 仓库根不存在 GLOSSARY.md,不存在 docs/adr/。架构评估以 codebase-design 技能词汇执行;无 ADR 冲突可核对。
  • 证据边界: 本轮为只读审阅,未运行代码(无需要验证的可疑错误)。已验证事实均指向本仓库 10d89 工作树源码行号;GPU/集成证据仅按证据索引转述并标注范围。

Summary

本 PR 做两件事:

  1. 原生冻结 MTP(MTPConfig.frozen):MTP 参数保留在模型中(可加载、可保存、可发布到 rollout 引擎供投机解码),但 requires_grad_(False)、不构建 MTP loss ctx、不执行 MTP training forward、不进 actor 优化器/不动 router bias。与 [Feature] Preserve external frozen MTP across RL updates and checkpoints #2289 的外置 adapter 方案互斥。
  2. HF fused MTP expert 解析(HFCheckpointLoader):Qwen3.5 源 checkpoint 中 mtp.layers.*.mlp.experts.gate_up_proj/down_proj(3D fused)按专家切片解析为原生 per-expert gate/up/down_proj.weight;直接索引键优先;非浮点/非法 shape/越界专家显式 ValueError;bin checkpoint 与其余键族保持原行为。

总体评价:改动小而收敛,抽象合理,无确认的功能缺陷。发现的问题集中在文档挂接(toctree 缺失)和少量设计/测试建议,见各章节 X2292-F01~F08。关键链路(frozen 参数 → 排除优化器 → 保留发布 → 保留 load spec → DCP 契约)经源码逐环核对一致。

Main Flowchart before this PR

graph TD
  subgraph MTPConfig["xtuner.v1.module.mtp.config.MTPConfig"]
    C1[num_layers / share_weights /<br/>loss_type / detach_* ]
  end
  subgraph MoE["xtuner.v1.model.moe.moe.MoE"]
    M1["__init__: build_mtp_block()<br/>(mtp_config 非空即建)"]
    M2["update_bias(): 主层 router + MTP gate<br/>行数 = num_hidden_layers + mtp 物理层"]
    M3["build_loss_ctx_batch(): mtp_config 非空<br/>即建 mtp / mtp_e2e_tv ctx"]
    M4["_forward(): mtp_block 非空即跑<br/>MTP training forward"]
    M5["_micro_batch_forward(): 同左"]
  end
  subgraph ActorWorker["xtuner.v1.rl.trainer.actor_worker.ActorWorker"]
    A1["mtp_config = model_cfg.mtp_config"]
    A2["mtp_cfgs = [MTPLossConfig per depth]"]
    A3["_mtp_trainable_parameters =<br/>trainable_parameters() 中 mtp_block.*"]
  end
  subgraph Engine["xtuner.v1.engine.train_engine.TrainEngine"]
    E1["优化器 = trainable_parameters()<br/>(全部 requires_grad=True)"]
    E2["DCP save: ignore_frozen_params=<br/>dcp_ignore_frozen_params(默认 True)"]
  end
  subgraph Loader["xtuner.v1.utils.loader.HFCheckpointLoader"]
    L1["is_key_exist: key in weight_map"]
    L2["load: 直接查 weight_map,<br/>缺失返回 None"]
  end
  subgraph WI["xtuner.v1.rl.weight_update.weight_iterator.WeightIterator"]
    W1["iter_hf_batches: _load_spec_params()<br/>→ _get_hf_param → 发布全部参数"]
  end
  C1 --> M1 --> M2
  C1 --> M3 --> M4
  C1 --> M5
  C1 --> A1 --> A2 --> A3
  M1 --> E1
  M2 --> E2
  M1 -.发布.-> W1
  L2 -.from_hf.-> M1
Loading

Main Flowchart after this PR

graph TD
  subgraph MTPConfig["xtuner.v1.module.mtp.config.MTPConfig"]
    C1[num_layers / share_weights /<br/>loss_type / detach_* ]
    C2["frozen: bool = False  ★新增字段"]
  end
  subgraph MoE["xtuner.v1.model.moe.moe.MoE"]
    M1["__init__: build_mtp_block() 后<br/>frozen 则 mtp_block.requires_grad_(False) ★"]
    MP["property _mtp_training_enabled<br/>= block 非空 且 config 非空 且 not frozen ★"]
    M2["update_bias(): 仅 _mtp_training_enabled<br/>才消费 MTP 行 ★"]
    M3["build_loss_ctx_batch(): 由<br/>mtp_config 非空改为 _mtp_training_enabled ★"]
    M4["_forward(): 由 mtp_block 非空<br/>改为 _mtp_training_enabled ★"]
    M5["_micro_batch_forward(): 同左 ★"]
  end
  subgraph ActorWorker["xtuner.v1.rl.trainer.actor_worker.ActorWorker"]
    A1["mtp_config = model_cfg.mtp_config"]
    A0["frozen 则 self.mtp_config = None ★<br/>(null object)"]
    A2["mtp_cfgs = [](frozen 时为空)"]
    A3["_mtp_trainable_parameters = []"]
  end
  subgraph Loader2["xtuner.v1.utils.loader.HFCheckpointLoader"]
    L1["is_key_exist: 直接键 OR<br/>_resolve_fused_mtp_expert ★"]
    L2["load: 直接键优先;缺失键走<br/>_load_fused_mtp_expert 切片 ★"]
    L3["regex: mtp.layers.N.mlp.experts.M.<br/>(gate|up|down)_proj.weight"]
    L4["gate = 前半, up = 后半;<br/>BF16/F16/F32 之外显式报错 ★"]
  end
  WI["WeightIterator: 不变(load spec 天然含 frozen 参数)"]
  C2 --> M1
  C2 --> MP
  MP --> M2
  MP --> M3
  MP --> M4
  MP --> M5
  C2 --> A0 --> A2
  M1 --> WI
  L3 --> L1
  L4 --> L2
  classDef hl fill:#ffe08a,stroke:#b58900,stroke-width:2px;
  class C2,M1,MP,M2,M3,M4,M5,A0,L1,L2,L4 hl;
Loading

修改与流程对应说明:

  • 冻结入口:MTPConfig.frozen(config.py:63,纯数据字段,符合 TypedDict/数据类例外)。MoE.__init__(moe.py:276-277)在建 block 后立即 requires_grad_(False)。
  • 训练路径消隐:moe.py 中原有 4 处 mtp_block is not None and config.mtp_config is not None 或 config.mtp_config is not None 分叉,统一收编为 _mtp_training_enabled(moe.py:312-313),调用点:update_bias(moe.py:422)、build_loss_ctx_batch(moe.py:495)、_forward(moe.py:750)、_micro_batch_forward(moe.py:1036)。
  • actor 侧 null object:actor_worker.py:122-123 将 frozen config 归一为 None,使 mtp_cfgs / _mtp_trainable_parameters 自然为空,下游零分叉。
  • loader 别名解析:loader.py:81-123;直接键在 load 中先查 weight_map(直接键优先,测试覆盖),is_key_exist 为"直接 OR 别名"。
  • 发布路径零改动:WeightIterator.iter_hf_batches 走 _load_spec_params()(state_dict 全量,不看 requires_grad),frozen 参数因此被发布到推理侧——这是本特性"冻结但可被投机解码消费"的关键,已有单测锁定(见测试章节)。

核心原理

  1. 冻结 = 参数保留 + 计算图摘除。requires_grad_(False) 使 frozen 参数:不进优化器(train_engine.py:280 trainable_parameters() 过滤)、不被 DCP ignore_frozen_params 语义外例外地保留(需用户显式 dcp_ignore_frozen_params=False,默认 True 会丢 frozen 参数——文档已写明此契约)。同时 4 处分叉消隐保证不执行 MTP training forward、不产生 MTP loss、不累积 MTP 侧 aux 统计行。
  2. bias 更新一致性:update_bias 消费的统计行数 = 实际执行了 forward 的 routed 层数。frozen 时 MTP gate 不产生统计行,update_bias 也跳过 MTP 行(moe.py:446 的行数校验会在不一致时显式 RuntimeError,属响亮失败)。
  3. fused expert 解析:Qwen3.5 HF checkpoint 将 n_routed_experts 个专家的 gate/up([E, 2I, H])与 down([E, H, I])存为 3D fused 张量;原生 load spec 寻址 per-expert 矩阵。loader 用 get_slice 按专家切片,gate=第 0I-1 行、up=I2I-1 行。gate 前半的约定与仓内既有实现一致:xtuner/v1/ops/act_fn.py:20 gate, up = torch.chunk(fused_x, 2, ...),GLM fused_w1w3 的 w1=gate/w3=up 同序(glm53.py:261-266)。证据索引中的 commit ece5744"读取原始 Qwen fused MTP expert 权重"亦指向真实权重核对(转述,非本树内证据)。
  4. share_weights 不误伤主模型:MTP 对 embed/lm_head 的共享是函数式的(_micro_batch_forward 传 embed_tokens_fn=self.embed_tokens、复用 self.lm_head),mtp_block.requires_grad_(False) 只触及 mtp_block 自有的 decoder_layer 参数,不会冻结主模型 embed/head——与文档"main model and its shared embedding/output head remain trainable"一致(已验证:moe.py:1054-1059、1092)。

核心实现与对应的单测

实现 位置 单测 原理说明
frozen 参数保留 + 排除训练 moe.py:276-277, 312-313; config.py:63 tests/model/test_glm53_shared_mtp_depth.py TestFrozenMTP.test_builder_retains_parameters_and_load_specs meta device 构建,断言 frozen 时 mtp 参数 requires_grad=False、_mtp_training_enabled=False、trainable_parameters() 不含 mtp_block、但 _load_spec_params() 仍含(发布契约)
frozen 跳过 training forward/loss moe.py:495, 750, 1036 test_micro_batch_forward_skips_frozen_mtp 大量 patch 隔离主路径后断言 mtp_block.forward 未被调用、output.mtp_loss is None
frozen 不动 MTP router bias moe.py:422-447 test_bias_update_consumes_only_main_router_rows 只给主层 router 行数,走 update_bias 不触发"行数不符" RuntimeError
frozen 参数仍进发布批次 (无源码改动)weight_iterator.py:69 tests/rl/test_weight_iterator.py TestFrozenMTPWeightUpdate FrozenMTPModel(requires_grad=False 的 mtp_block.weight)经 iter_hf_batches 后 state_dict 含 mtp_block.weight,证明发布链路不看 requires_grad
fused MTP expert 解析 loader.py:81-123 tests/utils/test_fused_mtp_loader.py(新文件,真实 safetensors I/O) 6 组用例:BF16/FP16/FP32 × 有/无 index.json 的逐专家逐片精确相等(rtol=atol=0);直接键优先;非 MTP/缺失键返回 None 保持原行为;bin 路径不受影响;4 种非法输入(2D shape、专家越界、奇数中间维、int64 dtype)显式 ValueError

抽象与信息隐藏评估

依据 improve-codebase-architecture / codebase-design 词汇(module/interface/depth/seam/locality/deletion test):

  • _mtp_training_enabled(property)通过 deletion test:删除它会把同一条 4 元条件撒回 4 个调用点;它把"frozen 规则"藏在单点,locality 好。interface 极小(无参布尔)。
  • frozen 是 MTPConfig 上的纯数据字段,不新增类,符合"尽量少增加类"。
  • loader 的别名解析是私有方法(_resolve_fused_mtp_expert / _load_fused_mtp_expert),公开 interface(load / is_key_exist)签名与语义不变,depth 保持。代价是通用 loader 模块耦合了一个模型家族的 HF 键族知识——按"one adapter = hypothetical seam",当前只有一个别名族,内联合理;若出现第二个族应抽 key-alias resolver。详见 /tmp/architecture-review-xt2292-20261111.html。
  • actor_worker 的 null object(mtp_config = None):以销毁信息换取下游零分叉,R3 达标;代价是 actor 此后无法区分"无 MTP"与"MTP frozen"(见 X2292-F05)。
  • GLOSSARY.md 与 docs/adr 在仓库中实际不存在,无法引用领域词汇与 ADR;已在架构 HTML 中注明。

新增功能守则(R1–R3)

  • 既有类接触点:MoE 新增接触点为 1 个 property + 5 次具名读取(≤ R1 上限,其中 __init__ 1 次 requires_grad_ 具名调用);ActorWorker 为 1 次具名判断 + 1 次赋值;HFCheckpointLoader 为 load/is_key_exist 各 1 次私有调用。达标。
  • R2(实现细节不外泄):调用点只出现 _mtp_training_enabled,frozen 的字段名(frozen)只出现在 property 定义、actor_worker 一处、config 定义中;pad 值/sp 规则/指标 key 无涉及。actor_worker 直接读 .frozen 字段名算轻微破例(1 处,可接受)。
  • R3(无新特性分叉):moe.py 的 4 处旧分叉被 property 收编而非新增分叉;actor 下游对 frozen 完全无感知(mtp_cfgs 空列表是自然结果)。达标。

公开接口的线性业务流程评估

  • HFCheckpointLoader.load 保持线性:直接键 → 别名解析 → 切片返回;_load_fused_mtp_expert 内部也是线性"解析 → 取 slice → shape/dtype 校验 → 切半",无抽象层级混乱,纯转发 wrapper 未新增。达标。
  • MoE.__init__ 新增两行紧跟 build 之后,属同层步骤;update_bias 中 MTP 分支保持原结构仅条件收紧,主流程(主层循环 → MTP 聚合 → 统一 add_)仍线性。达标。

单测建议

  • X2292-F06(低,建议):test_micro_batch_forward_skips_frozen_mtp 依赖 8 处 patch 且 embed/rotary/lm_head 均为桩,只证明"分叉条件正确",不证明 frozen 下真实前向的内存/图语义。建议补一个最小真实 forward(CPU、tiny config、frozen=True/False 对照),断言 frozen 时 loss 不依赖 mtp 参数(grad 为 None 或对 mtp 输入的梯度流为零)。
  • X2292-F07(低,建议):test_bias_update_consumes_only_main_router_rows 只验证"不抛行数错误",且全局 patch torch.Tensor.add_ 签名 (tensor, other) 若未来 add_ 带 kwargs 会误伤。建议改为构造非零 bias、断言值确实未变,并用 patch.object(NoAuxRouter, ...) 级粒度替代全局 Tensor patch。
  • 发布链路已有 TestFrozenMTPWeightUpdate 锁定 frozen 参数进批次,覆盖到位;如需更强证据,可在该测试中再断言 mtp 参数以 bf16 发布且 batches[-1].finished。

其他 issues

X2292-F01 — 新文档未挂 toctree,成为 orphan 页面(轻微,已确认)

  • 位置: docs/en/rl/advanced_tutorial/native_frozen_mtp.md(新增);docs/en/rl/advanced_tutorial/index.rst:1-9
  • 问题: index.rst 的 toctree 未加入 native_frozen_mtp.md(grep 无匹配,exit 1 已确认);且 docs/zh_cn/rl/advanced_tutorial/ 无对应中文文档,与目录内其他条目(agent_loop.md、judger.md 等均有 zh_cn 对应)不一致。Sphinx 构建将报 orphan 警告或干脆不收录。
  • 解决建议: 在 en index.rst toctree 加入 native_frozen_mtp.md;如需双语一致,补 zh_cn 版本。
   on_policy_distillation.md
   native_frozen_mtp.md

X2292-F02 — 通用 loader 模块内联 MTP 键族知识(设计建议,已确认/推断)

  • 位置: loader.py:84-98
  • 说明: regex 硬编码 mtp.layers.N.mlp.experts 布局与 gate/up 切半规则。当前仅一个别名族,内联通过 deletion test;若 Qwen 后续家族或其他模型出现不同 fused 布局,条件会在此堆积。已在架构 HTML(/tmp/architecture-review-xt2292-20261111.html)标为 Worth exploring,本轮不重构。
  • 伪代码(将来第二个族出现时再考虑):
class HFCheckpointLoader:
    def __init__(...):
        self._alias_resolvers: list[Callable[[str], AliasHit | None]] = [resolve_fused_mtp_expert]
    def _resolve(self, key):
        for r in self._alias_resolvers:
            hit = r(key)
            if hit: return hit

X2292-F03 — 量化 fused MTP 源从"静默缺失"变为显式报错(行为变更,已确认,属预期)

  • 位置: loader.py:112-113
  • 说明: 修改前,量化 fused 源 checkpoint 的 per-expert 键查询返回 None(走 missing 路径);现在 is_key_exist 为 True 且 load 抛 ValueError("...require unquantized floating weights")。文档已声明"Quantized fused-source aliases are not supported",属于把静默不一致变为响亮失败,判定为合理设计而非缺陷。注意 _read_hf_tensor(base.py:2258-2272)不会捕获该异常——失败会中断加载,这是预期。

X2292-F04 — frozen 时 is_key_exist 与 load 的弱一致窗口(轻微,已确认)

  • 位置: loader.py:81-82 vs 100-119
  • 问题: is_key_exist 为 True 的 fused 别名键,load 可能因 shape/越界/dtype 抛 ValueError。任何"先 is_key_exist 后把 load-None 当缺失跳过"的调用方语义会被改变(现存调用方 _read_hf_tensor 只把 None 当缺失,不吞异常,已核对安全)。属可接受的契约收紧,记录备查。

X2292-F05 — actor_worker 销毁 frozen 信息(设计建议,已确认)

  • 位置: actor_worker.py:122-123
  • 说明: self.mtp_config = None 使 actor 无法区分"模型无 MTP"与"MTP 被冻结"。当前无消费者需要区分,R3 收益大于代价;若未来需要(如发布前校验 frozen 参数确已发布),建议另存 self._mtp_frozen: bool 而非重读配置。

X2292-F08 — frozen MTP 与 dcp_ignore_frozen_params 默认值的契约依赖(文档已声明,提示确认)

  • 位置: xtuner/v1/model/base.py:143(默认 True);train_engine.py:391;docs/native_frozen_mtp.md
  • 说明: 默认 True 时 DCP save 会丢 frozen MTP 参数,文档要求用户显式置 False 以获得自足 checkpoint。这是"配置默认值与新特性语义冲突、靠文档补救"的折中;代码层不做防御(如 frozen 时 warning)。建议(可选)在 engine 构建时若检测到 frozen 参数且 dcp_ignore_frozen_params=True 打一条 rank0 warning,避免用户静默拿到缺 MTP 的 DCP。
if engine.has_freeze_params and model_cfg.dcp_ignore_frozen_params:
    log_rank0.warning("Frozen params exist but dcp_ignore_frozen_params=True; "
                      "they will be omitted from DCP checkpoints.")

(has_freeze_params 已在 train_engine.py:162 存在,接入成本一行。)

结论边界

  • 本报告全部"已确认"结论基于只读源码追踪(行号见上),未运行任何代码/测试/GPU。
  • 证据索引中的 NATIVE_ONLINE_4X4 / FULL_TRAINER_RESTORE 等 PASS 结果属于集成运行栈(core4876+9bdb+loader 修复),其生产代码与公开 10d89 对应文件逐字节相同(索引原文),可作强参照,但不等同于"公开 10d89 树的独立完整验收";且冷恢复被用户缩减(2 组×K2、无第三次更新)。
  • 未核对路径:frozen MTP 在 EP>1 / domino EP 下的实际执行(源码上 MTP 分支整体不进入,推断安全);GLM52/53 非 share_weights 的 frozen 组合(GLM53 强制 share_weights=True,glm53.py:198)。
  • 中间产物:按要求本轮不执行清理;架构 HTML 保留在 /tmp/architecture-review-xt2292-20261111.html。

报告生成:2026-11-11,审阅者:Kimi CLI 独立审阅。


Follow-up Review — XTuner #2292 修复复审(增量 base 10d89ad → head 80a7270)

  • 增量范围: 单 commit 80a72703 docs(rl): link native frozen MTP tutorial from navigation,1 文件 +1/-0:docs/en/rl/advanced_tutorial/index.rst。
  • 修复对象: 原报告 X2292-F01(英文 toctree 未挂 native_frozen_mtp.md,orphan 页面)。
  • 用户限定: 仅修英文 toctree;生产运行代码不变;中文翻译未新增、不作为本轮功能门禁;不重复伪装 GPU 验收。
  • GLOSSARY/ADR: 与原报告一致,仓库实际不存在,无新增可核对项。
  • 证据: 全部为本仓库 80a7270 工作树只读核对(行号见下),未运行代码/构建/GPU。

Summary

修复与 X2292-F01 的解决建议逐字一致,已解决,无新问题。原报告其余条目(F02–F08)均非本轮承诺修复项,状态不变。

核对明细

检查项 结果 证据
toctree 新增条目 ✅ 已加入,位置合理(append 在 on_policy_distillation.md 之后) docs/en/rl/advanced_tutorial/index.rst:12
缩进一致性 ✅ 3 空格缩进与既有条目一致 index.rst:7-12
目标页存在 ✅ docs/en/rl/advanced_tutorial/native_frozen_mtp.md 存在于 80a7270 树 工作树 ls 确认
生产代码零改动 ✅ diff stat 仅 1 个 .rst 文件,无 .py/.yaml 变更 git diff 10d89ad..80a7270 --stat
文档自身内容 未变(本轮仅挂链) diff 仅 +1 行
zh_cn 翻译 未新增(用户明示不作门禁) docs/zh_cn/rl/advanced_tutorial/ 无对应文件,记录备查

剩余观察(非阻塞)

  • zh_cn 缺失(原 F01 第二部分):按用户指令本轮不作功能门禁;若后续要求双语一致,需补 docs/zh_cn/rl/advanced_tutorial/native_frozen_mtp.md 并在 zh index.rst 挂链。状态:待办,非缺陷。
  • 未执行 Sphinx 构建(只读约束);RST 语法为纯 toctree 条目追加,静态核对无 orphan 风险残留。

结论

报告生成:2026-11-11,审阅者:Kimi CLI 独立复审。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant