[Model] Support GLM-5.3 Flash NVFP4 loading (#38621)
Co-authored-by: YAMY <74099316+YAMY1234@users.noreply.github.com>
This commit is contained in:
co-authored by
YAMY
parent
bede776c2a
commit
96d91ef926
@@ -94,6 +94,7 @@ from sglang.srt.models.glm_ocr import (
|
||||
GlmOcrVisionPatchEmbed,
|
||||
GlmOcrVisionPatchMerger,
|
||||
)
|
||||
from sglang.srt.models.utils import WeightsMapper
|
||||
from sglang.srt.multimodal.mm_utils import (
|
||||
run_dp_presharded_mrope_vision_model,
|
||||
run_dp_sharded_mrope_vision_model,
|
||||
@@ -1077,6 +1078,13 @@ class Glm5NextModel(nn.Module):
|
||||
|
||||
|
||||
class Glm5NextForConditionalGeneration(nn.Module):
|
||||
hf_to_sglang_mapper = WeightsMapper(
|
||||
orig_to_new_substr={
|
||||
"model.language_model.": "model.",
|
||||
"model.visual": "visual",
|
||||
}
|
||||
)
|
||||
|
||||
packed_modules_mapping = {
|
||||
"fused_qkv_a_proj_with_mqa": ["q_a_proj", "kv_a_proj_with_mqa"],
|
||||
"fused_qkvbfg_a_proj": [
|
||||
@@ -1200,6 +1208,17 @@ class Glm5NextForConditionalGeneration(nn.Module):
|
||||
text_config = getattr(hf_config, "text_config", hf_config)
|
||||
if not getattr(text_config, "n_shared_experts", None):
|
||||
return "No shared experts are defined in the config."
|
||||
if quant_config is not None and quant_config.get_name() == "modelopt_fp4":
|
||||
first_sparse_layer = getattr(text_config, "first_k_dense_replace", 0)
|
||||
for layer_id in range(first_sparse_layer, text_config.num_hidden_layers):
|
||||
moe_prefix = f"model.layers.{layer_id}.mlp"
|
||||
if quant_config.is_layer_excluded(
|
||||
f"{moe_prefix}.shared_experts"
|
||||
) and not quant_config.is_layer_excluded(f"{moe_prefix}.experts"):
|
||||
return (
|
||||
"ModelOpt FP4 keeps shared experts unquantized while routed "
|
||||
"experts are quantized."
|
||||
)
|
||||
if not _is_cuda:
|
||||
return "Shared experts fusion currently requires CUDA devices."
|
||||
if _device_sm is not None and _device_sm < 80:
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from sglang.srt.layers.quantization.modelopt_quant import ModelOptFp4Config
|
||||
from sglang.srt.models import glm5_next
|
||||
from sglang.srt.models.glm5_next import Glm5NextForConditionalGeneration
|
||||
from sglang.srt.runtime_context import get_parallel
|
||||
from sglang.test.ci.ci_register import register_cpu_ci
|
||||
from sglang.test.test_utils import CustomTestCase
|
||||
|
||||
register_cpu_ci(est_time=5, suite="base-a-test-cpu")
|
||||
|
||||
NVIDIA_EXCLUDE_MODULES = [
|
||||
"model.language_model.embed_tokens",
|
||||
"model.language_model.layers.11.self_attn*",
|
||||
"model.language_model.layers.11.mlp.gate",
|
||||
"model.language_model.layers.11.mlp.shared_experts*",
|
||||
"model.visual*",
|
||||
]
|
||||
|
||||
RADIXARK_EXCLUDE_MODULES = [
|
||||
"model.language_model.embed_tokens",
|
||||
"model.language_model.layers.11.self_attn*",
|
||||
"model.language_model.layers.11.mlp.gate",
|
||||
"model.visual*",
|
||||
"model.embed_tokens",
|
||||
"model.layers.11.self_attn*",
|
||||
"model.layers.11.mlp.gate",
|
||||
"model.language_model.layers.45*",
|
||||
"model.layers.45*",
|
||||
"visual*",
|
||||
]
|
||||
|
||||
|
||||
class TestGlm5NextModelOpt(CustomTestCase):
|
||||
def _config(self, exclude_modules):
|
||||
config = ModelOptFp4Config(
|
||||
is_checkpoint_nvfp4_serialized=True,
|
||||
group_size=16,
|
||||
exclude_modules=exclude_modules,
|
||||
)
|
||||
config.apply_weight_name_mapper(
|
||||
Glm5NextForConditionalGeneration.hf_to_sglang_mapper
|
||||
)
|
||||
return config
|
||||
|
||||
def _hf_config(self):
|
||||
return SimpleNamespace(
|
||||
text_config=SimpleNamespace(
|
||||
first_k_dense_replace=3,
|
||||
num_hidden_layers=45,
|
||||
n_shared_experts=1,
|
||||
)
|
||||
)
|
||||
|
||||
def test_checkpoint_exclusions_match_sglang_module_names(self):
|
||||
checkpoints = {
|
||||
"nvidia/GLM-5.3-Flash-NVFP4": NVIDIA_EXCLUDE_MODULES,
|
||||
"RadixArk/GLM-5.3-Flash-NVFP4": RADIXARK_EXCLUDE_MODULES,
|
||||
}
|
||||
|
||||
for checkpoint, exclude_modules in checkpoints.items():
|
||||
with self.subTest(checkpoint=checkpoint):
|
||||
config = self._config(exclude_modules)
|
||||
self.assertTrue(config.is_layer_excluded("model.embed_tokens"))
|
||||
self.assertTrue(
|
||||
config.is_layer_excluded("model.layers.11.self_attn.kv_b_proj")
|
||||
)
|
||||
self.assertTrue(config.is_layer_excluded("model.layers.11.mlp.gate"))
|
||||
self.assertTrue(
|
||||
config.is_layer_excluded("visual.blocks.0.attn.qkv_proj")
|
||||
)
|
||||
|
||||
def test_nvidia_mixed_precision_shared_experts_disable_fusion(self):
|
||||
config = self._config(NVIDIA_EXCLUDE_MODULES)
|
||||
|
||||
reason = Glm5NextForConditionalGeneration.shared_experts_fusion_disable_reason(
|
||||
self._hf_config(), config
|
||||
)
|
||||
|
||||
self.assertIn("shared experts unquantized", reason)
|
||||
|
||||
def test_radixark_uniform_fp4_shared_experts_keep_fusion(self):
|
||||
config = self._config(RADIXARK_EXCLUDE_MODULES)
|
||||
a2a_backend = SimpleNamespace(is_deepep=lambda: False)
|
||||
|
||||
with (
|
||||
patch.object(glm5_next, "_is_cuda", True),
|
||||
patch.object(glm5_next, "_device_sm", 100),
|
||||
patch.object(glm5_next, "get_moe_a2a_backend", return_value=a2a_backend),
|
||||
get_parallel().override(moe_ep_size=1),
|
||||
):
|
||||
reason = (
|
||||
Glm5NextForConditionalGeneration.shared_experts_fusion_disable_reason(
|
||||
self._hf_config(), config
|
||||
)
|
||||
)
|
||||
|
||||
self.assertIsNone(reason)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user