feat(glm5-next): add GLM-5.3-Flash training support - #3699
Conversation
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
|
🌿 Preview your docs: https://nvidia-preview-preview-636bf0bc2ef1.docs.buildwithfern.com/nemo/automodel |
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
|
Non-blocking — sharing two findings from poking at this PR. I'll follow up with the checkpoint-robustness CI enablement separately. 1. The checkpoint loading path probably needs further optimization. Loading OOMs at 1 node (ep8) and 2 nodes (ep16) with the same ~77 GB/rank footprint — it doesn't shrink with EP, so something dense seems to materialize per-rank before sharding. Everything works at your 9-node EP72 layout, but right now ~9 nodes is the floor even for forward-only use. Happy to help dig if useful. 2. GLM-5.3-Flash does not have the GLM-4.7-Flash numerical-sensitivity issue. Context: 4.7-Flash's released checkpoint amplifies tiny numerical noise through its MoE routing, which is why its parity CI needed a special profile — so I was curious whether the new Flash inherits that. I ran the same probes on 5.3-Flash at EP72 on the SDPA path. These are self-sensitivity measurements (the model compared against itself under sequence-shape changes and forced routing flips), not HF parity. Result: divergence stays at the healthy floor (mean KL 0.005–0.008 across 128–4096 tokens, worst token 0.35), and an injected routing flip dies out with depth (0.0065 at layer 2 → 0.0006 at layer 38) instead of amplifying. Same healthy class as GLM-5.2 — good news. Minor note: the cuDNN-DSA/FlashMLA runtimes aren't in the image build, so CI will take the SDPA path (same path as your CP1/CP8 validation runs). If the cudnn path should ever be CI-covered, the runtimes would need adding to the Dockerfile the way DeepEP/TileLang are. |
|
/ok to test e3c3cac |
Keep the base installation importable without VLM or FLA extras, add regression coverage for the torchvision-free path, and register the new architecture in model coverage docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
Follow the existing zai-org to thudm documentation slug mapping so recipe documentation coverage recognizes the model card. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: HuiyingLi <willwin.lee@gmail.com>
|
/claude review |
Review summaryThorough, well-structured onboarding of the GLM-5.3-Flash VLM. Registry wiring ( Two findings:
Neither is blocking. |
| def forward(ctx, local_tensor: torch.Tensor, group: Any, dim: int) -> torch.Tensor: | ||
| dim = dim if dim >= 0 else local_tensor.ndim + dim | ||
| gathered = [torch.empty_like(local_tensor) for _ in range(dist.get_world_size(group))] | ||
| dist.all_gather(gathered, local_tensor.contiguous(), group=group) | ||
| ctx.group = group | ||
| ctx.dim = dim | ||
| ctx.rank = dist.get_rank(group) | ||
| ctx.local_size = local_tensor.shape[dim] | ||
| return torch.cat(gathered, dim=dim) | ||
|
|
||
| @staticmethod | ||
| def backward(ctx, grad_output: torch.Tensor): |
There was a problem hiding this comment.
These new torch.autograd.Function methods accept tensors but have no docstring documenting their layout. Per the tensor-contract rule, custom autograd forward/backward methods must document each tensor input's shape/axis order. Please add Google-style Args/Returns sections:
_AllGatherSequence.forward—local_tensoris the per-rank sequence shard (e.g.[batch, local_sequence, ...], gathered alongdim); state which axisdimindexes and that the return is[batch, global_sequence, ...]._AllGatherSequence.backward—grad_outputis the gathered-tensor gradient[batch, global_sequence, ...]; return is the local shard[batch, local_sequence, ...]._AllGatherBackwardAnchor.forward/backward(below) —gathered/grad_outputlayouts.
The all_gather_sequence/all_gather_backward_anchor wrappers also carry only a one-line docstring with no tensor layout.
|
/ok to test 636bf0b |
What does this PR do ?
Adds native AutoModel training support for zai-org/GLM-5.3-Flash, including its hybrid Kimi Delta Attention (KDA) / DeepSeek Sparse Attention (DSA) decoder, MoE routing, VLM processing, Hugging Face checkpoint conversion, and packed-sequence context parallelism.
The included MedPix recipe uses the validated EP72/CP2 topology: TP1, PP1, 9 nodes / 72 GPUs, packed sequence length 2048, and 100 optimizer steps. It now selects the shared FlashMLA-forward/cuDNN-backward kernel for sparse MLA layers; KDA layers remain on FLA.
Important
Full-model single-GPU checkpoint loading and training are not supported. The supported base-checkpoint initialization path is distributed DCP loading.
User training does not require Transformers 5.16 or a nightly build. This implementation supports AutoModel's pinned
transformers==5.12.1, provides its own GLM-5.3 configuration and processor registration, and does not requiretrust_remote_code.Changelog
D=576, top-k <= 2048 contract.Validation
Hugging Face numerical parity
Reference setup:
5.16.0.dev0Packed CP1 / CP8 full-model training parity
Both full-model runs use commit
e3c3cacad2e8eaadda6c38c19d859a973587f604,mmoukouba/MedPix-VQA, packed sequence length 2048, global batch size 144, local batch size 1, TP1, PP1, and the SDPA sparse-attention reference. Both completed 100/100 optimizer steps with clean Slurm exits.Across all 100 matched steps, CP8 versus CP1:
0.0018790.0028000.0130at step 931.2344, CP81.2328(absolute difference0.0016)cuDNN sparse MLA parity and performance
The released checkpoint uses 64 query heads, a 512-wide latent K/V,
index_topk=2048, andindex_kpool=4, producing 2051 raw sparse slots before FlashMLA alignment.H100 shared-kernel stress test (
D=512, rawK=2063, larger than the released model's 2051 slots):Full native GLM-5.3 sparse layer versus the SDPA reference (
seq=64,D=512, rawK=2051, BF16):Single-node distributed training smoke test:
backend.attn=cudnn, activation checkpointing enabled10.7592,11.233913.29 GiB, then17.26 GiBFull-model, same-commit end-to-end comparison:
e3c3cacad2e8eaadda6c38c19d859a973587f604cuDNN versus SDPA:
+13.26%; median TPS:+13.32%-3:57/-10.60%-3:54/-9.88%-237.69 s/-10.43%+0.025 GiB/GPUfor cuDNNThe two 100-step loss curves remain aligned: mean absolute difference
0.002648, RMSE0.003076, maximum absolute difference0.0066at step 73, and final loss SDPA1.2359versus cuDNN1.2337.Runtime used
nvidia-cudnn-frontend[cutedsl]==1.27.0and FlashMLA b7643bd on H100 with CUDA 13.3.GLM-5.2 cuDNN regression: PR base versus head
This checks the GLM-5.2 path touched by the shared sparse-attention utility refactor. Both runs use the same nightly image without rebuilding,
nvidia-cudnn-frontend[cutedsl]==1.27.0, FlashMLA b7643bd, and the same training configuration:zai-org/GLM-5.2on the Tulu-3 SFT mixture (train[:100000])backend.attn=cudnn; W&B disabled for this scoped NeMo-CI regression8c954f67e3c3cacaAcross all 100 matched steps, head versus base loss parity is:
0.0000910.0001360.0006at compilation step 00.5357, head0.5356(absolute difference0.0001)The steady-state throughput and memory deltas are effectively neutral. The shorter head training-loop time is explained by run-to-run first-compilation variation; it is not treated as a steady-state speedup.
Unit tests
Result:
35 passed, 3 skippedin the interactive development container. The skipped cases require real optional GPU kernels; the H100 results above exercise those kernels directly.Before your PR is "Ready for review"
Pre checks:
Additional Information
transformers==5.12.1; no upgrade to 5.16/nightly and notrust_remote_codeare required.backend.attn=cudnnseparately requires bothnvidia-cudnn-frontend[cutedsl]and a compatible FlashMLA build; these kernel dependencies are independent of the Transformers version. Environments without them can selectbackend.attn=sdpa.