@@ -54,8 +54,11 @@ def __init__(self):
5454 # Set default attributes that recipes might set
5555 self .tensor_model_parallel_size = 1
5656 self .pipeline_model_parallel_size = 1
57+ self .pipeline_model_parallel_layout = None
5758 self .pipeline_dtype = None
5859 self .virtual_pipeline_model_parallel_size = None
60+ self .num_layers_in_first_pipeline_stage = None
61+ self .num_layers_in_last_pipeline_stage = None
5962 self .context_parallel_size = 1
6063 self .expert_model_parallel_size = 1
6164 self .expert_tensor_parallel_size = None
@@ -103,6 +106,23 @@ def from_hf_pretrained(hf_path: str, **kwargs):
103106 return _FakeBridge ()
104107
105108
109+ class _RealDepthFakeBridge (_FakeBridge ):
110+ """Fake AutoBridge that preserves the selected GLM-4.5 model depth."""
111+
112+ def __init__ (self , num_layers : int ):
113+ self .num_layers = num_layers
114+
115+ def to_megatron_provider (self , load_weights : bool = False ):
116+ model = _FakeModelCfg ()
117+ model .num_layers = self .num_layers
118+ return model
119+
120+ @staticmethod
121+ def from_hf_pretrained (hf_path : str , ** kwargs ):
122+ num_layers = 46 if hf_path .endswith ("Air" ) else 92
123+ return _RealDepthFakeBridge (num_layers )
124+
125+
106126class _FakeTokenizer :
107127 """Fake HuggingFace tokenizer for testing."""
108128
@@ -439,6 +459,35 @@ def test_glm45_air_106b_pretrain_defaults(monkeypatch: pytest.MonkeyPatch):
439459 assert hasattr (cfg .model , "mtp_loss_scaling_factor" )
440460
441461
462+ @pytest .mark .parametrize (
463+ "recipe_name,num_layers" ,
464+ [
465+ ("glm45_355b_pretrain_config" , 92 ),
466+ ("glm45_355b_sft_config" , 92 ),
467+ ("glm45_air_106b_pretrain_config" , 46 ),
468+ ("glm45_air_106b_sft_config" , 46 ),
469+ ],
470+ )
471+ def test_glm45_pipeline_partition_covers_real_model_depth (
472+ recipe_name : str ,
473+ num_layers : int ,
474+ monkeypatch : pytest .MonkeyPatch ,
475+ ):
476+ """GLM-4.5 recipe defaults should partition every real decoder layer."""
477+ from megatron .core .transformer .transformer_block import get_num_layers_to_build
478+
479+ recipe_func = getattr (_glm_module , recipe_name )
480+ patch_recipe_module_global (monkeypatch , recipe_func , "AutoBridge" , _RealDepthFakeBridge )
481+
482+ cfg = recipe_func ()
483+ layers_per_stage = [
484+ get_num_layers_to_build (cfg .model , pp_rank = pp_rank )
485+ for pp_rank in range (cfg .model .pipeline_model_parallel_size )
486+ ]
487+
488+ assert sum (layers_per_stage ) == num_layers
489+
490+
442491def test_glm45_sft_offline_packing_is_disabled (monkeypatch : pytest .MonkeyPatch ):
443492 """Test that unsupported offline packing remains disabled for GLM-4.5."""
444493 from megatron .bridge .recipes .glm import glm45_355b_sft_config
0 commit comments