fix(glm): align and diagnose cross-framework router parity - #3635
Merged
Conversation
Contributor
Author
|
/ok to test 50b6edd |
Contributor
Author
|
/ok to test aca8222 |
…y-diagnostics Signed-off-by: Yuhe Zhang <yuhez@nvidia.com> # Conflicts: # tests/functional_tests/checkpoint_robustness/test_checkpoint_robustness_llm.py
Contributor
Author
|
/ok to test 8615128 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test 75a7ce0 |
@yuhezhang-ai, there was an error processing your request: See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/ |
Contributor
Author
|
/ok to test 75a7ce0 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test 420b9b3 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test 1057047 |
…y-diagnostics Signed-off-by: Yuhe Zhang <yuhez@nvidia.com> # Conflicts: # tests/unit_tests/checkpoint/test_optimizer_state.py
Contributor
Author
|
/ok to test babe3fa |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
…y-diagnostics Signed-off-by: Yuhe Zhang <yuhez@nvidia.com> # Conflicts: # tests/unit_tests/ci_tests/test_checkpoint_robustness_hf_kwargs.py
Contributor
Author
|
/ok to test f0772b5 |
The shared MLA is reused by DeepSeek-V3, Mistral 4, and GLM MoE Lite, so a hidden epsilon default would let a future family silently inherit numerics it never chose. Each Block now states its checkpoint contract explicitly; all current upstream implementations construct the two latent RMSNorms with the Hugging Face reference default of 1e-6 rather than config.rms_norm_eps, and the HF config carries no field for it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test 8b6c1c1 |
akoumpa
approved these changes
Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR has three distinct scopes:
It also enables AutoModel-side checkpoint-robustness coverage for GLM 5.2. This PR was originally stacked on #3620; that base is now merged.
Production model fixes
GLM 4.x
glm4_moe_lite) now uses the upstream fixed1e-6epsilon for its query and key/value MLA latent RMSNorms instead of inheriting the decoder-wide epsilon.glm4_moe, including the GLM 4.5 Air family, andglm4_moe_lite) now own their upstream router precision policy: the gate projection defaults to FP32 and selected mixture weights remain FP32.GLM 5.2
1e-6epsilon, independently of the decoder block'srms_norm_eps=1e-5.e_score_correction_biasis included in the strict FP32 load contract.Shared MLA latent norm epsilon
latent_norm_epsas a required keyword-only parameter with no default, so every model states its checkpoint's contract at the call site instead of silently inheriting a shared-layer default. The value cannot come from config: upstream Hugging Face MLA implementations construct these two norms without an epsilon argument, inheriting the reference RMSNorm default of1e-6, whileconfig.rms_norm_epsonly governs the decoder-block norms and the HF config carries no separate field.glm4_moe_lite,deepseek_v3, andmistral4now pass1e-6explicitly. For Mistral 4, whose checkpoints shiprms_norm_eps=1e-5, the latent norms previously inherited that decoder epsilon; they now match upstream's1e-6, the same correction as GLM. DeepSeek V3 is numerically unchanged (rms_norm_epsis already1e-6);glm_moe_dsaanddeepseek_v32own their norms directly and are unaffected by the shared signature.General Adam/AdamW resume correctness
Adam creates per-parameter state lazily, after a parameter first receives a gradient. A trainable parameter that is unused in a step can therefore be present in the optimizer parameter groups but lack
step,exp_avg, andexp_avg_sq. The flattened DCP save/load path expected a complete optimizer-state skeleton and could fail to restore such a checkpoint.OptimizerState.state_dict()now materializes zero-valued lazy Adam state before both native and flattened DCP serialization. This is a general Adam/AdamW checkpoint fix, not a GLM-specific workaround, and zero initialization preserves the behavior of the parameter's future first update.Checkpoint-robustness coverage
GLM 4.7 Flash
relaxedprofile only for HF-source -> AutoModel and HF-export -> AutoModel reload. AutoModel consolidated reload and native resume remain on the standard/exact correctness gates.GLM 5.2
GBS=512,LBS=4) and 512 samples, enough to form a complete global batch at DP64.0.0049at 512 tokens (standard-profile pass) and0.0071/0.0065at 2K / 4K, with p95 within the standard profile and no divergent-token tail.relaxedsame-implementation profile (mean_kl <= 0.02,p95_kl <= 0.05) plus the one metric not covered by that profile, a model-specificcosine >= 0.985override. This does not relax native resume or other same-implementation comparisons.Harness and diagnostic changes
GLM 4.7 Flash diagnosis
The identical-input 2,048-token probe found no single discontinuous layer. Every local block remained close to HF (cosine at least about
0.99993), while exact router-set agreement was about98.4-99.7%per routed layer. The production-fix scoped run measured:The 70 tokens with no self-route flips had mean KL
0.0101, versus0.3290for tokens with one or more flips. This is an empirical floor rather than a pure routing-free control because causal attention can propagate earlier-token route differences.Route replay separates the remaining error sources:
AutoModel replaying its own captured indices and weights was exactly identical. The evidence shows that route bifurcation is the dominant tail amplifier, route-weight differences also matter, and a smaller continuous cross-framework residual accumulates through the routed layers; it does not identify a remaining correctness mismatch.
Changing only vanilla HF's total forward length reproduced the same sensitivity: at 512 tokens,
KL(HF@4096[:512] || HF@512)was0.1498, versus matched-shape HF-to-AutoModel KL0.1528. Qwen3-30B-A3B had a similar number of near-tie route flips but mean self-KL only0.0024, showing why flip count itself is diagnostic evidence rather than a correctness threshold.GLM 5.2 indexer training scope
The native-resume failure exposed by this PR and the desired training behavior are separate issues:
grad=None; that is what exposed the missing lazy Adam state during checkpoint restore.References: DeepSeek-V3.2 DSA training recipe and GLM-5 report.
Scoped CI
GLM 4.7 Flash
The first exact scoped run (parent 64048635, job 407983121) ran the ordinary 50-step recipe and all robustness phases:
Native DCP resume was exact on all eight ranks: steps 5-7 had zero loss difference, and all parameter, buffer, optimizer, gradient, and post-step digests matched. The calibrated rerun (parent 64054805, job 407998642) passed.
GLM 5.2
The first exact-head run (parent 64724314, retry 413471549) reached all requested phases after an initial rendezvous failure:
mean_kl=0.0073655,p95_kl=0.0297506, andcosine=0.991423.Commit
105704756added the general optimizer-state fix, initial Phase 2 bounds, and a complete 512-sample global batch. The conflict-free rerun (parent 64884019, leaf job 414485914) completed ordinary training and all robustness work, despite being summarized as an infrastructure issue:mean_kl=0,p95_kl=0,cosine=1).mean_kl=0.00889297,p95_kl=0.0375951, andcosine=0.989929. Mean and p95 passed the initial explicit bounds; cosine missed0.99by about0.000071.Commit
2374374bbfixes that harness-only comparison. Merge commitf0772b5deresolves the latestmainconflict and simplifies the consolidated-reload policy to the sharedrelaxedprofile plus only the model-specific cosine override (0.985). Native resume remains on the standard profile and requires exact restored state before the first resumed update.The final single-job scoped rerun passed against the verified conflict-free merge commit: parent pipeline 64902857, generated pipeline 64903663, leaf job 414650566.
mean_kl=0,p95_kl=0,cosine=1).mean_kl=0.00867099,p95_kl=0.03702399, andcosine=0.99011834; reload self-repeat was exact.0.00091209at step 6 and0.00099553at step 7, using at most17.1%and19.5%of the standard allowed difference; there were no tolerance violations. Gradient and post-step digests were not bitwise identical under this HybridEP/PP topology, so this establishes exact restore plus bounded standard-profile trajectory continuation, not bitwise-exact post-update execution.Local validation
git diff --checkand Ruff checks passed on the changed Python files.2 passed).relaxedtoautomodel_reloadand preserves the cosine override as the float0.985.Follow-up intentionally deferred