`[Model][Quantization] Add Ling-3.0-flash-fp8 support` (#51265)
Signed-off-by: Isotr0py <Isotr0py@outlook.com> Co-authored-by: Isotr0py <Isotr0py@outlook.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
zexplorerhj committed
Aug 10, 2026 at 14:09 UTC
ba1cdcfcf05f581d1f58cc911644fed62317c8c6
6 files changed
+298
-36
tests/quantization/test_quark.py
+23
-2
@@ -701,11 +701,32 @@ def test_non_fused_layer_unaffected():
701
702
703
def test_substr_match_on_fused_name():
704
- # skip_with_substr=True path: fused-name substring match should also
704
+ # Substring matching: a fused-name match should also
705
# short-circuit before shard expansion.
706
assert is_layer_skipped(
707
prefix="model.layers.0.self_attn.qkv_proj",
708
ignored_layers=["self_attn.qkv_proj"],
709
fused_mapping=FUSED_MAPPING,
710
- skip_with_substr=True,
710
+ match_mode="substring",
711
+ )
712
+
713
+
714
+@pytest.mark.parametrize(
715
+ ("prefix", "ignored_layer", "expected"),
716
+ [
717
+ ("model.layers.0.self_attn.b_proj", "b_proj", True),
718
+ ("model.layers.0.self_attn.q_b_proj", "b_proj", False),
719
+ ("model.layers.0.self_attn.kv_b_proj", "b_proj", False),
720
+ ("model.layers.5.self_attn.g_proj", "5.self_attn.g_proj", True),
721
+ ("model.layers.6.self_attn.g_proj", "5.self_attn.g_proj", False),
722
+ ],
723
+)
724
+def test_suffix_match_at_module_boundary(prefix, ignored_layer, expected):
725
+ assert (
726
+ is_layer_skipped(
727
+ prefix=prefix,
728
+ ignored_layers=[ignored_layer],
729
+ match_mode="suffix",
730
+ )
731
+ is expected
732
)
vllm/model_executor/layers/quantization/auto_awq.py
+2
-2
@@ -292,7 +292,7 @@ class AutoAWQConfig(QuantizationConfig):
292
prefix,
293
self.modules_to_not_convert,
294
self.packed_modules_mapping,
295
- skip_with_substr=True,
295
+ match_mode="substring",
296
):
297
return UnquantizedLinearMethod()
298
@@ -335,7 +335,7 @@ class AutoAWQConfig(QuantizationConfig):
335
if is_layer_skipped(
336
prefix,
337
getattr(self, "modules_to_not_convert", []),
338
- skip_with_substr=True,
338
+ match_mode="substring",
339
):
340
return UnquantizedFusedMoEMethod(layer.moe_config)
341
vllm/model_executor/layers/quantization/fp8.py
+6
-1
@@ -1,7 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
-from typing import TYPE_CHECKING, Any
4
+from typing import TYPE_CHECKING, Any, Literal
5
6
import torch
7
@@ -108,6 +108,9 @@ class Fp8Config(QuantizationConfig):
108
raise ValueError(f"Unsupported activation scheme {activation_scheme}")
109
self.activation_scheme = activation_scheme
110
self.ignored_layers = ignored_layers or []
111
+ self.ignored_layers_match_mode: Literal["exact", "substring", "suffix"] = (
112
+ "exact"
113
+ )
114
self.store_dtype = store_dtype
115
if weight_block_size is not None:
116
if not is_checkpoint_fp8_serialized:
@@ -177,6 +180,7 @@ class Fp8Config(QuantizationConfig):
180
prefix=prefix,
181
ignored_layers=self.ignored_layers,
182
fused_mapping=self.packed_modules_mapping,
183
+ match_mode=self.ignored_layers_match_mode,
184
):
185
return UnquantizedLinearMethod()
186
if not self.is_checkpoint_fp8_serialized:
@@ -196,6 +200,7 @@ class Fp8Config(QuantizationConfig):
200
prefix=prefix,
201
ignored_layers=self.ignored_layers,
202
fused_mapping=self.packed_modules_mapping,
203
+ match_mode=self.ignored_layers_match_mode,
204
):
205
return UnquantizedFusedMoEMethod(layer.moe_config)
206
if self.store_dtype == "mxfp4":
vllm/model_executor/layers/quantization/utils/quant_utils.py
+20
-8
@@ -5,7 +5,7 @@
5
from collections.abc import Callable, Mapping
6
from dataclasses import dataclass
7
from types import MappingProxyType
8
-from typing import TYPE_CHECKING, ClassVar, NamedTuple
8
+from typing import TYPE_CHECKING, ClassVar, Literal, NamedTuple
9
10
import numpy
11
import torch
@@ -604,7 +604,7 @@ def is_layer_skipped(
604
ignored_layers: list[str],
605
fused_mapping: Mapping[str, list[str]] = MappingProxyType({}),
606
*,
607
- skip_with_substr: bool = False,
607
+ match_mode: Literal["exact", "substring", "suffix"] = "exact",
608
) -> bool:
609
def prefix_full_match(prefix: str, ignored_layers: list[str]) -> bool:
610
return prefix in ignored_layers
@@ -613,7 +613,22 @@ def is_layer_skipped(
613
def substr_match(prefix: str, ignored_layers: list[str]) -> bool:
614
return any(layer in prefix for layer in ignored_layers)
615
616
- match_func = substr_match if skip_with_substr else prefix_full_match
616
+ # Match abbreviated module paths at a component boundary. For example,
617
+ # ``b_proj`` matches ``model.layers.0.self_attn.b_proj`` but not
618
+ # ``model.layers.0.self_attn.q_b_proj``.
619
+ def suffix_match(prefix: str, ignored_layers: list[str]) -> bool:
620
+ return any(
621
+ prefix == layer or prefix.endswith(f".{layer}") for layer in ignored_layers
622
+ )
623
+
624
+ if match_mode == "exact":
625
+ match_func = prefix_full_match
626
+ elif match_mode == "substring":
627
+ match_func = substr_match
628
+ elif match_mode == "suffix":
629
+ match_func = suffix_match
630
+ else:
631
+ raise ValueError(f"Unsupported layer skip match mode: {match_mode}")
632
633
# prefix: model.layers.0.self_attn.q_proj
634
# proj_name: q_proj
@@ -649,14 +664,11 @@ def is_layer_skipped(
664
"are quantized. All shards of fused layers "
665
"to have the same precision."
666
)
652
- elif "experts" in prefix and not skip_with_substr:
667
+ elif "experts" in prefix and match_mode == "exact":
668
expert_ignore_layers = filter(
669
lambda layer_name: "experts" in layer_name, ignored_layers
670
)
656
- return any(
657
- prefix in layer_name if not skip_with_substr else layer_name in prefix
658
- for layer_name in expert_ignore_layers
659
- )
671
+ return any(prefix in layer_name for layer_name in expert_ignore_layers)
672
else:
673
is_skipped = match_func(prefix, ignored_layers)
674
vllm/model_executor/models/bailing_moe_v3.py
+224
-21
@@ -10,6 +10,8 @@ vLLM's parallel linear layers, MLA kernel, KDA kernel and fused MoE loader.
10
11
import copy
12
from collections.abc import Callable, Iterable
13
+from math import lcm
14
+from typing import TypeGuard
15
16
import torch
17
import torch.nn as nn
@@ -55,6 +57,8 @@ from vllm.model_executor.layers.mla import (
57
MultiHeadLatentAttentionWrapper,
58
)
59
from vllm.model_executor.layers.quantization.base_config import QuantizationConfig
60
+from vllm.model_executor.layers.quantization.fp8 import Fp8Config
61
+from vllm.model_executor.layers.quantization.utils.quant_utils import is_layer_skipped
62
from vllm.model_executor.layers.rotary_embedding import get_rope
63
from vllm.model_executor.layers.vocab_parallel_embedding import (
64
ParallelLMHead,
@@ -79,7 +83,13 @@ from vllm.v1.attention.backends.gdn_attn import GDNAttentionMetadata
83
from vllm.v1.attention.backends.registry import MambaAttentionBackendEnum
84
85
from .interfaces import HasInnerState, IsHybrid, SupportsPP
82
-from .utils import PPMissingLayer, is_pp_missing_parameter, make_layers, maybe_prefix
86
+from .utils import (
87
+ PPMissingLayer,
88
+ WeightsMapper,
89
+ is_pp_missing_parameter,
90
+ make_layers,
91
+ maybe_prefix,
92
+)
93
94
95
def bailing_v3_kda_attention(
@@ -193,6 +203,155 @@ def _load_a_log(param: torch.nn.Parameter, loaded_weight: torch.Tensor) -> None:
203
sharded_weight_loader(2)(param, loaded_weight)
204
205
206
+def _is_block_fp8_config(
207
+ quant_config: QuantizationConfig | None,
208
+) -> TypeGuard[Fp8Config]:
209
+ return (
210
+ isinstance(quant_config, Fp8Config)
211
+ and quant_config.weight_block_size is not None
212
+ )
213
+
214
+
215
+def _configure_ling_fp8_quant_config(
216
+ quant_config: QuantizationConfig | None,
217
+) -> None:
218
+ if _is_block_fp8_config(quant_config):
219
+ quant_config.ignored_layers_match_mode = "suffix"
220
+
221
+
222
+def _is_fp8_module_excluded(
223
+ quant_config: QuantizationConfig | None,
224
+ prefix: str,
225
+) -> bool:
226
+ """Match Ling's abbreviated FP8 exclusions against mapped vLLM prefixes."""
227
+ if not _is_block_fp8_config(quant_config):
228
+ return False
229
+
230
+ return is_layer_skipped(
231
+ prefix=prefix,
232
+ ignored_layers=quant_config.ignored_layers,
233
+ fused_mapping=quant_config.packed_modules_mapping,
234
+ match_mode=quant_config.ignored_layers_match_mode,
235
+ )
236
+
237
+
238
+def _get_block_fp8_mlp_padded_intermediate_size(
239
+ quant_config: QuantizationConfig | None,
240
+ intermediate_size: int,
241
+ prefix: str,
242
+) -> int:
243
+ """Pad a block-FP8 MLP so each TP shard contains whole quant blocks."""
244
+ if not _is_block_fp8_config(quant_config):
245
+ return intermediate_size
246
+ block_size = quant_config.weight_block_size
247
+ assert block_size is not None
248
+
249
+ alignments: list[int] = []
250
+ if not _is_fp8_module_excluded(quant_config, f"{prefix}.gate_up_proj"):
251
+ alignments.append(int(block_size[0]))
252
+ if not _is_fp8_module_excluded(quant_config, f"{prefix}.down_proj"):
253
+ alignments.append(int(block_size[1]))
254
+ if not alignments:
255
+ return intermediate_size
256
+
257
+ tp_size = get_tensor_model_parallel_world_size()
258
+ tp_alignment = tp_size * lcm(*alignments)
259
+ return (intermediate_size + tp_alignment - 1) // tp_alignment * tp_alignment
260
+
261
+
262
+def _pad_block_fp8_mlp_checkpoint_tensor(
263
+ quant_config: QuantizationConfig,
264
+ name: str,
265
+ loaded_weight: torch.Tensor,
266
+ intermediate_size: int,
267
+ padded_intermediate_size: int,
268
+) -> torch.Tensor:
269
+ """Zero-pad an MLP checkpoint tensor on its intermediate dimension."""
270
+ if padded_intermediate_size == intermediate_size:
271
+ return loaded_weight
272
+
273
+ block_size = getattr(quant_config, "weight_block_size", None)
274
+ assert block_size is not None
275
+
276
+ if ".down_proj." in name:
277
+ if name.endswith(".bias"):
278
+ return loaded_weight
279
+ dim = 1
280
+ block = int(block_size[1])
281
+ logical_shards = 1
282
+ elif any(
283
+ projection in name
284
+ for projection in (".gate_proj.", ".up_proj.", ".gate_up_proj.")
285
+ ):
286
+ dim = 0
287
+ block = int(block_size[0])
288
+ logical_shards = 2 if ".gate_up_proj." in name else 1
289
+ else:
290
+ return loaded_weight
291
+
292
+ if name.endswith(".weight_scale_inv"):
293
+ expected_shard_size = (intermediate_size + block - 1) // block
294
+ target_shard_size = (padded_intermediate_size + block - 1) // block
295
+ elif name.endswith((".weight", ".bias")):
296
+ expected_shard_size = intermediate_size
297
+ target_shard_size = padded_intermediate_size
298
+ else:
299
+ return loaded_weight
300
+
301
+ current_size = loaded_weight.shape[dim]
302
+ if current_size % logical_shards != 0:
303
+ raise ValueError(
304
+ f"Cannot split {name} dimension {current_size} into "
305
+ f"{logical_shards} logical shards."
306
+ )
307
+ current_shard_size = current_size // logical_shards
308
+ if current_shard_size == target_shard_size:
309
+ return loaded_weight
310
+ if current_shard_size != expected_shard_size:
311
+ raise ValueError(
312
+ f"Cannot pad {name}: expected each logical intermediate dimension "
313
+ f"to be {expected_shard_size}, but got {current_shard_size}."
314
+ )
315
+
316
+ padded_shards: list[torch.Tensor] = []
317
+ for shard in loaded_weight.split(current_shard_size, dim=dim):
318
+ pad_shape = list(shard.shape)
319
+ pad_shape[dim] = target_shard_size - current_shard_size
320
+ padded_shards.extend([shard, shard.new_zeros(pad_shape)])
321
+ return torch.cat(padded_shards, dim=dim)
322
+
323
+
324
+def _maybe_pad_block_fp8_shared_expert_checkpoint_tensor(
325
+ quant_config: QuantizationConfig | None,
326
+ config: PretrainedConfig,
327
+ name: str,
328
+ loaded_weight: torch.Tensor,
329
+) -> torch.Tensor:
330
+ if ".mlp.shared_experts." not in name:
331
+ return loaded_weight
332
+
333
+ shared_prefix = name.split(".shared_experts.", 1)[0] + ".shared_experts"
334
+ shared_intermediate = (
335
+ config.moe_shared_expert_intermediate_size * config.num_shared_experts
336
+ )
337
+ padded_shared_intermediate = _get_block_fp8_mlp_padded_intermediate_size(
338
+ quant_config,
339
+ shared_intermediate,
340
+ shared_prefix,
341
+ )
342
+ if padded_shared_intermediate == shared_intermediate:
343
+ return loaded_weight
344
+
345
+ assert quant_config is not None
346
+ return _pad_block_fp8_mlp_checkpoint_tensor(
347
+ quant_config,
348
+ name,
349
+ loaded_weight,
350
+ shared_intermediate,
351
+ padded_shared_intermediate,
352
+ )
353
+
354
+
355
class _IdentityProjection(nn.Module):
356
def forward(self, x: torch.Tensor) -> tuple[torch.Tensor, None]:
357
return x, None
@@ -446,13 +605,36 @@ class BailingMoeV3KimiDeltaAttention(PluggableLayer, MambaBase):
605
606
projection_size = self.head_dim * self.num_heads
607
self.projection_size_per_partition = projection_size // self.tp_size
449
- self.qkvb_proj = MergedColumnParallelLinear(
450
- self.hidden_size,
451
- [projection_size, projection_size, projection_size, self.num_heads],
452
- bias=False,
453
- quant_config=quant_config,
454
- prefix=f"{prefix}.qkvb_proj",
455
- )
608
+ self.separate_b_proj = _is_fp8_module_excluded(quant_config, f"{prefix}.b_proj")
609
+ self.qkv_proj: MergedColumnParallelLinear | None
610
+ self.b_proj: ColumnParallelLinear | None
611
+ self.qkvb_proj: MergedColumnParallelLinear | None
612
+ if self.separate_b_proj:
613
+ self.qkv_proj = MergedColumnParallelLinear(
614
+ self.hidden_size,
615
+ [projection_size, projection_size, projection_size],
616
+ bias=False,
617
+ quant_config=quant_config,
618
+ prefix=f"{prefix}.qkv_proj",
619
+ )
620
+ self.b_proj = ColumnParallelLinear(
621
+ self.hidden_size,
622
+ self.num_heads,
623
+ bias=False,
624
+ quant_config=quant_config,
625
+ prefix=f"{prefix}.b_proj",
626
+ )
627
+ self.qkvb_proj = None
628
+ else:
629
+ self.qkvb_proj = MergedColumnParallelLinear(
630
+ self.hidden_size,
631
+ [projection_size, projection_size, projection_size, self.num_heads],
632
+ bias=False,
633
+ quant_config=quant_config,
634
+ prefix=f"{prefix}.qkvb_proj",
635
+ )
636
+ self.qkv_proj = None
637
+ self.b_proj = None
638
self.f_proj = ColumnParallelLinear(
639
self.hidden_size,
640
projection_size,
@@ -532,16 +714,23 @@ class BailingMoeV3KimiDeltaAttention(PluggableLayer, MambaBase):
714
) -> None:
715
del positions
716
num_tokens = hidden_states.size(0)
535
- qkvb = self.qkvb_proj(hidden_states)[0]
536
- q, k, v, beta_logits = qkvb.split(
537
- [
538
- self.projection_size_per_partition,
539
- self.projection_size_per_partition,
540
- self.projection_size_per_partition,
541
- self.local_num_heads,
542
- ],
543
- dim=-1,
544
- )
717
+ if self.separate_b_proj:
718
+ assert self.qkv_proj is not None and self.b_proj is not None
719
+ qkv = self.qkv_proj(hidden_states)[0]
720
+ q, k, v = qkv.split(self.projection_size_per_partition, dim=-1)
721
+ beta_logits = self.b_proj(hidden_states)[0]
722
+ else:
723
+ assert self.qkvb_proj is not None
724
+ qkvb = self.qkvb_proj(hidden_states)[0]
725
+ q, k, v, beta_logits = qkvb.split(
726
+ [
727
+ self.projection_size_per_partition,
728
+ self.projection_size_per_partition,
729
+ self.projection_size_per_partition,
730
+ self.local_num_heads,
731
+ ],
732
+ dim=-1,
733
+ )
734
beta = beta_logits.float().sigmoid().unsqueeze(0)
735
g1 = self.f_proj(hidden_states)[0]
736
g1 = fused_kda_gate(
@@ -910,7 +1099,6 @@ class BailingMoeV3MoE(nn.Module):
1099
prefix: str = "",
1100
) -> None:
1101
super().__init__()
913
- self.tp_size = get_tensor_model_parallel_world_size()
1102
self.num_experts = config.num_experts
1103
self.top_k = config.num_experts_per_tok
1104
self.hidden_size = config.hidden_size
@@ -926,7 +1114,9 @@ class BailingMoeV3MoE(nn.Module):
1114
config.moe_shared_expert_intermediate_size * config.num_shared_experts
1115
)
1116
self.shared_experts = BailingMoeV3MLP(
929
- intermediate_size=shared_intermediate,
1117
+ intermediate_size=_get_block_fp8_mlp_padded_intermediate_size(
1118
+ quant_config, shared_intermediate, f"{prefix}.shared_experts"
1119
+ ),
1120
config=config,
1121
quant_config=quant_config,
1122
reduce_results=False,
@@ -1149,8 +1339,11 @@ class BailingMoeV3Model(nn.Module):
1339
1340
1341
class BailingMoeV3ForCausalLM(nn.Module, HasInnerState, IsHybrid, SupportsPP):
1342
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_substr={".attention.": ".self_attn."})
1343
+
1344
packed_modules_mapping = {
1345
"gate_up_proj": ["gate_proj", "up_proj"],
1346
+ "qkv_proj": ["q_proj", "k_proj", "v_proj"],
1347
"qkvb_proj": ["q_proj", "k_proj", "v_proj", "b_proj"],
1348
}
1349
@@ -1158,6 +1351,7 @@ class BailingMoeV3ForCausalLM(nn.Module, HasInnerState, IsHybrid, SupportsPP):
1351
super().__init__()
1352
config = vllm_config.model_config.hf_config
1353
quant_config = vllm_config.quant_config
1354
+ _configure_ling_fp8_quant_config(quant_config)
1355
self.config = config
1356
self.quant_config = quant_config
1357
self.model = BailingMoeV3Model(
@@ -1226,11 +1420,15 @@ class BailingMoeV3ForCausalLM(nn.Module, HasInnerState, IsHybrid, SupportsPP):
1420
return self.model.get_expert_mapping()
1421
1422
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1423
+ weights = self.hf_to_vllm_mapper.apply(weights)
1424
params_dict = dict(self.named_parameters(remove_duplicate=False))
1425
loaded_params: set[str] = set()
1426
stacked_mappings = [
1427
(".gate_up_proj", ".gate_proj", 0),
1428
(".gate_up_proj", ".up_proj", 1),
1429
+ (".qkv_proj", ".q_proj", 0),
1430
+ (".qkv_proj", ".k_proj", 1),
1431
+ (".qkv_proj", ".v_proj", 2),
1432
(".qkvb_proj", ".q_proj", 0),
1433
(".qkvb_proj", ".k_proj", 1),
1434
(".qkvb_proj", ".v_proj", 2),
@@ -1263,13 +1461,18 @@ class BailingMoeV3ForCausalLM(nn.Module, HasInnerState, IsHybrid, SupportsPP):
1461
layer_idx = int(name.split("model.layers.")[1].split(".")[0])
1462
if layer_idx >= self.config.num_hidden_layers:
1463
return None
1266
- name = name.replace("attention.", "self_attn.")
1464
return maybe_remap_kv_scale_name(name, params_dict)
1465
1466
for orig_name, weight in weights:
1467
name = normalize_name(orig_name)
1468
if name is None:
1469
continue
1470
+ weight = _maybe_pad_block_fp8_shared_expert_checkpoint_tensor(
1471
+ self.quant_config,
1472
+ self.config,
1473
+ name,
1474
+ weight,
1475
+ )
1476
loaded = False
1477
for param_suf, weight_suf, stacked_shard_id in stacked_mappings:
1478
if weight_suf in name:
vllm/model_executor/models/bailing_moe_v3_mtp.py
+23
-2
@@ -15,6 +15,7 @@ from vllm.model_executor.layers.fused_moe import (
15
fused_moe_make_expert_params_mapping,
16
)
17
from vllm.model_executor.layers.layernorm import RMSNorm
18
+from vllm.model_executor.layers.linear import ReplicatedLinear
19
from vllm.model_executor.layers.logits_processor import LogitsProcessor
20
from vllm.model_executor.layers.vocab_parallel_embedding import (
21
ParallelLMHead,
@@ -25,8 +26,11 @@ from vllm.model_executor.model_loader.weight_utils import (
26
maybe_remap_kv_scale_name,
27
)
28
from vllm.model_executor.models.bailing_moe_v3 import (
29
+ BailingMoeV3ForCausalLM,
30
BailingMoeV3MLAAttention,
31
BailingMoeV3MoE,
32
+ _configure_ling_fp8_quant_config,
33
+ _maybe_pad_block_fp8_shared_expert_checkpoint_tensor,
34
)
35
from vllm.model_executor.models.interfaces import SupportsPP
36
from vllm.model_executor.models.utils import (
@@ -79,7 +83,14 @@ class BailingMoeV3MultiTokenPredictorLayer(nn.Module):
83
self.layer_id = layer_id
84
self.enorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
85
self.hnorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
82
- self.eh_proj = nn.Linear(config.hidden_size * 2, config.hidden_size, bias=False)
86
+ self.eh_proj = ReplicatedLinear(
87
+ config.hidden_size * 2,
88
+ config.hidden_size,
89
+ bias=False,
90
+ quant_config=vllm_config.quant_config,
91
+ prefix=maybe_prefix(prefix, "eh_proj"),
92
+ return_bias=False,
93
+ )
94
self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
95
self.self_attn = BailingMoeV3MLAAttention(
96
config,
@@ -204,6 +215,8 @@ class BailingMoeV3MultiTokenPredictor(nn.Module):
215
216
@support_torch_compile
217
class BailingMoeV3MTPModel(nn.Module, SupportsPP):
218
+ hf_to_vllm_mapper = BailingMoeV3ForCausalLM.hf_to_vllm_mapper
219
+
220
packed_modules_mapping = {
221
"gate_up_proj": ["gate_proj", "up_proj"],
222
"fused_qkv_a_proj": ["q_a_proj", "kv_a_proj_with_mqa"],
@@ -217,6 +230,8 @@ class BailingMoeV3MTPModel(nn.Module, SupportsPP):
230
) -> None:
231
super().__init__()
232
self.config = _get_draft_hf_config(vllm_config)
233
+ self.quant_config = vllm_config.quant_config
234
+ _configure_ling_fp8_quant_config(self.quant_config)
235
self.model = BailingMoeV3MultiTokenPredictor(
236
vllm_config=vllm_config,
237
prefix=maybe_prefix(prefix, "model"),
@@ -265,6 +280,7 @@ class BailingMoeV3MTPModel(nn.Module, SupportsPP):
280
)
281
282
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
283
+ weights = self.hf_to_vllm_mapper.apply(weights)
284
stacked_params_mapping = [
285
(".fused_qkv_a_proj", ".q_a_proj", 0),
286
(".fused_qkv_a_proj", ".kv_a_proj_with_mqa", 1),
@@ -320,7 +336,6 @@ class BailingMoeV3MTPModel(nn.Module, SupportsPP):
336
return None
337
338
def normalize_name(name: str) -> str:
323
- name = name.replace(".attention.", ".self_attn.")
339
return name.replace(
340
"mlp.gate.e_score_correction_bias",
341
"mlp.gate.expert_bias",
@@ -349,6 +364,12 @@ class BailingMoeV3MTPModel(nn.Module, SupportsPP):
364
if spec_layer is None:
365
continue
366
name = normalize_name(name)
367
+ loaded_weight = _maybe_pad_block_fp8_shared_expert_checkpoint_tensor(
368
+ self.quant_config,
369
+ self.config,
370
+ name,
371
+ loaded_weight,
372
+ )
373
374
loaded = False
375
for param_name, weight_name, stacked_shard_id in stacked_params_mapping: