A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 12, 22:15 UTC
[Feature] EPLB on Qwen3VLMoe and CompressedTensorsWNA16MoEMethod (#28849)
JartX committed
Nov 20, 2025 at 00:30 UTC
8e38e998298364b0a94cddf7ccc59d8466c2396a
2 files changed
+82
-7
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_moe.py
+24
-3
@@ -1921,9 +1921,20 @@ class CompressedTensorsWNA16MoEMethod(CompressedTensorsMoEMethod):
1921
logical_replica_count: torch.Tensor | None = None,
1922
) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
1923
if enable_eplb:
1924
- raise NotImplementedError(
1925
- "EPLB not supported for `CompressedTensorsWNA16MoEMethod` yet."
1926
- )
1924
+ if expert_load_view is None:
1925
+ raise ValueError("enable_eplb=True requiere expert_load_view != None")
1926
+ if logical_to_physical_map is None:
1927
+ raise ValueError(
1928
+ "enable_eplb=True requiere logical_to_physical_map != None"
1929
+ )
1930
+ if logical_replica_count is None:
1931
+ raise ValueError(
1932
+ "enable_eplb=True requiere logical_replica_count != None"
1933
+ )
1934
+ if not isinstance(layer, FusedMoE):
1935
+ raise TypeError(
1936
+ "EPLB is only supported when `layer` is a instance of FusedMoE."
1937
+ )
1938
1939
from vllm.model_executor.layers.fused_moe import fused_experts
1940
@@ -1940,6 +1951,12 @@ class CompressedTensorsWNA16MoEMethod(CompressedTensorsMoEMethod):
1951
routed_scaling_factor=routed_scaling_factor,
1952
e_score_correction_bias=e_score_correction_bias,
1953
indices_type=self.topk_indices_dtype,
1954
+ num_fused_shared_experts=getattr(layer, "num_fused_shared_experts", 0),
1955
+ enable_eplb=enable_eplb,
1956
+ expert_map=expert_map,
1957
+ expert_load_view=expert_load_view,
1958
+ logical_to_physical_map=logical_to_physical_map,
1959
+ logical_replica_count=logical_replica_count,
1960
)
1961
1962
return fused_experts(
@@ -1956,6 +1973,10 @@ class CompressedTensorsWNA16MoEMethod(CompressedTensorsMoEMethod):
1973
quant_config=self.moe_quant_config,
1974
)
1975
1976
+ @property
1977
+ def supports_eplb(self) -> bool:
1978
+ return True
1979
+
1980
1981
class CompressedTensorsW4A8Int8MoEMethod(CompressedTensorsMoEMethod):
1982
"""
vllm/model_executor/models/qwen3_vl_moe.py
+58
-4
@@ -15,7 +15,7 @@
15
# you may not use this file except in compliance with the License.
16
# You may obtain a copy of the License at
17
#
18
-# http://www.apache.org/licenses/LICENSE-2.0
18
+# http://www.apache.org/licenses/LICENSE-2.0
19
#
20
# Unless required by applicable law or agreed to in writing, software
21
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,7 +29,9 @@ from collections.abc import Callable, Iterable
29
from itertools import islice
30
31
import torch
32
-from transformers.models.qwen3_vl_moe.configuration_qwen3_vl_moe import Qwen3VLMoeConfig
32
+from transformers.models.qwen3_vl_moe.configuration_qwen3_vl_moe import (
33
+ Qwen3VLMoeConfig,
34
+)
35
36
from vllm.compilation.decorators import support_torch_compile
37
from vllm.config import VllmConfig
@@ -44,7 +46,12 @@ from vllm.model_executor.model_loader.weight_utils import (
46
from vllm.multimodal import MULTIMODAL_REGISTRY
47
from vllm.sequence import IntermediateTensors
48
47
-from .qwen3_moe import Qwen3MoeForCausalLM, Qwen3MoeModel
49
+from .interfaces import MixtureOfExperts
50
+from .qwen3_moe import (
51
+ Qwen3MoeForCausalLM,
52
+ Qwen3MoeModel,
53
+ Qwen3MoeSparseMoeBlock,
54
+)
55
from .qwen3_vl import (
56
Qwen3_VisionTransformer,
57
Qwen3VLDummyInputsBuilder,
@@ -344,12 +351,56 @@ class Qwen3MoeLLMForCausalLM(Qwen3MoeForCausalLM):
351
)
352
353
354
+class Qwen3VLMoeMixtureOfExperts(MixtureOfExperts):
355
+ def update_physical_experts_metadata(
356
+ self,
357
+ num_physical_experts: int,
358
+ num_local_physical_experts: int,
359
+ ) -> None:
360
+ assert self.num_local_physical_experts == num_local_physical_experts
361
+ self.num_physical_experts = num_physical_experts
362
+ self.num_local_physical_experts = num_local_physical_experts
363
+ self.num_redundant_experts = num_physical_experts - self.num_logical_experts
364
+ for layer in self.language_model.model.layers:
365
+ if isinstance(layer.mlp, Qwen3MoeSparseMoeBlock):
366
+ moe = layer.mlp
367
+ moe.n_local_physical_experts = num_local_physical_experts
368
+ moe.n_physical_experts = num_physical_experts
369
+ moe.n_redundant_experts = self.num_redundant_experts
370
+ moe.experts.update_expert_map()
371
+
372
+ def set_moe_parameters(self):
373
+ self.expert_weights = []
374
+
375
+ self.moe_layers = []
376
+ example_moe = None
377
+ for layer in self.language_model.model.layers:
378
+ if hasattr(layer, "mlp") and isinstance(layer.mlp, Qwen3MoeSparseMoeBlock):
379
+ example_moe = layer.mlp
380
+ self.moe_layers.append(layer.mlp.experts)
381
+
382
+ if example_moe is None:
383
+ raise RuntimeError("No Qwen3Moe layer found in the language_model.")
384
+
385
+ # Set MoE hyperparameters
386
+ self.num_moe_layers = len(self.moe_layers)
387
+ self.num_expert_groups = 1
388
+ self.num_shared_experts = 0
389
+ self.num_logical_experts = example_moe.n_logical_experts
390
+ self.num_physical_experts = example_moe.n_physical_experts
391
+ self.num_local_physical_experts = example_moe.n_local_physical_experts
392
+ self.num_routed_experts = example_moe.n_routed_experts
393
+ self.num_redundant_experts = example_moe.n_redundant_experts
394
+
395
+
396
@MULTIMODAL_REGISTRY.register_processor(
397
Qwen3VLMultiModalProcessor,
398
info=Qwen3VLMoeProcessingInfo,
399
dummy_inputs=Qwen3VLDummyInputsBuilder,
400
)
352
-class Qwen3VLMoeForConditionalGeneration(Qwen3VLForConditionalGeneration):
401
+class Qwen3VLMoeForConditionalGeneration(
402
+ Qwen3VLForConditionalGeneration, Qwen3VLMoeMixtureOfExperts
403
+):
404
packed_modules_mapping = {
405
"qkv_proj": [
406
"q_proj",
@@ -413,3 +464,6 @@ class Qwen3VLMoeForConditionalGeneration(Qwen3VLForConditionalGeneration):
464
self.deepstack_input_embeds = None
465
self.visual_dim = config.vision_config.out_hidden_size
466
self.multiscale_dim = self.visual_dim * self.deepstack_num_level
467
+
468
+ # Set MoE hyperparameters
469
+ self.set_moe_parameters()