Make compressed-tensors MoEs support ignored layers (#17828)

Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
Co-authored-by: Peng Zhang <aniz1905@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
LHXuuu
2026-02-09 14:37:33 +08:00
committed by GitHub
parent 14652243bd
commit 107958a489
2 changed files with 80 additions and 22 deletions

View File

@@ -147,15 +147,6 @@ class CompressedTensorsConfig(QuantizationConfig):
) -> Optional[QuantizeMethodBase]:
from sglang.srt.layers.linear import LinearBase
# Check if the layer is skipped for quantization.
# TODO (@robertgshaw2): support module names
if should_ignore_layer(
prefix, ignore=self.ignore, fused_mapping=self.packed_modules_mapping
):
if isinstance(layer, LinearBase):
return UnquantizedLinearMethod()
return None
if isinstance(layer, LinearBase):
# If linear_fp8_config is set, use FP8 for linear layers
# This allows mixed quantization: experts with int4, linear layers with fp8
@@ -172,6 +163,20 @@ class CompressedTensorsConfig(QuantizationConfig):
return CompressedTensorsMoEMethod.get_moe_method(self, layer, prefix)
return None
def _add_fused_moe_to_target_scheme_map(self):
"""
Helper function to update target_scheme_map
since linear layers get fused into FusedMoE
targeting 'Linear' needs to also match
FusedMoE modules.
"""
if (
"Linear" not in self.target_scheme_map
or "FusedMoE" in self.target_scheme_map
):
return
self.target_scheme_map["FusedMoE"] = self.target_scheme_map["Linear"]
@property
def weight_block_size(self) -> Optional[List[int]]:
"""Get the weight block size from the quantization config."""
@@ -619,17 +624,11 @@ class CompressedTensorsConfig(QuantizationConfig):
# so we do not have to re-write these functions
# need to make accelerate optional in ct to do this
# Will be empty for models with only sparsity
weight_quant = input_quant = None
if self.target_scheme_map:
matched_target = find_matched_target(
layer_name=layer_name,
module=layer,
targets=self.target_scheme_map.keys(),
fused_mapping=self.packed_modules_mapping,
)
scheme_dict = self.target_scheme_map[matched_target]
# Use the new get_scheme_dict method to extract QuantizationArgs
scheme_dict = self.get_scheme_dict(layer, layer_name)
weight_quant = None
input_quant = None
if scheme_dict:
weight_quant = scheme_dict.get("weights")
input_quant = scheme_dict.get("input_activations")
@@ -677,6 +676,37 @@ class CompressedTensorsConfig(QuantizationConfig):
logger.debug("Using scheme: %s for %s", scheme.__class__.__name__, layer_name)
return scheme
def get_scheme_dict(
self, layer: torch.nn.Module, layer_name: str | None = None
) -> dict[str, QuantizationArgs | str | None] | None:
"""
Extract the QuantizationArgs for a given layer.
Returns:
dict with {
"weights": QuantizationArgs,
"input_activations": QuantizationArgs | None,
"format": str | None
} | None
"""
if should_ignore_layer(
layer_name, ignore=self.ignore, fused_mapping=self.packed_modules_mapping
):
return None
# Will be empty for models with only sparsity
if self.target_scheme_map:
matched_target = find_matched_target(
layer_name=layer_name,
module=layer,
targets=self.target_scheme_map.keys(),
fused_mapping=self.packed_modules_mapping,
)
return self.target_scheme_map[matched_target]
return None
def get_cache_scale(self, name: str) -> Optional[str]:
"""
Check whether the param name matches the format for k/v cache scales

View File

@@ -45,6 +45,7 @@ from sglang.srt.layers.quantization.fp8_utils import (
)
from sglang.srt.layers.quantization.gptq import gptq_marlin_moe_repack
from sglang.srt.layers.quantization.marlin_utils import marlin_moe_permute_scales
from sglang.srt.layers.quantization.unquant import UnquantizedFusedMoEMethod
from sglang.srt.layers.quantization.utils import (
all_close_1d,
per_tensor_dequantize,
@@ -131,8 +132,35 @@ class CompressedTensorsMoEMethod(FusedMoEMethodBase):
# TODO: @dsikka: refactor this to use schemes as other kernels
# are supported + check if the layer is being ignored.
weight_quant = quant_config.target_scheme_map["Linear"].get("weights")
input_quant = quant_config.target_scheme_map["Linear"].get("input_activations")
# FusedMoE was made by combining multiple Linears so need to
# make sure quantization config for Linear can target it
quant_config._add_fused_moe_to_target_scheme_map()
unfused_names = [
prefix + proj_name
for proj_name in [".0.gate_proj", ".0.up_proj", ".0.down_proj"]
]
# TODO: refactor this to use expert_mapping and check all layer numbers
all_scheme_dicts = [
quant_config.get_scheme_dict(layer, name) for name in unfused_names
]
scheme_dict = all_scheme_dicts[0] if all_scheme_dicts else None
# multiple schemes found
if not all(d == scheme_dict for d in all_scheme_dicts):
raise ValueError(
"All MoE projections need to have same "
"quantization scheme but found multiple"
)
use_triton_kernels = get_moe_runner_backend().is_triton_kernels()
use_flashinfer_trtllm_moe = get_moe_runner_backend().is_flashinfer_trtllm()
if scheme_dict is None: # ignored layer
return UnquantizedFusedMoEMethod(
use_triton_kernels, use_flashinfer_trtllm_moe
)
weight_quant = scheme_dict.get("weights")
input_quant = scheme_dict.get("input_activations")
if quant_config._is_wNa16_group_channel(weight_quant, input_quant):
if not _is_npu: