Repository navigation
feat(model): add GLM-5.3-Flash support - #6044
HollowMan6 wants to merge 8 commits into
Conversation
a38eef8 to
fb5ee38
Compare
|
Bug: the MTP In AutoMapping(
f"{mtp_mg}.final_layernorm.weight",
"model.language_model.norm.weight",
),The GLM-5.3-Flash checkpoint has its own
The GLM-4.5 bridge maps the same tensor from Suggested fix: AutoMapping(
f"{mtp_mg}.final_layernorm.weight",
- "model.language_model.norm.weight",
+ f"{mtp_hf}.shared_head.norm.weight",
),How we found it: we round-tripped a tiny GLM-5.3-Flash through this bridge. It had 4 HF layers built from the real config, with random weights and every norm randomized so no two were equal. We imported it, then exported it with ModelOpt's Megatron→HF exporter (NVIDIA/Model-Optimizer#2539).
This was on the |
|
Thank you @kevalmorabia97, this is now fixed in e6f7cf2 |
…ash code @HollowMan6 wrote NVIDIA/Megatron-LM#7054/#7521/#7522 (mcore_ext), NVIDIA-NeMo/Megatron-Bridge#6044 (the upstream counterpart of glm5_next) and vllm-project/vllm#56327; @hershg wrote vllm-project/vllm#56718. Name Megatron-Bridge#6044 in the removal plan as the PR that retires glm5_next. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…MoE, full fine-tuning and LoRA sync to vLLM (merge_lora=false) (#2179) ## What Adds GLM-5.3-Flash (HF `glm5_next`, `Glm5NextForConditionalGeneration`) to the Megatron backend, for both full fine-tuning and LoRA training with adapter-only weight sync to vLLM (`merge_lora=false`). The architecture is new to both upstreams: 45 layers of 3:1 KDA linear attention / NoPE-MLA DeepSeek sparse attention with a k-pool compressed indexer, a 288-expert sigmoid MoE with one shared expert (dense MLP in the first layer), clamped SwiGLU, and manifold-constrained hyper-connections (mHC) on every block. It ships as a VL checkpoint, and SkyRL trains the language model only (`language_model_only=True`). No dependency pins change: this runs on `main`'s vLLM 0.30.0, megatron-core and megatron-bridge. What the pinned upstreams don't have yet is vendored under `patches/`. **Credit:** most of the vendored code comes from @HollowMan6's open upstream PRs: NVIDIA/Megatron-LM#7054, #7521 and #7522, NVIDIA-NeMo/Megatron-Bridge#6044 (the upstream home for `glm5_next/`), and vllm-project/vllm#56327. The MLA prefill LoRA fix is @hershg's vllm-project/vllm#56718. Each vendored section credits them in its module docstring. ## Components ### `patches/megatron/mcore_ext/`: megatron-core pieces (vendored from open Megatron-LM PRs) | module | upstream | what | |---|---|---| | `kda.py` | NVIDIA/Megatron-LM#7054 | `KimiDeltaAttention`: TE linears, depthwise causal convs, fp32 `A_log`/`dt_bias`, fla `chunk_kda`, gated output norm. TP over heads, packed THD via `cu_seqlens`. | | `hyper_connection.py` | #7521 | megatron-core's `HyperConnectionModule` with GLM's standard-RMSNorm input norm. | | `mhc_transformer_layer.py` | #7521 | `HyperConnectionTransformerLayer` with **MoE** sub-layers (upstream's layer rejects MoE). | | `dsa_kpool.py` | #7522 | The k-pool DSA indexer kernels, copied verbatim. | ### `patches/megatron/glm5_next/`: the Megatron-Bridge model - `provider.py`: `Glm5NextModelProvider`, with the KDA, mHC and k-pool fields. - `layer_specs.py`: per-layer KDA-or-DSA × dense-or-MoE mHC specs. - `dsa.py`: `Glm5NextDSAIndexer` (k-pool gate/ape and gate score) and `Glm5NextDSAttention`. - The pinned `DSAttention.forward` does its own token-level top-k and never calls the indexer's `forward_with_scores`. - So `Glm5NextDSAttention` swaps that step for `fused_qk_topk_kpool`, and raises if the pooled selection doesn't run exactly once. - `bridge.py`: `Glm5NextBridge` maps all 3050 language-model tensors 1:1, including the mHC scale mappings and the k-pool compression parameters. **`patches/megatron/README.md` is the removal plan.** For each vendored module and runtime patch it gives: - the upstream change that retires it; - how to check whether a new pin already contains it; - every touchpoint outside `patches/` that has to change with it; - the tests to run. It's linked from `AGENTS.md` for megatron-core / megatron-bridge bumps. ### `patches/vllm/patch_glm5next_lora_packing.py`: vLLM LoRA for GLM-5.3-Flash Mostly a backport of vllm-project/vllm#56327 and #56718, applied in every vLLM worker before model init: - the Glm5Next `packed_modules_mapping`; - `replicated_shard_ids` honored for KDA's duplicated `f_a`/`g_a` LoRA-B; - a `.contiguous()` guard in `add_shrink`; - the `kv_b_proj` adapter on MLA's absorbed decode path, which decode would otherwise drop entirely; - the `kv_b_proj` adapter on MLA's MHA prefill path and prefix-cached context chunks (#56718). - The attention impl keeps a pre-LoRA reference to `kv_b_proj`. So every prompt longer than `reorder_batch_threshold` (128 tokens at TP4/TP8) was prefilled without the adapter. - The patch swaps in a LoRA-applying proxy for the duration of `forward_mha`, rather than rewriting five method signatures. ### Other SkyRL changes - `MegatronWorker.init_configs`: mHC models downgrade SkyRL's default `recompute_granularity="full"` to selective. megatron-core rejects mHC under full recompute, and its suggested `'mhc'` selective mode needs recompute managers the vendored layer doesn't thread. - `model_bridges.py` registers the bridge. - `SKYRL_VLLM_START_PORT` makes the vLLM base port overridable, for hosts where port 8000 is taken. - `CUDA_HOME` is forwarded to Ray actors, since TileLang JIT picks its toolkit from it. - Non-JSON data-plane responses are logged at warning level with the body. - Tests: - GLM-5.3-Flash rows in `gpu_ci/megatron/test_megatron_models.py`: the 4-layer slice, and the same slice past `index_topk`. - `glm-5.3-flash-4layer_h100_tp2_ep4_adapter` in `gpu_ci/megatron/test_megatron_lora_models.py`: #2275's zero → perturb → publish LoRA roundtrip, with GLM's trainer and vLLM target modules. - A GLM LoRA case in full-trainer checkpointing. - **Tests for `patches/` code now mirror its layout**, so they're found and deleted with the patch: - CPU: `tests/backends/skyrl_train/patches/megatron/mcore_ext/test_dsa_kpool_math.py`. Now marked `megatron`; before, it never ran in CI. - GPU: `tests/backends/skyrl_train/gpu/gpu_ci/patches/megatron/`, with `mcore_ext/test_dsa_kpool.py`, `mcore_ext/test_modules_vs_hf.py` (KDA/mHC vs HF), `test_dsa_index_share_recompute.py` and `test_shared_expert_lora_tp.py`. - The FSDP GPU job ignores `gpu_ci/patches/megatron`, as it already does `gpu_ci/megatron`. - Examples: `examples/train/glm5_3_flash/`. - `run_gsm8k_glm5p3_flash_lora_1node.sh`: a single-node GSM8K LoRA smoke run. - `run_dapo_glm5p3_flash_lora_sync_2node.sh`: a 2-node DAPO 2k/8k LoRA recipe with `merge_lora=false`, and R3 behind `ENABLE_ROUTING_REPLAY`. - `run_dapo_glm5p3_flash_fullft_sync_8node.sh`: the 8-node full fine-tuning recipe validated below, with R3 on by default. - Docs: `supported_models.mdx`, the Megatron backend agent doc, fixed CPU test commands in `AGENTS.md` / `testing.md`, and the `tests/.../patches/` convention in `testing.md`. ## Validation Megatron vs vLLM logprob parity on the 4-layer slice (`eatang/GLM-5.3-Flash-4layer`), TP2 EP4, threshold 0.1: | row | Megatron vs vLLM | vLLM pre/post weight sync | |---|---|---| | `glm-5.3-flash-4layer_h100_tp2_ep4` | 0.065 | 0.254 | | `..._kpool_beyond_topk` (sequences past `index_topk`=2048) | 0.053 | 0.348 | The k-pool row measured 0.059 before the `DSAttention` top-k swap, when the pooled indexer wasn't actually used in training. LoRA roundtrip (`glm-5.3-flash-4layer_h100_tp2_ep4_adapter`, `merge_lora=false`, LoRA-B std 0.008): | phase | diff | check | |---|---|---| | zero adapter: vLLM vs Megatron | 0.068 | < 0.1 | | perturbed trainer vs stale sampler | 0.155 | > 0.1 | | synced adapter: vLLM vs Megatron | 0.062 | < 0.1 | Before the #56718 backport, the synced-adapter diff grew with the adapter (0.18 at std 0.01). That fits vLLM prefilling without the `kv_b_proj` adapter. Also passing: - `test_modules_vs_hf.py`: mHC matches HF to 4e-9; KDA on packed sequences matches the per-sequence HF reference. - `test_dsa_kpool.py` and `test_dsa_kpool_math.py`. Full model, DAPO 2k/8k recipe, 8×8 B200, TP4 / DP16. Held-out AIME-2024 `avg_score` (30 problems × 12 samples; step-0 evals across runs spread about ±0.03): | step | 0 | 5 | 10 | 15 | 20 | 25 | 30 | 35 | |---|---|---|---|---|---|---|---|---| | **full fine-tuning, R3** (EP32 × ETP2, LR 1e-6) | 0.072 | 0.300 | 0.494 | 0.572 | 0.617 | 0.672 | **0.711** | | | LoRA `merge_lora=false`, R3 (EP16) | 0.083 | 0.183 | 0.511 | 0.622 | 0.639 | **0.656** | 0.478 | 0.261 | | LoRA `merge_lora=false`, R3 off (EP16) | 0.106 | | | | | 0.483 | | | - **Full fine-tuning:** every step syncs the full ~599 GiB of weights to vLLM, in about 45 s. - The rollout/train logprob gap stayed at 0.007-0.010 for all 30 steps while every weight changed, so vLLM always served the trained weights. - Held-out AIME was still rising at step 30. Entropy held at 0.18-0.25 and response length stayed steady, with none of the LoRA run's late overfitting. - Steps took 15-21 min. At EP32 × ETP1 the backward's DSA softmax recompute ran out of memory at step 7; ETP2 halves the per-GPU expert params and grads. - **R3 off:** policy entropy collapsed to about 0.02 early on, and the run learned slowly. The same thing happens on this cluster with the earlier fork-based megatron-core / vLLM 0.28 stack, at both DP16 and DP4. - **R3 on:** the rollout/train logprob gap is about 4× smaller (0.009 vs 0.039 at step 1) and entropy stays up. Held-out AIME peaks at 0.656 at step 25. For comparison, an earlier fork-based-stack run on B300 without R3 reached 0.561 at step 25. - Past step 25 training reward keeps rising, but held-out accuracy falls and entropy climbs to about 0.77. That's overfitting. - For longer runs, stop around step 25, or add entropy control / a lower LR, and use `ckpt_interval=5`. - This is why the DAPO recipe documents R3 as recommended. ## Known limitations - The LoRA DAPO runs above predate the #56718 backport, so their rollouts prefilled prompts over 128 tokens without the `kv_b_proj` adapter. That may account for some of the LoRA run's late collapse. Full fine-tuning is unaffected. - `f_b_proj` / `g_b_proj` stay out of both LoRA target lists. - KDA has no context parallelism and no inference cache. - mHC requires PP=1 and doesn't support selective `layernorm`/`mlp`/`mhc` recompute. - Cross-layer DSA index sharing raises. The 4-layer slice and the full checkpoint use only `"full"` indexers. - `patches/megatron/patch_mla_thd_v_pad.py` isn't applied by anything. This PR doesn't change that; the README flags it for a decision. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Eric Tang <erictang000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Two training-loop failures with GLM-5.3-Flash ( Setup:
Iteration 1 trains fine. Loss is finite and grad norm 1.92. Then: 1. Saving a checkpoint with the distributed optimizer asserts
2. With the non-distributed optimizer, iteration 2 asserts in the grad buffer With That looks like some parameters never receive a gradient in iteration 1. I haven't isolated which ones. The DSA indexer, whose training goes through its own loss, is a candidate. Both happen without any quantization. Running the same job with a plain BF16 student, no ModelOpt quantizers involved, gives the identical assertion Workaround we used: one iteration, |
|
@kevalmorabia97 For 1, you should be able to fix it by patching this dev commit to main NVIDIA/Megatron-LM@ceaa6c5, for 2, that's a good catch and now it should be fixed with NVIDIA/Megatron-LM@bfb1773 |
e353ca3 to
2a13240
Compare
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
Signed-off-by: Hollow Man <hollowman@opensuse.org>
4edf36d to
e8202eb
Compare
Pending on:
What does this PR do ?
Add HF ↔ Megatron support for GLM-5.3-Flash (
model_typeglm5_next,Glm5NextForConditionalGeneration): a unified bridge, provider, and VLM wrapper for its hybrid KDA/DSA + MoE + mHC language model with a replicated HF vision tower, plus the shared conversion, PEFT, and packed-sequence pieces it needs.Changelog
GLM-5.3-Flash (
src/megatron/bridge/models/glm5next/)GLM53FlashBridge,GLM53FlashModelProvider, andGLM53FlashModel, registered forGlm5NextForConditionalGenerationwithmodel_type="glm5_next"and exported frommegatron.bridge.models.hybrid_layer_patternfrom the HFlayer_types/mlp_layer_types: each HF decoder layer becomes two physical layers (KDAKor DSADattention at2N, dense-or MoEEFFN at2N+1), withmoe_layer_freqderived per physical module andnum_hidden_layersrecovered from the pattern on export.qk_pos_emb_head_dim=0,kv_channels=v_head_dim), the kpool DSA indexer (FP8 kpool;index_kpool/index_kpool_always_select_tailread from the HF config), KDA two-stage low-rank gates withgate_lower_bound, mHC multi-stream hyper-connections with fp32 mappings, sigmoid routing with expert bias and an always-on shared expert (moe_shared_expert_gate=False), grouped GEMM with the HybridEP flex dispatcher, and a one-layerDEMTP using the repeated-layer spec.in_proj/conv1dbuilt from separate HF Q/K/V tensors with section-wise TP sharding (_ColumnParallelConcatMapping), MLA projections and indexer weights, dense and MoE FFN (grouped-GEMM and sequential expert layouts), mHChc_{attn,ffn}_{fn,base,scale}, and the MTPeh_projsplit intoe_proj/h_proj(_EhProjSplitMapping, import only).Glm5NextVisionModelon pre-process ranks, image/video features scattered into the embeddings before THD packing and the sequence-parallel scatter, text-only fallback when no pixel inputs are given, andfreeze_{language_model,vision_model,vision_projection}options.Hybrid providers
HybridMLAModelProvider(HybridModelProvider+MLATransformerConfig). Withpipeline_model_parallel_size > 1and DSA layers in the pattern, it inserts balanced|separators only before full-indexer DSA layers so IndexShare groups never cross a stage, validates user-provided separators, and rejectsnum_layers_in_first/last_pipeline_stage.scatter_embedding_sequence_paralleltoHybridModelProvider(defaultTrue, matchingHybridModel) and pass it through; the VLM provider sets it toFalseso vision features are injected before the SP scatter.Shared conversion infrastructure
HCAlphaMapping, mapping an HF[3]hc_*_scaletensor to Megatron'salpha_pre/alpha_post/alpha_res(index 0 exports all three), and migrateDeepSeekV4Bridgefrom its private_HCAlphaMapping/_HCAlphaSecondaryMappingto it with equivalent import/export behavior.InitOnlyMappingfor Megatron params with no HF counterpart (import keeps init, export is a no-op).MegatronModelBridge._prefix_mapping_registryto re-key a text-model registry under a VLM prefix while keeping nested_tp_mappingnames in sync.PEFT
in_projLoRAlinear_outweights by Q/K/V section sizes whenkda_two_stage_gatesis set, instead of the GQA-stylesplit_qkv_weightspath, so KDA LoRA adapters export correctly.Packed sequences
preprocess_packed_seqsfrommodels/qwen_vl/modelling_qwen3_vl/utils.pytotraining/utils/packed_seq_utils.py(shared by Qwen3-VL and GLM-5.3-Flash) and adduse_fp8_padding, which aligns each sequence tolcm(16, align)and the packed total toalign * 128.Tests
tests/unit_tests/models/glm5next/test_glm53flash_mapping.py: provider precision contract and multimodal config copy,language_model.prefixing of text mappings,HCAlphaMappingimport/export and wildcard resolution, section-wise KDA TP sharding round-trips (TP 1 to 16).tests/unit_tests/models/qwen_vl/modelling_qwen3_vl/test_utils.py: packed-sequence alignment and gradient flow with and without FP8 padding.tests/unit_tests/models/test_model_bridge_lora.py: KDA Q/K/V LoRAlinear_outsplit.GitHub Actions CI
See the CI section in the Contributing doc for how to trigger the CI. A Nvidia developer will need to approve and trigger the CI for external contributors.
Before your PR is "Ready for review"
Pre checks:
Glm5NextForConditionalGenerationis imported behind atry/exceptthat falls back to the class name,Glm5NextModel/Glm5NextVisionModelare imported lazily insideGLM53FlashModel.__init__, and the new unit tests usepytest.importorskipon the GLM-5.3-Flash config module.Additional Information
glm5_nextmodel family ships in transformers v5.17.0;pyproject.tomlcurrently pinstransformers<=5.15.0, so on the pinned version the bridge only resolves by class name, the VLM wrapper cannot be instantiated, and the new unit tests are skipped. The pin bump should go in a separatebuild:PR per the contributing guide.preprocess_packed_seqsmoved without a compatibility re-export from its old Qwen3-VL module.docs/models/glm/page and README / docs model tables, recipes and examples, verification card, and a functional HF ↔ Megatron round-trip test.