@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / a8c536829c
Fork 0

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

Consolidate Nvidia ModelOpt quant config handling for all quantization methods (#28076)

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>

Shengliang Xu committed Nov 19, 2025 at 19:39 UTC a8c536829cb7b5564f54beff97e938666f286dd6
1 file changed +234 -265
vllm/model_executor/layers/quantization/modelopt.py
+234 -265
@@ -2,6 +2,7 @@
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 from collections.abc import Callable
5 +from fnmatch import fnmatch
6 from typing import TYPE_CHECKING, Any, Optional
7
8 import torch
@@ -13,7 +14,6 @@ import vllm.model_executor.layers.fused_moe.modular_kernel as mk
14 from vllm._custom_ops import cutlass_scaled_fp4_mm, scaled_fp4_quant
15 from vllm.logger import init_logger
16 from vllm.model_executor.layers.fused_moe.config import (
16 - FusedMoEConfig,
17 FusedMoEQuantConfig,
18 RoutingMethodType,
19 fp8_w8a8_moe_quant_config,
@@ -86,45 +86,218 @@ QUANT_ALGOS = ["FP8", "NVFP4"]
86 KV_CACHE_QUANT_ALGOS = ["FP8"]
87
88
89 -class ModelOptFp8Config(QuantizationConfig):
89 +class ModelOptFp8KVCacheMethod(BaseKVCacheMethod):
90 + """
91 + Supports loading kv-cache scaling factors from FP8 checkpoints.
92 + """
93 +
94 + def __init__(self, quant_config: "ModelOptQuantConfigBase"):
95 + super().__init__(quant_config)
96 +
97 +
98 +class ModelOptQuantConfigBase(QuantizationConfig):
99 + LinearMethodCls: type = LinearMethodBase
100 + FusedMoEMethodCls: type = FusedMoEMethodBase
101 + KVCacheMethodCls: type = BaseKVCacheMethod
102 +
103 + def __init__(
104 + self,
105 + exclude_modules: list[str],
106 + ):
107 + super().__init__()
108 + self.exclude_modules: list[str] = exclude_modules
109 +
110 + def is_layer_excluded(self, prefix: str) -> bool:
111 + """
112 + Check if a layer should be excluded from quantization.
113 +
114 + Handles both exact matching (for fused layers) and ModelOpt wildcard matching.
115 +
116 + The ModelOpt exclude_modules list is a list of wildcards.
117 + """
118 + if len(self.exclude_modules) == 0:
119 + return False
120 +
121 + # First check exact matching with fused layer support
122 + if is_layer_skipped(prefix, self.exclude_modules, self.packed_modules_mapping):
123 + return True
124 +
125 + # TODO: This special hard coded logic is not needed for quantized checkpoints
126 + # generated by ModelOpt >= 0.39.0 where they are handled natually by the
127 + # exclude_modules config. But need to keep them for loading quantized
128 + # checkpoints generated by older versions. Then check substring matching
129 + # for patterns not caught by exact match
130 + for exclude_module in self.exclude_modules:
131 + # Skip exact matches already handled above
132 + if exclude_module != prefix and (
133 + exclude_module in prefix
134 + or (
135 + prefix.startswith("language_model.")
136 + and exclude_module in prefix.removeprefix("language_model.")
137 + )
138 + ):
139 + return True
140 +
141 + # modelopt exclude modules are not simple strings, they are wildcards
142 + for wildcard_pattern in self.exclude_modules:
143 + if fnmatch(prefix, wildcard_pattern):
144 + return True
145 +
146 + return False
147 +
148 + def get_quant_method(
149 + self, layer: torch.nn.Module, prefix: str
150 + ) -> Optional["QuantizeMethodBase"]:
151 + from vllm.attention.layer import Attention # Avoid circular import
152 +
153 + # handle kv-cache first so we can focus only on weight quantization thereafter
154 + if isinstance(layer, Attention):
155 + return self.KVCacheMethodCls(self)
156 +
157 + # handle exclusion
158 + if self.is_layer_excluded(prefix):
159 + if isinstance(layer, LinearBase):
160 + return UnquantizedLinearMethod()
161 + return None
162 +
163 + # TODO: This special hard coded logic is not needed for quantized checkpoints
164 + # generated by ModelOpt >= 0.39.0 where they are handled natually by the
165 + # exclude_modules config. But need to keep them for loading quantized
166 + # checkpoints generated by older versions. Then check substring matching
167 + # for patterns not caught by exact match
168 + if "vision_tower" in prefix or "vision_model" in prefix:
169 + return UnquantizedLinearMethod()
170 +
171 + # now, the layer is quantized, handle it here
172 + if isinstance(layer, LinearBase):
173 + return self.LinearMethodCls(self)
174 + elif isinstance(layer, FusedMoE):
175 + return self.FusedMoEMethodCls(quant_config=self, layer=layer)
176 +
177 + return None
178 +
179 + def apply_vllm_mapper(self, hf_to_vllm_mapper: "WeightsMapper"):
180 + if len(self.exclude_modules) > 0:
181 + self.exclude_modules = hf_to_vllm_mapper.apply_list(self.exclude_modules)
182 +
183 + @staticmethod
184 + def get_config_filenames() -> list[str]:
185 + return ["hf_quant_config.json"]
186 +
187 + @classmethod
188 + def _from_config(
189 + cls,
190 + *,
191 + quant_method: str,
192 + kv_cache_quant_method: str | None,
193 + exclude_modules: list[str],
194 + original_config: dict[str, Any],
195 + group_size: int | None,
196 + ) -> "ModelOptQuantConfigBase":
197 + raise NotImplementedError("Please implement this function in sub classes")
198 +
199 + @classmethod
200 + def from_config(cls, config: dict[str, Any]) -> "ModelOptQuantConfigBase":
201 + # Handle both ModelOpt format and compressed-tensors style format
202 + if "quantization" in config:
203 + # Traditional ModelOpt format:
204 + # {"quantization": {"quant_algo": "..."}}
205 + quant_config = cls.get_from_keys(config, ["quantization"])
206 + if not isinstance(quant_config, dict):
207 + raise ValueError("Expected 'quantization' to be a dictionary in config")
208 +
209 + quant_method = quant_config.get("quant_algo")
210 +
211 + # Handle kv_cache_quant_algo with proper type validation
212 + kv_cache_quant_method = quant_config.get("kv_cache_quant_algo")
213 +
214 + # Handle group_size with proper type validation
215 + group_size_raw = quant_config.get("group_size")
216 +
217 + # "exclude_modules" is the key in the legacy hf_quant_config.json
218 + exclude_modules = quant_config.get("exclude_modules", [])
219 + else:
220 + # Compressed-tensors style format:
221 + # {"quant_algo": "...", "quant_method": "modelopt"}
222 + quant_method = config.get("quant_algo")
223 + kv_cache_quant_method = config.get("kv_cache_quant_algo")
224 + # "ignore" is the key in config.json
225 + exclude_modules = config.get("ignore", [])
226 + group_size_raw = config.get("group_size")
227 +
228 + if not quant_method:
229 + raise ValueError("Missing 'quant_algo' in quantization config")
230 +
231 + if kv_cache_quant_method is None:
232 + # No KV cache quantization, keep this branch just to have this comment
233 + pass
234 + elif not isinstance(kv_cache_quant_method, str):
235 + raise ValueError(
236 + f"kv_cache_quant_algo must be a string, got "
237 + f"{type(kv_cache_quant_method)}"
238 + )
239 +
240 + if not isinstance(exclude_modules, list):
241 + raise ValueError(
242 + f"exclude_modules must be a list, got {type(exclude_modules)}"
243 + )
244 +
245 + if group_size_raw is None:
246 + group_size = None
247 + elif isinstance(group_size_raw, int):
248 + group_size = group_size_raw
249 + else:
250 + try:
251 + group_size = int(group_size_raw)
252 + except (ValueError, TypeError):
253 + raise ValueError(
254 + f"group_size must be an integer, got {type(group_size_raw)}"
255 + ) from None
256 +
257 + if quant_method not in QUANT_ALGOS:
258 + raise ValueError(
259 + f"ModelOpt currently only supports: {QUANT_ALGOS} "
260 + "quantizations in vLLM. Please check the "
261 + "`hf_quant_config.json` file for your model's "
262 + "quant configuration."
263 + )
264 + return cls._from_config(
265 + quant_method=quant_method,
266 + kv_cache_quant_method=kv_cache_quant_method,
267 + exclude_modules=exclude_modules,
268 + group_size=group_size,
269 + original_config=config,
270 + )
271 +
272 +
273 +class ModelOptFp8Config(ModelOptQuantConfigBase):
274 """Config class for ModelOpt FP8."""
275
276 def __init__(
277 self,
94 - is_checkpoint_fp8_serialized: bool = False,
95 - kv_cache_quant_method: str | None = None,
96 - exclude_modules: list[str] | None = None,
278 + is_checkpoint_fp8_serialized: bool,
279 + kv_cache_quant_method: str | None,
280 + exclude_modules: list[str],
281 ) -> None:
98 - super().__init__()
282 + super().__init__(exclude_modules)
283 self.is_checkpoint_fp8_serialized = is_checkpoint_fp8_serialized
284 self.kv_cache_quant_method = kv_cache_quant_method
101 - self.exclude_modules = exclude_modules or []
285 if is_checkpoint_fp8_serialized:
286 logger.warning(
287 "Detected ModelOpt fp8 checkpoint. Please note that"
288 " the format is experimental and could change."
289 )
290
108 - @classmethod
109 - def get_name(cls) -> QuantizationMethods:
291 + def get_name(self) -> QuantizationMethods:
292 return "modelopt"
293
112 - @classmethod
113 - def get_supported_act_dtypes(cls) -> list[torch.dtype]:
294 + def get_supported_act_dtypes(self) -> list[torch.dtype]:
295 return [torch.bfloat16, torch.half]
296
297 @classmethod
298 def get_min_capability(cls) -> int:
299 return 89
300
120 - @classmethod
121 - def get_config_filenames(cls) -> list[str]:
122 - return ["hf_quant_config.json"]
123 -
124 - def apply_vllm_mapper(self, hf_to_vllm_mapper: "WeightsMapper"):
125 - if self.exclude_modules is not None:
126 - self.exclude_modules = hf_to_vllm_mapper.apply_list(self.exclude_modules)
127 -
301 @classmethod
302 def override_quantization_method(
303 cls, hf_quant_cfg, user_quant
@@ -158,88 +331,19 @@ class ModelOptFp8Config(QuantizationConfig):
331 return None
332
333 @classmethod
161 - def from_config(cls, config: dict[str, Any]) -> "ModelOptFp8Config":
162 - # Handle both ModelOpt format and compressed-tensors style format
163 - if "quantization" in config:
164 - # ModelOpt format: {"quantization": {"quant_algo": "..."}}
165 - quant_config = cls.get_from_keys(config, ["quantization"])
166 - if not isinstance(quant_config, dict):
167 - raise ValueError("Expected 'quantization' to be a dictionary in config")
168 - quant_method = quant_config.get("quant_algo", "")
169 - if not quant_method:
170 - raise ValueError("Missing 'quant_algo' in quantization config")
171 - kv_cache_quant_method = quant_config.get("kv_cache_quant_algo")
172 - # "exclude_modules" is the key in the legacy hf_quant_config.json
173 - exclude_modules = quant_config.get("exclude_modules")
174 - else:
175 - # Compressed-tensors style format:
176 - # {"quant_algo": "...", "quant_method": "modelopt"}
177 - quant_method = config.get("quant_algo", "")
178 - kv_cache_quant_method = config.get("kv_cache_quant_algo")
179 - # "ignore" is the key in config.json
180 - exclude_modules = config.get("ignore")
181 -
182 - if quant_method not in QUANT_ALGOS:
183 - raise ValueError(
184 - f"ModelOpt currently only supports: {QUANT_ALGOS} "
185 - "quantizations in vLLM. Please check the "
186 - "`hf_quant_config.json` file for your model's "
187 - "quant configuration."
188 - )
334 + def _from_config(
335 + cls,
336 + *,
337 + quant_method: str,
338 + kv_cache_quant_method: str | None,
339 + exclude_modules: list[str],
340 + original_config: dict[str, Any],
341 + **kwargs: Any,
342 + ) -> "ModelOptFp8Config":
343 is_checkpoint_fp8_serialized = "FP8" in quant_method
344
345 return cls(is_checkpoint_fp8_serialized, kv_cache_quant_method, exclude_modules)
346
193 - def is_layer_excluded(self, prefix: str) -> bool:
194 - """
195 - Check if a layer should be excluded from quantization.
196 - Handles both exact matching (for fused layers) and substring matching.
197 -
198 - This method handles both regular models and multimodal models that use
199 - the language_model prefix. For multimodal models, it checks if the
200 - module name (without the language_model prefix) is in the exclude list.
201 - """
202 - if self.exclude_modules is None:
203 - return False
204 -
205 - # First check exact matching with fused layer support
206 - if is_layer_skipped(prefix, self.exclude_modules, self.packed_modules_mapping):
207 - return True
208 -
209 - # Then check substring matching for patterns not caught by exact match
210 - for module in self.exclude_modules:
211 - # Skip exact matches already handled above
212 - if module != prefix and (
213 - module in prefix
214 - or (
215 - prefix.startswith("language_model.")
216 - and module in prefix.removeprefix("language_model.")
217 - )
218 - ):
219 - return True
220 - return False
221 -
222 - def get_quant_method(
223 - self, layer: torch.nn.Module, prefix: str
224 - ) -> Optional["QuantizeMethodBase"]:
225 - from vllm.attention.layer import ( # Avoid circular import
226 - Attention,
227 - MLAAttention,
228 - )
229 -
230 - if isinstance(layer, LinearBase):
231 - if self.is_layer_excluded(prefix):
232 - return UnquantizedLinearMethod()
233 - # Check if this is a vision model layer that should not be quantized
234 - if "vision_tower" in prefix or "vision_model" in prefix:
235 - return UnquantizedLinearMethod()
236 - return ModelOptFp8LinearMethod(self)
237 - elif isinstance(layer, (Attention, MLAAttention)):
238 - return ModelOptFp8KVCacheMethod(self)
239 - elif isinstance(layer, FusedMoE):
240 - return ModelOptFp8MoEMethod(self, layer)
241 - return None
242 -
347
348 class ModelOptFp8LinearMethod(LinearMethodBase):
349 """Linear method for Model Optimizer static quantization.
@@ -344,7 +448,7 @@ class ModelOptFp8MoEMethod(FusedMoEMethodBase):
448 def __init__(
449 self,
450 quant_config: ModelOptFp8Config,
347 - layer: torch.nn.Module,
451 + layer: FusedMoE,
452 ) -> None:
453 super().__init__(layer.moe_config)
454 self.layer = layer
@@ -686,7 +790,12 @@ class ModelOptFp8MoEMethod(FusedMoEMethodBase):
790 )
791
792
689 -class ModelOptNvFp4Config(QuantizationConfig):
793 +ModelOptFp8Config.LinearMethodCls = ModelOptFp8LinearMethod
794 +ModelOptFp8Config.FusedMoEMethodCls = ModelOptFp8MoEMethod
795 +ModelOptFp8Config.KVCacheMethodCls = ModelOptFp8KVCacheMethod
796 +
797 +
798 +class ModelOptNvFp4Config(ModelOptQuantConfigBase):
799 """Config class for ModelOpt FP4."""
800
801 def __init__(
@@ -696,7 +805,7 @@ class ModelOptNvFp4Config(QuantizationConfig):
805 exclude_modules: list[str],
806 group_size: int = 16,
807 ) -> None:
699 - super().__init__()
808 + super().__init__(exclude_modules)
809 self.is_checkpoint_nvfp4_serialized = is_checkpoint_nvfp4_serialized
810 if is_checkpoint_nvfp4_serialized:
811 logger.warning(
@@ -706,28 +815,17 @@ class ModelOptNvFp4Config(QuantizationConfig):
815
816 self.group_size = group_size
817 self.kv_cache_quant_algo = kv_cache_quant_algo
709 - self.exclude_modules = exclude_modules
818
711 - @classmethod
712 - def get_name(cls) -> QuantizationMethods:
819 + def get_name(self) -> QuantizationMethods:
820 return "modelopt_fp4"
821
715 - @classmethod
716 - def get_supported_act_dtypes(cls) -> list[torch.dtype]:
822 + def get_supported_act_dtypes(self) -> list[torch.dtype]:
823 return [torch.bfloat16, torch.half, torch.float8_e4m3fn]
824
825 @classmethod
826 def get_min_capability(cls) -> int:
827 return 80
828
723 - @classmethod
724 - def get_config_filenames(cls) -> list[str]:
725 - return ["hf_quant_config.json"]
726 -
727 - def apply_vllm_mapper(self, hf_to_vllm_mapper: "WeightsMapper"):
728 - if self.exclude_modules is not None:
729 - self.exclude_modules = hf_to_vllm_mapper.apply_list(self.exclude_modules)
730 -
829 @classmethod
830 def override_quantization_method(
831 cls, hf_quant_cfg, user_quant
@@ -761,105 +859,25 @@ class ModelOptNvFp4Config(QuantizationConfig):
859 return None
860
861 @classmethod
764 - def from_config(cls, config: dict[str, Any]) -> "ModelOptNvFp4Config":
765 - # Handle both traditional ModelOpt format and compressed-tensors
766 - # style format
767 - if "quantization" in config:
768 - # Traditional ModelOpt format:
769 - # {"quantization": {"quant_algo": "..."}}
770 - quant_config = cls.get_from_keys(config, ["quantization"])
771 - if not isinstance(quant_config, dict):
772 - raise ValueError("Expected 'quantization' to be a dictionary in config")
773 -
774 - quant_method = quant_config.get("quant_algo", "")
775 - if not quant_method:
776 - raise ValueError("Missing 'quant_algo' in quantization config")
777 -
778 - # Handle kv_cache_quant_algo with proper type validation
779 - kv_cache_quant_algo_raw = quant_config.get("kv_cache_quant_algo")
780 - if kv_cache_quant_algo_raw is None:
781 - # No KV cache quantization by default
782 - kv_cache_quant_algo = None
783 - elif isinstance(kv_cache_quant_algo_raw, str):
784 - kv_cache_quant_algo = kv_cache_quant_algo_raw
785 - else:
786 - raise ValueError(
787 - f"kv_cache_quant_algo must be a string, got "
788 - f"{type(kv_cache_quant_algo_raw)}"
789 - )
790 -
791 - # Handle group_size with proper type validation
792 - group_size_raw = quant_config.get("group_size")
793 - if group_size_raw is None:
794 - group_size = 16 # Default value
795 - elif isinstance(group_size_raw, int):
796 - group_size = group_size_raw
797 - else:
798 - try:
799 - group_size = int(group_size_raw)
800 - except (ValueError, TypeError):
801 - raise ValueError(
802 - f"group_size must be an integer, got {type(group_size_raw)}"
803 - ) from None
804 -
805 - # "exclude_modules" is the key in the legacy hf_quant_config.json
806 - exclude_modules = quant_config.get("exclude_modules", [])
807 - if not isinstance(exclude_modules, list):
808 - raise ValueError(
809 - f"exclude_modules must be a list, got {type(exclude_modules)}"
810 - )
811 - else:
812 - # Compressed-tensors style format:
813 - # {"quant_algo": "...", "quant_method": "modelopt"}
814 - quant_method = config.get("quant_algo", "")
815 -
816 - # Handle kv_cache_quant_algo with proper type validation
817 - kv_cache_quant_algo_raw = config.get("kv_cache_quant_algo")
818 - if kv_cache_quant_algo_raw is None:
819 - # No KV cache quantization by default
820 - kv_cache_quant_algo = None
821 - elif isinstance(kv_cache_quant_algo_raw, str):
822 - kv_cache_quant_algo = kv_cache_quant_algo_raw
823 - else:
824 - raise ValueError(
825 - f"kv_cache_quant_algo must be a string, got "
826 - f"{type(kv_cache_quant_algo_raw)}"
827 - )
828 -
829 - # Handle group_size with proper type validation
830 - group_size_raw = config.get("group_size")
831 - if group_size_raw is None:
832 - group_size = 16 # Default value
833 - elif isinstance(group_size_raw, int):
834 - group_size = group_size_raw
835 - else:
836 - try:
837 - group_size = int(group_size_raw)
838 - except (ValueError, TypeError):
839 - raise ValueError(
840 - f"group_size must be an integer, got {type(group_size_raw)}"
841 - ) from None
842 -
843 - # "ignore" is the key in config.json
844 - exclude_modules = config.get("ignore", [])
845 - if not isinstance(exclude_modules, list):
846 - raise ValueError(
847 - f"exclude_modules must be a list, got {type(exclude_modules)}"
848 - )
849 -
850 - if quant_method not in QUANT_ALGOS:
851 - raise ValueError(
852 - f"ModelOpt currently only supports: {QUANT_ALGOS} "
853 - "quantizations in vLLM. Please check the "
854 - "`hf_quant_config.json` file for your model's "
855 - "quant configuration."
856 - )
862 + def _from_config(
863 + cls,
864 + *,
865 + quant_method: str,
866 + kv_cache_quant_method: str | None,
867 + exclude_modules: list[str],
868 + original_config: dict[str, Any],
869 + group_size: int | None,
870 + **kwargs: Any,
871 + ) -> "ModelOptNvFp4Config":
872 is_checkpoint_nvfp4_serialized = "NVFP4" in quant_method
873
874 + if group_size is None:
875 + group_size = 16 # Default value
876 +
877 # For FP4, these fields are required
860 - if is_checkpoint_nvfp4_serialized and "quantization" in config:
878 + if is_checkpoint_nvfp4_serialized and "quantization" in original_config:
879 # Check if required fields are present in the quantization config
862 - quant_config = config["quantization"]
880 + quant_config = original_config["quantization"]
881 required_fields = ["group_size", "kv_cache_quant_algo", "exclude_modules"]
882 missing_fields = [
883 field for field in required_fields if field not in quant_config
@@ -872,64 +890,11 @@ class ModelOptNvFp4Config(QuantizationConfig):
890
891 return cls(
892 is_checkpoint_nvfp4_serialized,
875 - kv_cache_quant_algo,
893 + kv_cache_quant_method,
894 exclude_modules,
895 group_size,
896 )
897
880 - def is_layer_excluded(self, prefix: str) -> bool:
881 - """
882 - Check if a layer should be excluded from quantization.
883 - Handles both exact matching (for fused layers) and pattern matching.
884 - """
885 - # First check exact matching with fused layer support
886 - if is_layer_skipped(prefix, self.exclude_modules, self.packed_modules_mapping):
887 - return True
888 -
889 - # Check regex pattern matching for patterns not caught by exact match
890 - import regex as re
891 -
892 - for pattern in self.exclude_modules:
893 - # Skip patterns that would be caught by exact matching
894 - if "*" in pattern or "." in pattern:
895 - regex_str = pattern.replace(".", r"\.").replace("*", r".*")
896 - if re.fullmatch(regex_str, prefix):
897 - return True
898 - return False
899 -
900 - def get_quant_method(
901 - self, layer: torch.nn.Module, prefix: str
902 - ) -> Optional["QuantizeMethodBase"]:
903 - from vllm.attention.layer import ( # Avoid circular import
904 - Attention,
905 - MLAAttention,
906 - )
907 -
908 - skip_layer = self.is_layer_excluded(prefix)
909 - if isinstance(layer, LinearBase):
910 - if skip_layer:
911 - return UnquantizedLinearMethod()
912 - # Check if this is a vision model layer that should not be quantized
913 - if "vision_tower" in prefix or "vision_model" in prefix:
914 - return UnquantizedLinearMethod()
915 - return ModelOptNvFp4LinearMethod(self)
916 - elif isinstance(layer, (Attention, MLAAttention)):
917 - return ModelOptFp8KVCacheMethod(self)
918 - elif isinstance(layer, FusedMoE):
919 - if skip_layer:
920 - return None
921 - return ModelOptNvFp4FusedMoE(self, layer.moe_config, layer)
922 - return None
923 -
924 -
925 -class ModelOptFp8KVCacheMethod(BaseKVCacheMethod):
926 - """
927 - Supports loading kv-cache scaling factors from FP8 checkpoints.
928 - """
929 -
930 - def __init__(self, quant_config: ModelOptFp8Config | ModelOptNvFp4Config):
931 - super().__init__(quant_config)
932 -
898
899 class ModelOptNvFp4LinearMethod(LinearMethodBase):
900 """Linear method for Model Optimizer NVFP4.
@@ -1157,14 +1122,13 @@ class ModelOptNvFp4FusedMoE(FusedMoEMethodBase):
1122 def __init__(
1123 self,
1124 quant_config: ModelOptNvFp4Config,
1160 - moe: FusedMoEConfig,
1161 - layer: torch.nn.Module,
1125 + layer: FusedMoE,
1126 ) -> None:
1127 from vllm.model_executor.layers.quantization.utils.nvfp4_moe_support import (
1128 detect_nvfp4_moe_support, # noqa: E501
1129 )
1130
1167 - super().__init__(moe)
1131 + super().__init__(layer.moe_config)
1132 self.quant_config = quant_config
1133 self.layer = layer
1134 _nvfp4 = detect_nvfp4_moe_support(self.__class__.__name__)
@@ -1802,3 +1766,8 @@ class ModelOptNvFp4FusedMoE(FusedMoEMethodBase):
1766 k=x.shape[1],
1767 e=layer.w13_weight.shape[0],
1768 )
1769 +
1770 +
1771 +ModelOptNvFp4Config.LinearMethodCls = ModelOptNvFp4LinearMethod
1772 +ModelOptNvFp4Config.FusedMoEMethodCls = ModelOptNvFp4FusedMoE
1773 +ModelOptNvFp4Config.KVCacheMethodCls = ModelOptFp8KVCacheMethod