mcore-bridge 1.6.4__tar.gz → 1.8.0.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/PKG-INFO +5 -5
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/README.md +2 -2
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/setup.py +3 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/__init__.py +6 -6
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/bridge/gpt_bridge.py +170 -12
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/config/__init__.py +1 -1
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/config/model_config.py +108 -55
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/config/parser.py +146 -3
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/__init__.py +1 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/constant.py +5 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpt_model.py +92 -99
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/deepseek_v4.py +81 -20
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/glm4.py +4 -4
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/gpts/glm_moe_dsa.py +41 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/llm.py +1 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/minimax_m2.py +4 -5
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/nemotron_h.py +33 -33
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/olmoe.py +4 -5
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/qwen3_next.py +14 -29
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/qwen3_next_gdn.py +26 -4
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/qwen4_exp.py +294 -23
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/hybrid_model.py +30 -5
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpt_model.py +29 -4
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mm_gpts/__init__.py +3 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mm_gpts/deepseek_v41.py +1852 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/gemma4.py +82 -19
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mm_gpts/glm5_next.py +726 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/llama4.py +4 -11
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/muse_glimmer.py +1 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mm_gpts/nemo_speechlm.py +328 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mm_gpts/nemotron_h_omni.py +379 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen3_5.py +2 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen3_5_gdn.py +2 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen4_exp.py +2 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/utils.py +28 -2
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/__init__.py +4 -2
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/absorbed_mla.py +2 -6
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/dsa_indexer.py +2 -9
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/modules/dspark.py +447 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/modules/engram.py +431 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/modules/engram_fp8.py +239 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/modules/gated_delta_net.py +493 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/gated_self_attention.py +1 -5
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/kernels/__init__.py +3 -1
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/kernels/ple_kernels.py +17 -14
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/kernels/qsa_block_sparse_attn.py +71 -107
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/kernels/qsa_kernels.py +155 -39
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/ple.py +116 -42
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/qsa_indexer.py +68 -21
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/modules/topk_router.py +77 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/transformer_block.py +8 -9
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/transformer_layer.py +70 -17
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mtp.py +711 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/model/mtp_detect.py +188 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/register.py +112 -64
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/patcher.py +0 -65
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/patches/megatron_glm53_dev.patch +592 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/tools/__init__.py +1 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/tools/apply_megatron_patch.py +210 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/tuners/lora.py +78 -98
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/tuners/npu_lora.py +27 -20
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/tuners/patcher.py +10 -1
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/__init__.py +2 -1
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/utils/constants.py +6 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/megatron_utils.py +38 -141
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/utils/quantizer.py +95 -0
- mcore_bridge-1.8.0.dev0/src/mcore_bridge/utils/qwen4_exp_checkpoint.py +395 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/safetensors.py +19 -2
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/version.py +2 -2
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge.egg-info/PKG-INFO +5 -5
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge.egg-info/SOURCES.txt +54 -2
- mcore_bridge-1.8.0.dev0/src/mcore_bridge.egg-info/requires.txt +6 -0
- mcore_bridge-1.8.0.dev0/tests/test_apply_megatron_patch.py +280 -0
- mcore_bridge-1.8.0.dev0/tests/test_deepseek_v41_block32_loading.py +144 -0
- mcore_bridge-1.8.0.dev0/tests/test_deepseek_v41_engram.py +988 -0
- mcore_bridge-1.8.0.dev0/tests/test_deepseek_v41_hybrid.py +598 -0
- mcore_bridge-1.8.0.dev0/tests/test_deepseek_v41_language_only_preprocess.py +114 -0
- mcore_bridge-1.8.0.dev0/tests/test_deepseek_v41_packing_cp.py +194 -0
- mcore_bridge-1.8.0.dev0/tests/test_dsv4_layer_spec_builders.py +102 -0
- mcore_bridge-1.8.0.dev0/tests/test_dsv4_mla_rope.py +46 -0
- mcore_bridge-1.8.0.dev0/tests/test_engram_fp8_tables.py +262 -0
- mcore_bridge-1.8.0.dev0/tests/test_engram_fp8_upstream.py +219 -0
- mcore_bridge-1.8.0.dev0/tests/test_gdn_sp_projection_params.py +173 -0
- mcore_bridge-1.8.0.dev0/tests/test_gemma4_ffpa_attn.py +263 -0
- mcore_bridge-1.8.0.dev0/tests/test_gemma4_per_layer_config.py +96 -0
- mcore_bridge-1.8.0.dev0/tests/test_glm5_hybrid.py +401 -0
- mcore_bridge-1.8.0.dev0/tests/test_glm5_next.py +1448 -0
- mcore_bridge-1.8.0.dev0/tests/test_hybrid_compat.py +144 -0
- mcore_bridge-1.8.0.dev0/tests/test_lora_replicated_base.py +158 -0
- mcore_bridge-1.8.0.dev0/tests/test_lora_row_parallel.py +94 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/tests/test_mllm.py +5 -1
- mcore_bridge-1.8.0.dev0/tests/test_mtp_capabilities.py +134 -0
- mcore_bridge-1.8.0.dev0/tests/test_mtp_checkpoint.py +235 -0
- mcore_bridge-1.8.0.dev0/tests/test_mtp_detection.py +190 -0
- mcore_bridge-1.8.0.dev0/tests/test_mtp_layout_spec.py +267 -0
- mcore_bridge-1.8.0.dev0/tests/test_mtp_runtime.py +557 -0
- mcore_bridge-1.8.0.dev0/tests/test_nemo_speechlm.py +646 -0
- mcore_bridge-1.8.0.dev0/tests/test_nemotron_omni.py +582 -0
- mcore_bridge-1.8.0.dev0/tests/test_npu_grouped_lora_expert_params.py +39 -0
- mcore_bridge-1.8.0.dev0/tests/test_ple_checkpoint.py +147 -0
- mcore_bridge-1.8.0.dev0/tests/test_ple_cp_grad.py +170 -0
- mcore_bridge-1.8.0.dev0/tests/test_ple_kernels.py +131 -0
- mcore_bridge-1.8.0.dev0/tests/test_ple_sp_tp_grad.py +281 -0
- mcore_bridge-1.8.0.dev0/tests/test_qsa_indexer.py +168 -0
- mcore_bridge-1.8.0.dev0/tests/test_qsa_packed_documents.py +58 -0
- mcore_bridge-1.8.0.dev0/tests/test_qsa_sparse_kernels.py +203 -0
- mcore_bridge-1.8.0.dev0/tests/test_qsa_tile_index.py +141 -0
- mcore_bridge-1.8.0.dev0/tests/test_qwen4_exp_checkpoint.py +635 -0
- mcore_bridge-1.8.0.dev0/tests/test_qwen4_exp_mtp.py +382 -0
- mcore_bridge-1.8.0.dev0/tests/test_qwen4_exp_peft_export.py +147 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/tests/test_qwen4_exp_units.py +13 -3
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/tests/test_save_missing_weights_dsv4.py +54 -33
- mcore_bridge-1.8.0.dev0/tests/test_split_cp_inputs.py +83 -0
- mcore_bridge-1.8.0.dev0/tests/test_vision_token_provenance.py +68 -0
- mcore_bridge-1.6.4/src/mcore_bridge/model/gpts/glm_moe_dsa.py +0 -50
- mcore_bridge-1.6.4/src/mcore_bridge/model/mm_gpts/__init__.py +0 -3
- mcore_bridge-1.6.4/src/mcore_bridge/model/modules/gated_delta_net.py +0 -502
- mcore_bridge-1.6.4/src/mcore_bridge/model/modules/mtp_layer.py +0 -453
- mcore_bridge-1.6.4/src/mcore_bridge/model/modules/topk_router.py +0 -21
- mcore_bridge-1.6.4/src/mcore_bridge.egg-info/requires.txt +0 -6
- mcore_bridge-1.6.4/tests/test_qsa_indexer.py +0 -67
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/LICENSE +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/setup.cfg +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/bridge/__init__.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/__init__.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/bailing_hybrid.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/bailing_moe.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/hunyuan.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/gpts/qwen3_emb.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/glm.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/internvl.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/kimi_vl.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/llava.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/minicpmv4_6.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen3_asr.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen3_omni.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/mm_gpts/qwen3_vl.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/compressor.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/hyper_connection_gated.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/modules/multi_latent_attention.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/model/rope.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/tuners/__init__.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/tuners/utils.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/dequantizer.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/env.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/import_utils.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/logger.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/torch_utils.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge/utils/utils.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge.egg-info/dependency_links.txt +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge.egg-info/not-zip-safe +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/src/mcore_bridge.egg-info/top_level.txt +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/tests/test_llm.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/tests/test_ple_fp8_scale.py +0 -0
- {mcore_bridge-1.6.4 → mcore_bridge-1.8.0.dev0}/tests/test_save_missing_weights.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mcore_bridge
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0.dev0
|
|
4
4
|
Summary: MCore-Bridge: Making Megatron training as simple as Transformers
|
|
5
5
|
Home-page: https://github.com/modelscope/mcore-bridge
|
|
6
6
|
Author: ModelScope teams
|
|
@@ -19,12 +19,12 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Requires-Python: >=3.8.0
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: megatron-core<0.
|
|
22
|
+
Requires-Dist: megatron-core<0.21,>=0.18
|
|
23
23
|
Requires-Dist: modelscope
|
|
24
24
|
Requires-Dist: peft<0.21,>=0.11
|
|
25
25
|
Requires-Dist: safetensors
|
|
26
26
|
Requires-Dist: tqdm
|
|
27
|
-
Requires-Dist: transformers
|
|
27
|
+
Requires-Dist: transformers>=4.33
|
|
28
28
|
|
|
29
29
|
# MCore-Bridge: Making Megatron training as simple as Transformers
|
|
30
30
|
|
|
@@ -48,7 +48,7 @@ Requires-Dist: transformers<5.17.0,>=4.33
|
|
|
48
48
|
<p align="center">
|
|
49
49
|
<img src="https://img.shields.io/badge/python-3.12-5be.svg">
|
|
50
50
|
<img src="https://img.shields.io/badge/pytorch-%E2%89%A52.0-orange.svg">
|
|
51
|
-
<a href="https://github.com/NVIDIA/Megatron-LM/"><img src="https://img.shields.io/badge/megatron--core-%E2%89%A50.
|
|
51
|
+
<a href="https://github.com/NVIDIA/Megatron-LM/"><img src="https://img.shields.io/badge/megatron--core-%E2%89%A50.18-76B900.svg"></a>
|
|
52
52
|
<!-- <a href="https://mcore-bridge.readthedocs.io/en/latest/"><img src="https://img.shields.io/badge/docs-latest-blue.svg"></a> -->
|
|
53
53
|
<a href="https://pypi.org/project/mcore-bridge/"><img src="https://badge.fury.io/py/mcore-bridge.svg"></a>
|
|
54
54
|
<a href="https://github.com/modelscope/mcore-bridge/blob/main/LICENSE"><img src="https://img.shields.io/github/license/modelscope/mcore-bridge"></a>
|
|
@@ -138,7 +138,7 @@ Recommended Runtime Environment:
|
|
|
138
138
|
| torch | >=2.0 | 2.8.0/2.11.0 | |
|
|
139
139
|
| transformer-engine | >=2.3 | 2.14.1 | |
|
|
140
140
|
| apex | | 0.1 | Optional |
|
|
141
|
-
| megatron-core | >=0.
|
|
141
|
+
| megatron-core | >=0.18,<0.21 | 0.19.2 | |
|
|
142
142
|
| flash-attn | | 2.8.3/3.0.0b1 | Optional |
|
|
143
143
|
| transformers | >=4.33 | 4.57.6/5.8.1 | |
|
|
144
144
|
| modelscope | >=1.23 | | |
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<p align="center">
|
|
21
21
|
<img src="https://img.shields.io/badge/python-3.12-5be.svg">
|
|
22
22
|
<img src="https://img.shields.io/badge/pytorch-%E2%89%A52.0-orange.svg">
|
|
23
|
-
<a href="https://github.com/NVIDIA/Megatron-LM/"><img src="https://img.shields.io/badge/megatron--core-%E2%89%A50.
|
|
23
|
+
<a href="https://github.com/NVIDIA/Megatron-LM/"><img src="https://img.shields.io/badge/megatron--core-%E2%89%A50.18-76B900.svg"></a>
|
|
24
24
|
<!-- <a href="https://mcore-bridge.readthedocs.io/en/latest/"><img src="https://img.shields.io/badge/docs-latest-blue.svg"></a> -->
|
|
25
25
|
<a href="https://pypi.org/project/mcore-bridge/"><img src="https://badge.fury.io/py/mcore-bridge.svg"></a>
|
|
26
26
|
<a href="https://github.com/modelscope/mcore-bridge/blob/main/LICENSE"><img src="https://img.shields.io/github/license/modelscope/mcore-bridge"></a>
|
|
@@ -110,7 +110,7 @@ Recommended Runtime Environment:
|
|
|
110
110
|
| torch | >=2.0 | 2.8.0/2.11.0 | |
|
|
111
111
|
| transformer-engine | >=2.3 | 2.14.1 | |
|
|
112
112
|
| apex | | 0.1 | Optional |
|
|
113
|
-
| megatron-core | >=0.
|
|
113
|
+
| megatron-core | >=0.18,<0.21 | 0.19.2 | |
|
|
114
114
|
| flash-attn | | 2.8.3/3.0.0b1 | Optional |
|
|
115
115
|
| transformers | >=4.33 | 4.57.6/5.8.1 | |
|
|
116
116
|
| modelscope | >=1.23 | | |
|
|
@@ -45,6 +45,9 @@ if __name__ == '__main__':
|
|
|
45
45
|
url='https://github.com/modelscope/mcore-bridge',
|
|
46
46
|
package_dir={'': 'src'},
|
|
47
47
|
packages=find_packages('src'),
|
|
48
|
+
# The Megatron patch for GLM-5.3 ships inside the package so an installed mcore-bridge can
|
|
49
|
+
# apply it (see mcore_bridge/tools/apply_megatron_patch.py).
|
|
50
|
+
package_data={'mcore_bridge': ['patches/*.patch']},
|
|
48
51
|
python_requires='>=3.8.0',
|
|
49
52
|
classifiers=[
|
|
50
53
|
'Development Status :: 4 - Beta',
|
|
@@ -9,18 +9,18 @@ apply_patch()
|
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from .bridge import GPTBridge
|
|
12
|
-
from .config import ModelConfig, hf_to_mcore_config
|
|
13
|
-
from .model import get_mcore_model
|
|
12
|
+
from .config import MLAModelConfig, ModelConfig, hf_to_mcore_config
|
|
13
|
+
from .model import get_mcore_model, resolve_mtp_config, resolve_mtp_num_layers
|
|
14
14
|
from .tuners import LoraParallelLinear
|
|
15
|
-
from .utils import get_logger, set_random_seed, split_cp_inputs
|
|
15
|
+
from .utils import get_logger, set_random_seed, split_cp_inputs
|
|
16
16
|
from .version import __release_datetime__, __version__
|
|
17
17
|
else:
|
|
18
18
|
_import_structure = {
|
|
19
19
|
'bridge': ['GPTBridge'],
|
|
20
|
-
'config': ['ModelConfig', 'hf_to_mcore_config'],
|
|
21
|
-
'model': ['get_mcore_model'],
|
|
20
|
+
'config': ['MLAModelConfig', 'ModelConfig', 'hf_to_mcore_config'],
|
|
21
|
+
'model': ['get_mcore_model', 'resolve_mtp_config', 'resolve_mtp_num_layers'],
|
|
22
22
|
'tuners': ['LoraParallelLinear'],
|
|
23
|
-
'utils': ['get_logger', 'set_random_seed', 'split_cp_inputs'
|
|
23
|
+
'utils': ['get_logger', 'set_random_seed', 'split_cp_inputs'],
|
|
24
24
|
'version': ['__release_datetime__', '__version__'],
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -7,6 +7,7 @@ import torch.distributed as dist
|
|
|
7
7
|
import torch.nn.functional as F
|
|
8
8
|
from contextlib import contextmanager
|
|
9
9
|
from megatron.core import mpu
|
|
10
|
+
from megatron.core.utils import unwrap_model
|
|
10
11
|
from peft import PeftModel
|
|
11
12
|
from peft.utils import ModulesToSaveWrapper
|
|
12
13
|
from tqdm import tqdm
|
|
@@ -17,7 +18,8 @@ from typing import Callable, List, Optional, Union
|
|
|
17
18
|
from mcore_bridge.config import ModelConfig
|
|
18
19
|
from mcore_bridge.tuners import LoraParallelLinear
|
|
19
20
|
from mcore_bridge.utils import (MxFp4Dequantizer, PackedDequantizer, SafetensorLazyLoader, StreamingSafetensorSaver,
|
|
20
|
-
deep_getattr, gc_collect, get_logger, is_master
|
|
21
|
+
deep_getattr, gc_collect, get_logger, is_master)
|
|
22
|
+
from mcore_bridge.utils.constants import EXPORT_CHUNK_BYTES
|
|
21
23
|
|
|
22
24
|
logger = get_logger()
|
|
23
25
|
|
|
@@ -28,6 +30,9 @@ EP_PP_RANK = None
|
|
|
28
30
|
|
|
29
31
|
class GPTBridge:
|
|
30
32
|
fp8_block_size = 128
|
|
33
|
+
# Bound the per-collective GPU buffer when a full gathered tensor is
|
|
34
|
+
# streamed to CPU (checkpoint save / CPU-offloaded weight sync).
|
|
35
|
+
export_chunk_bytes = EXPORT_CHUNK_BYTES
|
|
31
36
|
hf_layers_prefix = 'model.layers'
|
|
32
37
|
hf_mtp_prefix = 'model.layers'
|
|
33
38
|
hf_embed_key = 'model.embed_tokens.weight'
|
|
@@ -51,6 +56,11 @@ class GPTBridge:
|
|
|
51
56
|
additional_dim1_keys = set()
|
|
52
57
|
_support_hf_grouped_lora = True
|
|
53
58
|
|
|
59
|
+
def __deepcopy__(self, memo):
|
|
60
|
+
# Bridges hold process groups; per-layer config copies must share, not copy, them.
|
|
61
|
+
memo[id(self)] = self
|
|
62
|
+
return self
|
|
63
|
+
|
|
54
64
|
def __init__(self, config: ModelConfig):
|
|
55
65
|
self.config = config
|
|
56
66
|
self._disable_tqdm = False
|
|
@@ -336,11 +346,57 @@ class GPTBridge:
|
|
|
336
346
|
hf_state_dict[k] = v.to(self._target_device)
|
|
337
347
|
return self._add_prefix(hf_state_dict, hf_prefix)
|
|
338
348
|
|
|
349
|
+
def _stream_to_cpu(self) -> bool:
|
|
350
|
+
"""Whether large gathers/broadcasts should be chunked straight into host
|
|
351
|
+
memory. Enabled when the exported tensor is requested on CPU (checkpoint
|
|
352
|
+
save / CPU-offloaded weight sync): materializing the full gathered tensor
|
|
353
|
+
on GPU can OOM while the training state is still resident. The decision
|
|
354
|
+
only depends on properties identical across the group, so the collective
|
|
355
|
+
sequence stays in sync on every rank. Every participating rank still
|
|
356
|
+
assembles the full CPU result (matching the pre-chunking semantics); only
|
|
357
|
+
the GPU-resident full-size buffer is avoided."""
|
|
358
|
+
return self._target_device == 'cpu'
|
|
359
|
+
|
|
360
|
+
def _chunk_rows(self, shape, elem_size: int) -> int:
|
|
361
|
+
"""Rows (along dim0) per broadcast/gather chunk, ~export_chunk_bytes."""
|
|
362
|
+
inner = 1
|
|
363
|
+
for s in shape[1:]:
|
|
364
|
+
inner *= s
|
|
365
|
+
rows = max(1, self.export_chunk_bytes // max(1, inner * elem_size))
|
|
366
|
+
return max(1, min(rows, shape[0]))
|
|
367
|
+
|
|
368
|
+
def _chunked_all_gather_tp(self, tensor, tp_dim: int, tp_group, tp_size: int):
|
|
369
|
+
"""All-gather `tensor` along tp_dim and assemble the result in host memory
|
|
370
|
+
chunk by chunk, so the full gathered tensor never exists on GPU at once.
|
|
371
|
+
The chunk count derives from the local shape, which is identical on every
|
|
372
|
+
rank of the group, so the collective sequence stays in sync."""
|
|
373
|
+
dim_size = tensor.shape[tp_dim]
|
|
374
|
+
chunk_bytes = max(1, self.export_chunk_bytes // tp_size)
|
|
375
|
+
inner_rows = max(1, chunk_bytes // max(1, tensor.numel() // dim_size * tensor.element_size()))
|
|
376
|
+
out_shape = list(tensor.shape)
|
|
377
|
+
out_shape[tp_dim] = dim_size * tp_size
|
|
378
|
+
output = torch.empty(out_shape, dtype=tensor.dtype, device='cpu')
|
|
379
|
+
for start in range(0, dim_size, inner_rows):
|
|
380
|
+
end = min(dim_size, start + inner_rows)
|
|
381
|
+
local = tensor.narrow(tp_dim, start, end - start).contiguous()
|
|
382
|
+
gathered = [torch.empty_like(local) for _ in range(tp_size)]
|
|
383
|
+
dist.all_gather(gathered, local, group=tp_group)
|
|
384
|
+
del local
|
|
385
|
+
for j in range(tp_size):
|
|
386
|
+
dst = tuple(
|
|
387
|
+
slice(j * dim_size + start, j * dim_size + end) if ax == tp_dim else slice(None)
|
|
388
|
+
for ax in range(tensor.ndim))
|
|
389
|
+
output[dst] = gathered[j].cpu()
|
|
390
|
+
del gathered
|
|
391
|
+
return output
|
|
392
|
+
|
|
339
393
|
def _all_gather_tp(self, tensor, tp_dim, is_expert):
|
|
340
394
|
tensor = None if tensor is None else tensor.to('cuda')
|
|
341
395
|
tp_size = self.etp_size if is_expert else self.tp_size
|
|
342
396
|
tp_group = self.etp_group if is_expert else self.tp_group
|
|
343
397
|
if tensor is not None and tp_dim is not None and tp_size > 1:
|
|
398
|
+
if self._stream_to_cpu() and tensor.numel() * tensor.element_size() > self.export_chunk_bytes:
|
|
399
|
+
return self._chunked_all_gather_tp(tensor, tp_dim, tp_group, tp_size)
|
|
344
400
|
if tp_dim == 0:
|
|
345
401
|
# save memory
|
|
346
402
|
tensor_shape = list(tensor.shape)
|
|
@@ -363,6 +419,33 @@ class GPTBridge:
|
|
|
363
419
|
del output
|
|
364
420
|
return tensor
|
|
365
421
|
|
|
422
|
+
def _chunked_broadcast_pp(self, tensor, shape, dtype, src_rank: int, pp_group):
|
|
423
|
+
"""Chunked pp/ep-pp broadcast (the pp counterpart of _chunked_all_gather_tp):
|
|
424
|
+
stream the tensor chunk by chunk instead of materializing the full buffer
|
|
425
|
+
on GPU. On the holder rank `tensor` carries the data and is returned
|
|
426
|
+
as-is; receivers pass `shape`/`dtype` from the already-broadcast meta and
|
|
427
|
+
assemble the result in host memory (ranks that do not keep the export
|
|
428
|
+
still join every collective but skip the host assembly). Both sides
|
|
429
|
+
derive the same chunk count from the meta shape."""
|
|
430
|
+
rows = self._chunk_rows(shape, torch.tensor([], dtype=dtype).element_size())
|
|
431
|
+
if tensor is not None:
|
|
432
|
+
for start in range(0, shape[0], rows):
|
|
433
|
+
end = min(shape[0], start + rows)
|
|
434
|
+
send = tensor[start:end]
|
|
435
|
+
if not send.is_cuda or send.dtype != dtype or not send.is_contiguous():
|
|
436
|
+
send = send.to(device='cuda', dtype=dtype).contiguous()
|
|
437
|
+
dist.broadcast(send, src=src_rank, group=pp_group)
|
|
438
|
+
return tensor
|
|
439
|
+
output = torch.empty(shape, dtype=dtype, device='cpu')
|
|
440
|
+
buf = None
|
|
441
|
+
for start in range(0, shape[0], rows):
|
|
442
|
+
end = min(shape[0], start + rows)
|
|
443
|
+
if buf is None or buf.shape[0] != end - start:
|
|
444
|
+
buf = torch.empty([end - start] + list(shape[1:]), device='cuda', dtype=dtype)
|
|
445
|
+
dist.broadcast(buf, src=src_rank, group=pp_group)
|
|
446
|
+
output[start:end] = buf.cpu()
|
|
447
|
+
return output
|
|
448
|
+
|
|
366
449
|
def _broadcast_ep_pp(self, tensor, is_expert):
|
|
367
450
|
pp_group = self.ep_pp_group if is_expert else self.pp_group
|
|
368
451
|
pp_size = self.ep_pp_size if is_expert else self.pp_size
|
|
@@ -373,12 +456,20 @@ class GPTBridge:
|
|
|
373
456
|
dist.all_reduce(src_rank, group=pp_group)
|
|
374
457
|
src_rank = dist.get_global_rank(pp_group, src_rank.item())
|
|
375
458
|
meta_data = torch.zeros(10, dtype=torch.int64, device='cuda')
|
|
376
|
-
|
|
459
|
+
# Append NCCL-supported buffer dtypes without renumbering existing metadata.
|
|
460
|
+
dtype_mapping = [
|
|
461
|
+
torch.float64, torch.float32, torch.float16, torch.bfloat16, torch.uint8, torch.int32, torch.int64,
|
|
462
|
+
torch.bool, torch.int8
|
|
463
|
+
]
|
|
377
464
|
dtype_mapping_r = {v: k for k, v in enumerate(dtype_mapping)}
|
|
378
465
|
if tensor is None:
|
|
379
466
|
dist.broadcast(meta_data, src=src_rank, group=pp_group)
|
|
380
467
|
shape = meta_data[1:1 + meta_data[0]].tolist()
|
|
381
468
|
dtype = dtype_mapping[meta_data[-1].item()]
|
|
469
|
+
numel = math.prod(shape) if shape else 1
|
|
470
|
+
elem_size = torch.empty((), dtype=dtype).element_size()
|
|
471
|
+
if self._stream_to_cpu() and numel * elem_size > self.export_chunk_bytes and len(shape) > 0:
|
|
472
|
+
return self._chunked_broadcast_pp(None, shape, dtype, src_rank, pp_group)
|
|
382
473
|
tensor = torch.empty(shape, device='cuda', dtype=dtype)
|
|
383
474
|
dist.broadcast(tensor, src=src_rank, group=pp_group)
|
|
384
475
|
else:
|
|
@@ -386,6 +477,9 @@ class GPTBridge:
|
|
|
386
477
|
meta_data[1:1 + tensor.ndim] = torch.tensor(tensor.shape, dtype=torch.int64, device='cuda')
|
|
387
478
|
meta_data[-1] = dtype_mapping_r[tensor.dtype]
|
|
388
479
|
dist.broadcast(meta_data, src=src_rank, group=pp_group)
|
|
480
|
+
if self._stream_to_cpu() and tensor.numel() * tensor.element_size() > (
|
|
481
|
+
self.export_chunk_bytes) and tensor.ndim > 0:
|
|
482
|
+
return self._chunked_broadcast_pp(tensor, list(tensor.shape), tensor.dtype, src_rank, pp_group)
|
|
389
483
|
dist.broadcast(tensor, src=src_rank, group=pp_group)
|
|
390
484
|
return tensor
|
|
391
485
|
|
|
@@ -405,7 +499,7 @@ class GPTBridge:
|
|
|
405
499
|
tensor = [tensor]
|
|
406
500
|
if self._is_fp8_param(tensor[0]):
|
|
407
501
|
mg_scale_inv = [
|
|
408
|
-
t._rowwise_scale_inv[..., :math.ceil(t._rowwise_data.shape[-1] / self.fp8_block_size)]
|
|
502
|
+
t._rowwise_scale_inv[..., :math.ceil(t._rowwise_data.shape[-1] / self.fp8_block_size)].contiguous()
|
|
409
503
|
for t in tensor
|
|
410
504
|
]
|
|
411
505
|
tensor = [t._rowwise_data for t in tensor]
|
|
@@ -428,14 +522,16 @@ class GPTBridge:
|
|
|
428
522
|
if tensor.dtype == torch.uint8:
|
|
429
523
|
mg_scale_inv = self._all_gather_tp(mg_scale_inv, tp_dim, is_expert)
|
|
430
524
|
mg_scale_inv = self._broadcast_ep_pp(mg_scale_inv, is_expert)
|
|
525
|
+
if mg_scale_inv is not None and mg_scale_inv.device != tensor.device:
|
|
526
|
+
mg_scale_inv = mg_scale_inv.to(tensor.device)
|
|
431
527
|
tensor = tensor.view(torch.float8_e4m3fn)
|
|
432
528
|
assert tensor is not None, f'mg_key: {mg_key}'
|
|
433
529
|
if offset:
|
|
434
530
|
assert mg_scale_inv is None, f'mg_key: {mg_key}'
|
|
435
531
|
tensor = tensor + offset
|
|
436
532
|
is_embedding = mg_key in {'embedding.word_embeddings.weight', 'output_layer.weight'}
|
|
437
|
-
if is_embedding and self.config.
|
|
438
|
-
tensor = tensor[:self.config.
|
|
533
|
+
if is_embedding and self.config.actual_vocab_size < tensor.shape[0]:
|
|
534
|
+
tensor = tensor[:self.config.actual_vocab_size]
|
|
439
535
|
if self._target_device is not None:
|
|
440
536
|
tensor = tensor.to(device=self._target_device)
|
|
441
537
|
if mg_scale_inv is not None:
|
|
@@ -1670,7 +1766,11 @@ class GPTBridge:
|
|
|
1670
1766
|
self._set_state_dict(hyper_connection, 'bias', hf_state_dict, f'hc_{hf_key}_base', to_mcore)
|
|
1671
1767
|
has_hyper_connection = hyper_connection is not None
|
|
1672
1768
|
has_hyper_connection = self._reduce_tensor_pp_group(has_hyper_connection, to_mcore)
|
|
1673
|
-
|
|
1769
|
+
# ``alpha_*`` are frozen base parameters written outside ``_set_state_dict``, so they
|
|
1770
|
+
# need the peft guard the mapping_proj/bias calls above get for free -- otherwise a
|
|
1771
|
+
# LoRA export writes base weights into ``adapter_model.safetensors`` and a LoRA load
|
|
1772
|
+
# demands a key the adapter does not carry. Same shape as the Engram export guard.
|
|
1773
|
+
if has_hyper_connection and not self._peft_format:
|
|
1674
1774
|
if to_mcore:
|
|
1675
1775
|
alpha = hf_state_dict[f'hc_{hf_key}_scale'].load()
|
|
1676
1776
|
for i, alpha_suffix in enumerate(['pre', 'post', 'res']):
|
|
@@ -1758,6 +1858,10 @@ class GPTBridge:
|
|
|
1758
1858
|
self._set_state_dict(lm_model, 'decoder.final_layernorm.weight', hf_state_dict, self.hf_final_layernorm_key,
|
|
1759
1859
|
to_mcore)
|
|
1760
1860
|
|
|
1861
|
+
def _convert_additional_layers(self, mg_model, hf_state_dict, hf_prefix, to_mcore, is_pp_last_stage):
|
|
1862
|
+
"""Extension point for model-specific auxiliary stacks outside standard MTP."""
|
|
1863
|
+
return ()
|
|
1864
|
+
|
|
1761
1865
|
def _convert_hf_state_dict(self, hf_state_dict, to_mcore):
|
|
1762
1866
|
res = {}
|
|
1763
1867
|
for k, v in hf_state_dict.items():
|
|
@@ -1771,6 +1875,7 @@ class GPTBridge:
|
|
|
1771
1875
|
return res
|
|
1772
1876
|
|
|
1773
1877
|
def _convert(self, mg_models, hf_state_dict, hf_prefix: str, to_mcore: bool, tqdm_desc: str = 'Converting: '):
|
|
1878
|
+
self._pending_export_iter = None
|
|
1774
1879
|
if to_mcore:
|
|
1775
1880
|
hf_state_dict = self._remove_prefix(hf_state_dict, hf_prefix)
|
|
1776
1881
|
hf_state_dict = self._convert_hf_state_dict(hf_state_dict, to_mcore)
|
|
@@ -1820,7 +1925,11 @@ class GPTBridge:
|
|
|
1820
1925
|
yield
|
|
1821
1926
|
else:
|
|
1822
1927
|
res = self._convert_hf_state_dict(res, to_mcore)
|
|
1823
|
-
|
|
1928
|
+
# Drain any staged PLE table shards first: they are produced one
|
|
1929
|
+
# at a time (see _iter_ple_table_export) so the 100GB-scale table
|
|
1930
|
+
# never accumulates in host memory.
|
|
1931
|
+
yield from self._drain_pending_export(hf_prefix)
|
|
1932
|
+
yield from self._add_prefix(res, hf_prefix).items()
|
|
1824
1933
|
hf_state_dict = {}
|
|
1825
1934
|
|
|
1826
1935
|
if (not to_mcore or is_pp_last_stage) and self.config.mtp_num_layers:
|
|
@@ -1828,8 +1937,14 @@ class GPTBridge:
|
|
|
1828
1937
|
if to_mcore and self.pp_rank > 0:
|
|
1829
1938
|
self._set_state_dict(lm_model, 'embedding.word_embeddings.weight', hf_state_dict, self.hf_embed_key,
|
|
1830
1939
|
to_mcore)
|
|
1940
|
+
from mcore_bridge.model.mtp import get_physical_mtp_count
|
|
1941
|
+
if not to_mcore:
|
|
1942
|
+
phys_count = self._reduce_mtp_physical_count(lm_model)
|
|
1943
|
+
else:
|
|
1944
|
+
# Import: only the owning (last) stage reaches here.
|
|
1945
|
+
phys_count = get_physical_mtp_count(lm_model)
|
|
1831
1946
|
layer_idx = 0
|
|
1832
|
-
while layer_idx <
|
|
1947
|
+
while layer_idx < phys_count:
|
|
1833
1948
|
res = self._convert_mtp_layer(lm_model, hf_state_dict, f'{self.hf_mtp_prefix}.', layer_idx, to_mcore)
|
|
1834
1949
|
layer_idx += 1
|
|
1835
1950
|
if to_mcore:
|
|
@@ -1838,6 +1953,7 @@ class GPTBridge:
|
|
|
1838
1953
|
res = self._convert_hf_state_dict(res, to_mcore)
|
|
1839
1954
|
yield from list(self._add_prefix(res, hf_prefix).items())
|
|
1840
1955
|
hf_state_dict = {}
|
|
1956
|
+
yield from self._convert_additional_layers(mg_model, hf_state_dict, hf_prefix, to_mcore, is_pp_last_stage)
|
|
1841
1957
|
if not to_mcore or is_pp_last_stage:
|
|
1842
1958
|
hf_state_dict.update(self._convert_post_process(mg_model, hf_state_dict, '', to_mcore))
|
|
1843
1959
|
if to_mcore:
|
|
@@ -1847,6 +1963,16 @@ class GPTBridge:
|
|
|
1847
1963
|
yield from list(self._add_prefix(hf_state_dict, hf_prefix).items())
|
|
1848
1964
|
prog_bar.close()
|
|
1849
1965
|
|
|
1966
|
+
def _drain_pending_export(self, hf_prefix: str):
|
|
1967
|
+
"""Yield (and release) the PLE table shards staged by _set_layer_ple."""
|
|
1968
|
+
it, self._pending_export_iter = self._pending_export_iter, None
|
|
1969
|
+
if it is None:
|
|
1970
|
+
return
|
|
1971
|
+
for k, v in it:
|
|
1972
|
+
if v is None:
|
|
1973
|
+
continue
|
|
1974
|
+
yield from self._add_prefix(self._convert_hf_state_dict({k: v}, False), hf_prefix).items()
|
|
1975
|
+
|
|
1850
1976
|
def _convert_mtp_extra(self, mtp_layer, hf_state_dict, to_mcore, origin_hf_state_dict):
|
|
1851
1977
|
for key in ['enorm.weight', 'hnorm.weight', 'eh_proj.weight']:
|
|
1852
1978
|
self._set_state_dict(mtp_layer, key, hf_state_dict, key, to_mcore)
|
|
@@ -1854,6 +1980,17 @@ class GPTBridge:
|
|
|
1854
1980
|
self._set_state_dict(mtp_layer, 'final_layernorm.weight', hf_state_dict, self.hf_mtp_final_layernorm_key,
|
|
1855
1981
|
to_mcore)
|
|
1856
1982
|
|
|
1983
|
+
def _reduce_mtp_physical_count(self, lm_model) -> int:
|
|
1984
|
+
"""PP export: obtain the physical MTP layer count from the owning stage
|
|
1985
|
+
so every rank iterates the same number of times (collective safety)."""
|
|
1986
|
+
from mcore_bridge.model.mtp import get_physical_mtp_count
|
|
1987
|
+
local = get_physical_mtp_count(lm_model)
|
|
1988
|
+
if self.pp_size <= 1:
|
|
1989
|
+
return local
|
|
1990
|
+
t = torch.tensor([local], dtype=torch.long, device='cuda')
|
|
1991
|
+
dist.all_reduce(t, op=dist.ReduceOp.MAX, group=self.pp_group)
|
|
1992
|
+
return int(t.item())
|
|
1993
|
+
|
|
1857
1994
|
def _convert_mtp_layer(self, lm_model, hf_state_dict, hf_prefix: str, layer_idx: int, to_mcore: bool):
|
|
1858
1995
|
mtp_layer = lm_model.mtp.layers[layer_idx] if hasattr(lm_model, 'mtp') else None
|
|
1859
1996
|
if self.hf_mtp_prefix == self.hf_layers_prefix:
|
|
@@ -1865,8 +2002,16 @@ class GPTBridge:
|
|
|
1865
2002
|
origin_hf_state_dict = hf_state_dict
|
|
1866
2003
|
hf_state_dict = self._remove_prefix(hf_state_dict, hf_prefix)
|
|
1867
2004
|
if len(hf_state_dict) == 0:
|
|
1868
|
-
|
|
1869
|
-
|
|
2005
|
+
if self._peft_format:
|
|
2006
|
+
return {}
|
|
2007
|
+
expected = f'{hf_prefix}*'
|
|
2008
|
+
if not self.config.mtp_allow_random_init:
|
|
2009
|
+
raise ValueError(f'MTP weights not found under {expected} (expected '
|
|
2010
|
+
f'{self.config.mtp_num_layers} physical set(s) after the {self.config.num_layers} '
|
|
2011
|
+
'decoder layers). Set mtp_shared_weights=True to reuse one set across depths, or '
|
|
2012
|
+
'mtp_allow_random_init=True to train MTP from random init.')
|
|
2013
|
+
logger.warning(f'MTP Layer {mtp_layer.layer_number} weights not found under {expected}; '
|
|
2014
|
+
'randomly initializing (mtp_allow_random_init=True).')
|
|
1870
2015
|
for param in mtp_layer.parameters():
|
|
1871
2016
|
if param.ndim == 2:
|
|
1872
2017
|
mtp_layer.config.init_method(param.data)
|
|
@@ -1875,7 +2020,7 @@ class GPTBridge:
|
|
|
1875
2020
|
origin_hf_state_dict = {}
|
|
1876
2021
|
hf_state_dict = {}
|
|
1877
2022
|
self._convert_mtp_extra(mtp_layer, hf_state_dict, to_mcore, origin_hf_state_dict)
|
|
1878
|
-
transformer_layer = None if mtp_layer is None else mtp_layer.
|
|
2023
|
+
transformer_layer = None if mtp_layer is None else mtp_layer.mtp_model_layer
|
|
1879
2024
|
self._convert_mtp_embeds(lm_model, hf_state_dict, to_mcore)
|
|
1880
2025
|
hf_state_dict.update(self._set_layer_attn(transformer_layer, hf_state_dict, -1, to_mcore))
|
|
1881
2026
|
hf_state_dict.update(self._set_layer_mlp(transformer_layer, hf_state_dict, -1, to_mcore, is_mtp=True))
|
|
@@ -1948,6 +2093,7 @@ class GPTBridge:
|
|
|
1948
2093
|
tqdm_desc: str = 'Exporting: ',
|
|
1949
2094
|
disable_tqdm: bool = True,
|
|
1950
2095
|
_is_saving: bool = False,
|
|
2096
|
+
skip_unsupported_export: bool = False,
|
|
1951
2097
|
):
|
|
1952
2098
|
"""Export Megatron model weights to safetensors (HuggingFace) format as a generator.
|
|
1953
2099
|
|
|
@@ -1965,6 +2111,11 @@ class GPTBridge:
|
|
|
1965
2111
|
converter: Used to perform key-value conversion on the newly exported state_dict.
|
|
1966
2112
|
tqdm_desc: Description text for the progress bar. Defaults to 'Exporting: '.
|
|
1967
2113
|
disable_tqdm: Whether to disable the tqdm progress bar. Defaults to True.
|
|
2114
|
+
skip_unsupported_export: When True, weights whose Megatron->HF export is not implemented
|
|
2115
|
+
(e.g. DeepSeek-V4.1 Engram tables, which are frozen during on-policy RL and already
|
|
2116
|
+
loaded in the rollout engine) are silently skipped instead of raising. Used by the RL
|
|
2117
|
+
weight-sync path; the checkpoint-save path keeps the default (False) so a saved HF
|
|
2118
|
+
checkpoint stays complete.
|
|
1968
2119
|
|
|
1969
2120
|
Yields:
|
|
1970
2121
|
Tuple[str, torch.Tensor]: Key-value pairs of parameter names and tensors.
|
|
@@ -1975,6 +2126,7 @@ class GPTBridge:
|
|
|
1975
2126
|
self._adapter_name = adapter_name
|
|
1976
2127
|
self._disable_tqdm = disable_tqdm
|
|
1977
2128
|
self._is_saving = _is_saving
|
|
2129
|
+
self._skip_unsupported_export = skip_unsupported_export
|
|
1978
2130
|
self._peft_target_modules = set()
|
|
1979
2131
|
self._peft_modules_to_save = set()
|
|
1980
2132
|
self._fp8_skip_modules = set()
|
|
@@ -2045,6 +2197,10 @@ class GPTBridge:
|
|
|
2045
2197
|
saver.finalize()
|
|
2046
2198
|
dist.barrier() # Ensure all weights are saved completely
|
|
2047
2199
|
|
|
2200
|
+
def _normalize_missing_weight_key(self, key: str) -> str:
|
|
2201
|
+
"""Return the identity used to detect aliases while restoring source-only weights."""
|
|
2202
|
+
return key
|
|
2203
|
+
|
|
2048
2204
|
def _save_missing_weights(self, saver, saved_keys, source_model_dir=None) -> None:
|
|
2049
2205
|
"""Copy tensors present in the source checkpoint but absent from the exported ones.
|
|
2050
2206
|
|
|
@@ -2061,7 +2217,9 @@ class GPTBridge:
|
|
|
2061
2217
|
return
|
|
2062
2218
|
with SafetensorLazyLoader(source_model_dir) as loader:
|
|
2063
2219
|
state_dict = loader.get_state_dict()
|
|
2064
|
-
|
|
2220
|
+
saved_identities = {self._normalize_missing_weight_key(key) for key in saved_keys}
|
|
2221
|
+
missing_keys = sorted(
|
|
2222
|
+
key for key in state_dict if self._normalize_missing_weight_key(key) not in saved_identities)
|
|
2065
2223
|
if not missing_keys:
|
|
2066
2224
|
return
|
|
2067
2225
|
logger.info(f'Restoring {len(missing_keys)} weights from the source checkpoint '
|