Skip to content

Commit 5c04b69

Browse files
Deepseek v4 Support (flagos-ai#1195)
### PR Category <!-- One of [ Train | Inference | Compress | Serve | RL | Core | Hardware | CICD | Tools | Others ] --> [Train] Most of codes are copied from Megatron-LM Dev branch. The dev branch is different with main branch or release version. Megatron LM PR: DeepSeek-V4: NVIDIA/Megatron-LM#4458 NVIDIA/Megatron-LM#4481 NVIDIA/Megatron-LM#4518 mHC: NVIDIA/Megatron-LM#2943 ### PR Types <!-- One of [ User Experience | New Features | Bug Fixes | Improvements | Performance | Breaking Change| Deprecations | Test Case | Docs | Others ] --> [New features] ### PR Description <!-- Describe what you’ve done --> Add DeepSeek V4 model into FlagScale and Megatron-FL Supported: 1. CSA and HCA 2. Hash Router 3. mHC 4. Engram(optional) Unsupported: 1. Sqrtsoftpuls router score function. ✅ 2. mHC recompute. ✅ 3. Overlap_grad_reduce and overlap_param_gather when Zero 1. ✅ 4. Any infra optimizations. ### NOTE: This is only a draft pr, please reivew to give more suggestions. such as: 1. File structure. - **All modules are moved to Megatron-FL. Only model_builder is left in Flagscale.** - Delete Engram related CI or not? ### Next plan: 1. Distributed training. ✅ 3. Muon optimizer with Zero 1 adaptation. 😢 4. Low precision is out of scope of this pr, limited by resource. 5. Maybe context parallel for sparse attention. 6. Welcome to give more suggestions. --------- Co-authored-by: zhaoyingli <86812880+zhaoyinglia@users.noreply.github.com>
1 parent c8f6047 commit 5c04b69

17 files changed

Lines changed: 1664 additions & 940 deletions
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# Copyright (c) 2026 FlagScale CORPORATION & AFFILIATES. All rights reserved.
2+
3+
"""Alternative GPT builder file.
4+
5+
This file is intentionally shaped like deepseek_builders.py so you can switch by
6+
changing only the import path in training scripts.
7+
"""
8+
9+
from dataclasses import dataclass
10+
from typing import Optional, Union
11+
12+
import torch
13+
14+
from megatron.core.models.gpt.gpt_layer_specs import (
15+
get_gpt_mtp_block_spec,
16+
get_gpt_layer_with_transformer_engine_spec,
17+
get_gpt_layer_local_spec,
18+
get_gpt_layer_with_inference_spec
19+
)
20+
from megatron.core.fusions.fused_bias_dropout import get_bias_dropout_add
21+
from megatron.core.transformer.spec_utils import ModuleSpec
22+
from megatron.core.transformer.transformer_config import TransformerConfig
23+
from megatron.core.transformer.transformer_layer import get_transformer_layer_offset
24+
from megatron.training import print_rank_0
25+
from megatron.training.arguments import core_transformer_config_from_args
26+
from megatron.training.yaml_arguments import core_transformer_config_from_yaml
27+
from megatron.core.transformer.identity_op import IdentityOp
28+
from megatron.core.transformer.transformer_block import (
29+
TransformerBlockSubmodules,
30+
get_num_layers_to_build,
31+
)
32+
33+
from megatron.core.transformer.enums import LayerType
34+
from megatron.training.utils import get_args
35+
from megatron.core.models.gpt.experimental_attention_variant_module_specs import (
36+
get_transformer_block_with_experimental_attention_variant_spec,
37+
_get_backend_spec_provider,
38+
get_dsv4_hybrid_module_spec_for_backend,
39+
_get_moe_module_spec,
40+
get_moe_layer_pattern
41+
)
42+
from megatron.core.transformer.hyper_connection import HyperConnectionModule
43+
from megatron.core.transformer.engram import EngramModule
44+
try:
45+
import transformer_engine as te # pylint: disable=unused-import
46+
47+
from megatron.core.extensions.transformer_engine import TENorm
48+
from megatron.core.extensions.transformer_engine_spec_provider import TESpecProvider
49+
50+
HAVE_TE = True
51+
except ImportError:
52+
HAVE_TE = False
53+
54+
try:
55+
import nvidia_kitchen # pylint: disable=unused-import
56+
57+
from megatron.core.extensions.kitchen import KitchenSpecProvider
58+
59+
HAVE_KITCHEN = True
60+
except ImportError:
61+
HAVE_KITCHEN = False
62+
63+
try:
64+
import apex # pylint: disable=unused-import
65+
66+
from megatron.core.fusions.fused_layer_norm import FusedLayerNorm
67+
68+
HAVE_APEX = True
69+
LNImpl = FusedLayerNorm
70+
except ImportError:
71+
import warnings
72+
73+
from megatron.core.transformer.torch_norm import WrappedTorchNorm
74+
75+
warnings.warn("Apex is not installed. Falling back to Torch Norm")
76+
LNImpl = WrappedTorchNorm
77+
HAVE_APEX = False
78+
79+
from .deepseek_transformer_layer import DeepSeekTransformerLayer, DeepSeekTransformerLayerSubmodules
80+
from .deepseek_model import DeepSeekModel
81+
82+
83+
84+
def get_deepseek_layer_spec(
85+
use_te: bool,
86+
config: TransformerConfig,
87+
build_engram: bool = False,
88+
) -> ModuleSpec:
89+
"""
90+
Build LayerSpec that inserts engram and mhc into TransformerLayer.
91+
Because not all layers have engram, we build the engram module as an optional submodule.
92+
"""
93+
backend = _get_backend_spec_provider(config=config)
94+
hybrid_attn_spec = get_dsv4_hybrid_module_spec_for_backend(config=config, backend=backend)
95+
96+
moe_layer_spec = _get_moe_module_spec(config=config, backend=backend)
97+
rms_norm = config.normalization == "RMSNorm"
98+
input_layernorm = (
99+
IdentityOp
100+
if hybrid_attn_spec.metainfo["fuse_input_layernorm"]
101+
else backend.layer_norm(rms_norm=rms_norm, for_qk=False)
102+
)
103+
pre_mlp_layernorm = (
104+
IdentityOp
105+
if moe_layer_spec.metainfo["fuse_pre_mlp_layernorm"]
106+
else backend.layer_norm(rms_norm=rms_norm, for_qk=False)
107+
)
108+
if build_engram:
109+
engram_module = EngramModule
110+
else:
111+
engram_module = IdentityOp
112+
submodules = DeepSeekTransformerLayerSubmodules(
113+
input_layernorm=input_layernorm,
114+
self_attention=hybrid_attn_spec,
115+
self_attn_bda=get_bias_dropout_add,
116+
self_attention_hyper_connection=HyperConnectionModule,
117+
pre_mlp_layernorm=pre_mlp_layernorm,
118+
mlp=moe_layer_spec,
119+
mlp_bda=get_bias_dropout_add,
120+
mlp_hyper_connection=HyperConnectionModule,
121+
engram=ModuleSpec(module=engram_module)
122+
)
123+
124+
return ModuleSpec(module=DeepSeekTransformerLayer, submodules=submodules)
125+
126+
127+
def get_deepseek_decoder_block_spec(
128+
config: TransformerConfig,
129+
use_transformer_engine: bool,
130+
normalization: Optional[str] = None,
131+
qk_l2_norm: Optional[bool] = False,
132+
vp_stage: Optional[int] = None,
133+
pp_rank: int | None = None,
134+
is_dualpipev_first_chunk: bool | None = False,
135+
use_moe: bool | None = False,
136+
):
137+
"""Build decoder block spec and attach STM/HC placeholders to each local layer."""
138+
139+
"""GPT block spec."""
140+
layer_norm_impl = TENorm
141+
moe_deepseek_engram_layer_spec = get_deepseek_layer_spec(
142+
use_te=use_transformer_engine,
143+
config=config,
144+
build_engram=True,
145+
)
146+
moe_deepseek_layer_spec = get_deepseek_layer_spec(
147+
use_te=use_transformer_engine,
148+
config=config,
149+
build_engram=False,
150+
)
151+
152+
153+
# Create the layer specs for the model.
154+
layer_specs = []
155+
for layer_number in range(config.num_layers):
156+
if config.use_engram and layer_number in config.engram_layer_ids:
157+
is_engram_layer = True
158+
else:
159+
is_engram_layer = False
160+
layer_specs.append(moe_deepseek_engram_layer_spec if is_engram_layer else moe_deepseek_layer_spec)
161+
162+
# Slice the layer specs to only include the layers that are built in this pipeline stage.
163+
# Note: MCore layer_number starts at 1
164+
######### FlagScale Modify ########
165+
num_layers_to_build = get_num_layers_to_build(
166+
config,
167+
vp_stage=vp_stage,
168+
pp_rank=pp_rank,
169+
is_dualpipev_first_chunk=is_dualpipev_first_chunk,
170+
)
171+
172+
if config.pipeline_model_parallel_layout is not None:
173+
local_layer_specs = [
174+
layer_specs[layer_id]
175+
for layer_id in config.pipeline_model_parallel_layout.get_layer_id_list(
176+
layer_type=LayerType.decoder, vp_stage=vp_stage, pp_rank=pp_rank
177+
)
178+
]
179+
else:
180+
######### FlagScale Modify ########
181+
offset = get_transformer_layer_offset(
182+
config,
183+
vp_stage=vp_stage,
184+
pp_rank=pp_rank,
185+
is_dualpipev_first_chunk=is_dualpipev_first_chunk,
186+
)
187+
local_layer_specs = layer_specs[offset : offset + num_layers_to_build]
188+
189+
# Block spec.
190+
block_spec = TransformerBlockSubmodules(
191+
layer_specs=local_layer_specs, layer_norm=layer_norm_impl
192+
)
193+
194+
return block_spec
195+
196+
197+
def deepseek_builder(args, pre_process, post_process, vp_stage=None, config=None, pg_collection=None):
198+
"""Drop-in replacement builder compatible with model_provider(...)."""
199+
print_rank_0('building DeepSeek model (engram and mhc file) ...')
200+
201+
if config is None:
202+
if args.yaml_cfg is not None:
203+
config = core_transformer_config_from_yaml(args, "language_model")
204+
else:
205+
config = core_transformer_config_from_args(args)
206+
207+
208+
if args.use_legacy_models:
209+
raise NotImplementedError("Legacy GPT models do not support deepseek module insertion.")
210+
else:
211+
if args.spec is not None:
212+
raise NotImplementedError("Using custom spec is not supported with deepseek builder.")
213+
else:
214+
use_te = args.transformer_impl == "transformer_engine"
215+
216+
if args.heterogeneous_layers_config_path is not None:
217+
assert not (config.transformer_impl == "inference_optimized")
218+
raise NotImplementedError("Using heterogeneous layers is not supported with deepseek builder.")
219+
transformer_layer_spec = get_deepseek_decoder_block_spec(
220+
config=config,
221+
use_transformer_engine=use_te,
222+
normalization=args.normalization,
223+
qk_l2_norm=args.qk_l2_norm,
224+
vp_stage=vp_stage,
225+
use_moe=True
226+
)
227+
228+
mtp_block_spec = None
229+
if args.mtp_num_layers is not None:
230+
assert not (config.transformer_impl == "inference_optimized")
231+
transformer_layer_spec_for_mtp = get_deepseek_layer_spec(use_te, config, build_engram=False)
232+
mtp_block_spec = get_gpt_mtp_block_spec(
233+
config,
234+
transformer_layer_spec_for_mtp,
235+
use_transformer_engine=use_te,
236+
vp_stage=vp_stage,
237+
)
238+
239+
model = DeepSeekModel(
240+
config=config,
241+
transformer_layer_spec=transformer_layer_spec,
242+
vocab_size=args.padded_vocab_size,
243+
max_sequence_length=args.max_position_embeddings,
244+
pre_process=pre_process,
245+
post_process=post_process,
246+
fp16_lm_cross_entropy=args.fp16_lm_cross_entropy,
247+
parallel_output=True,
248+
share_embeddings_and_output_weights=not args.untie_embeddings_and_output_weights,
249+
position_embedding_type=args.position_embedding_type,
250+
rotary_percent=args.rotary_percent,
251+
rotary_base=args.rotary_base,
252+
rope_scaling=args.use_rope_scaling,
253+
mtp_block_spec=mtp_block_spec,
254+
vp_stage=vp_stage,
255+
pg_collection=pg_collection,
256+
)
257+
print(f"Model = {model}")
258+
return model

0 commit comments

Comments
 (0)