Reduce `AutoWeightsLoader` kwargs (#53106)
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Harry Mellor committed
Aug 20, 2026 at 16:40 UTC
1fe3a1571ac67581478a11743e55a306de1d136f
84 files changed
+578
-569
tests/models/inkling/test_moe_weight_layout.py
+1
-1
@@ -104,7 +104,7 @@ def test_inkling_mapper_maps_modelopt_exclusions() -> None:
104
)
105
106
quant_config.apply_vllm_mapper(
107
- _TmlForCausalLMBase.hf_to_vllm_mapper.get_unstacked_mapper()
107
+ _TmlForCausalLMBase.hf_to_vllm_mapper.get_rename_mapper()
108
)
109
110
assert quant_config.is_layer_excluded("model.layers.2.mlp.experts")
tests/models/test_dspark_mla.py
+3
-5
@@ -55,11 +55,9 @@ def test_dspark_mla_checkpoint_weight_mapping(checkpoint_name, runtime_name, sha
55
def test_dspark_mla_shares_frozen_target_weights_and_skips_training_head():
56
assert not K3DSparkForCausalLM.has_own_embed_tokens
57
assert not K3DSparkForCausalLM.has_own_lm_head
58
- assert set(K3DSparkForCausalLM.checkpoint_skip_substrs) == {
59
- "confidence_head",
60
- "embed_tokens",
61
- "lm_head",
62
- }
58
+ mapper = K3DSparkForCausalLM.hf_to_vllm_mapper
59
+ for name in ("confidence_head.weight", "embed_tokens.weight", "lm_head.weight"):
60
+ assert mapper._map_name(name) is None
61
62
63
@pytest.mark.cpu_test
tests/models/test_utils.py
+28
-76
@@ -2,6 +2,7 @@
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
import pytest
5
+import regex as re
6
import torch
7
8
from vllm.model_executor.layers.vocab_parallel_embedding import (
@@ -10,6 +11,7 @@ from vllm.model_executor.layers.vocab_parallel_embedding import (
11
)
12
from vllm.model_executor.models.utils import (
13
AutoWeightsLoader,
14
+ WeightsMapper,
15
_merge_multimodal_embeddings,
16
)
17
from vllm.platforms import current_platform
@@ -93,82 +95,6 @@ def test_module_with_child_containing_batchnorm_can_autoload():
95
assert new_mod.nested_mod.bn.num_batches_tracked.item() == 1
96
97
96
-@pytest.mark.cpu_test
97
-def test_module_skip_prefix():
98
- """Ensure the auto weight loader can skip prefix."""
99
- mod = ModuleWithNestedBatchNorm()
100
- # Run some data through the module with batchnorm
101
- mod(torch.Tensor([[1, 2], [3, 4]]))
102
-
103
- # Try to load the weights to a new instance
104
- def weight_generator():
105
- # weights needed to be filtered out
106
- redundant_weights = {
107
- "prefix.bn.weight": torch.Tensor([1, 2]),
108
- "prefix.bn.bias": torch.Tensor([3, 4]),
109
- }
110
- yield from (mod.state_dict() | redundant_weights).items()
111
-
112
- new_mod = ModuleWithNestedBatchNorm()
113
-
114
- assert not torch.all(
115
- new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean
116
- )
117
- assert not torch.all(
118
- new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var
119
- )
120
- assert new_mod.nested_mod.bn.num_batches_tracked.item() == 0
121
-
122
- loader = AutoWeightsLoader(new_mod, skip_prefixes=["prefix."])
123
- loader.load_weights(weight_generator())
124
-
125
- # Ensure the stats are updated
126
- assert torch.all(
127
- new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean
128
- )
129
- assert torch.all(new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
130
- assert new_mod.nested_mod.bn.num_batches_tracked.item() == 1
131
-
132
-
133
-@pytest.mark.cpu_test
134
-def test_module_skip_substr():
135
- """Ensure the auto weight loader can skip prefix."""
136
- mod = ModuleWithNestedBatchNorm()
137
- # Run some data through the module with batchnorm
138
- mod(torch.Tensor([[1, 2], [3, 4]]))
139
-
140
- # Try to load the weights to a new instance
141
- def weight_generator():
142
- # weights needed to be filtered out
143
- redundant_weights = {
144
- "nested_mod.0.substr.weight": torch.Tensor([1, 2]),
145
- "nested_mod.0.substr.bias": torch.Tensor([3, 4]),
146
- "nested_mod.substr.weight": torch.Tensor([1, 2]),
147
- "nested_mod.substr.bias": torch.Tensor([3, 4]),
148
- }
149
- yield from (mod.state_dict() | redundant_weights).items()
150
-
151
- new_mod = ModuleWithNestedBatchNorm()
152
-
153
- assert not torch.all(
154
- new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean
155
- )
156
- assert not torch.all(
157
- new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var
158
- )
159
- assert new_mod.nested_mod.bn.num_batches_tracked.item() == 0
160
-
161
- loader = AutoWeightsLoader(new_mod, skip_substrs=["substr."])
162
- loader.load_weights(weight_generator())
163
-
164
- # Ensure the stats are updated
165
- assert torch.all(
166
- new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean
167
- )
168
- assert torch.all(new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
169
- assert new_mod.nested_mod.bn.num_batches_tracked.item() == 1
170
-
171
-
98
VOCAB_SIZE = 16
99
HIDDEN_SIZE = 2
100
@@ -265,3 +191,29 @@ def test_merge_multimodal_embeddings_no_sync():
191
_merge_multimodal_embeddings(
192
inputs_embeds, multimodal_embeddings, is_multimodal
193
)
194
+
195
+
196
+@pytest.mark.cpu_test
197
+def test_get_rename_mapper_keeps_only_renames():
198
+ """`None` means "do not load", which is meaningless to the consumers of
199
+ this mapper (LoRA name parsing, quantization config layer lists), and
200
+ applying it would silently shrink their lists."""
201
+ mapper = WeightsMapper(
202
+ orig_to_new_regex={re.compile(r"^drop_regex\."): None},
203
+ orig_to_new_substr={"drop_substr": None, "keep_substr": "kept"},
204
+ orig_to_new_stacked={".q_proj": (".qkv_proj", "q")},
205
+ orig_to_new_prefix={"drop_prefix.": None, "keep_prefix.": "kept."},
206
+ orig_to_new_suffix={".drop_suffix": None},
207
+ )
208
+ renames = mapper.get_rename_mapper()
209
+
210
+ assert renames.orig_to_new_regex == {}
211
+ assert renames.orig_to_new_substr == {"keep_substr": "kept"}
212
+ assert renames.orig_to_new_stacked == {}
213
+ assert renames.orig_to_new_prefix == {"keep_prefix.": "kept."}
214
+ assert renames.orig_to_new_suffix == {}
215
+
216
+ # Names the full mapper drops now survive unchanged.
217
+ for name in ("drop_regex.w", "drop_substr.w", "drop_prefix.w", "w.drop_suffix"):
218
+ assert mapper._map_name(name) is None
219
+ assert renames._map_name(name) == name
tests/quantization/test_modelopt.py
+2
-2
@@ -214,9 +214,9 @@ def test_modelopt_mixed_precision_composes_gemma4_mappers():
214
)
215
216
config.apply_vllm_mapper(
217
- Gemma4ForConditionalGeneration.hf_to_vllm_mapper.get_unstacked_mapper()
217
+ Gemma4ForConditionalGeneration.hf_to_vllm_mapper.get_rename_mapper()
218
)
219
- config.apply_vllm_mapper(Gemma4ForCausalLM.hf_to_vllm_mapper.get_unstacked_mapper())
219
+ config.apply_vllm_mapper(Gemma4ForCausalLM.hf_to_vllm_mapper.get_rename_mapper())
220
221
expected_prefix = "language_model.model.layers.0.moe.experts"
222
assert set(config.quantized_layers) == {
vllm/lora/worker_manager.py
+4
-5
@@ -128,14 +128,13 @@ class WorkerLoRAManager:
128
# loading weights, throwing an exception if validation fails.
129
peft_helper.validate_legal(self.lora_config)
130
131
- # For some models like Qwen2VL, we need to use hf_to_vllm_mapper
132
- # to ensure correct loading of lora weights. Drop the QKV/MLP fusion
133
- # substr maps so constituent names (e.g. `q_proj`) survive for the
134
- # LoRA manager to pack, while keeping genuine renames/prefixes.
131
+ # For some models like Qwen2VL, we need to use hf_to_vllm_mapper to ensure
132
+ # correct loading of lora weights. We only need to know about renames for
133
+ # this, so we use get_rename_mapper() to ignore stacking and deletions.
134
model = self._adapter_manager.model
135
hf_to_vllm_mapper = getattr(model, "hf_to_vllm_mapper", None)
136
if hf_to_vllm_mapper is not None:
138
- hf_to_vllm_mapper = hf_to_vllm_mapper.get_unstacked_mapper()
137
+ hf_to_vllm_mapper = hf_to_vllm_mapper.get_rename_mapper()
138
139
# Get model-defined prefixes to skip during LoRA loading.
140
lora_skip_prefixes = getattr(model, "lora_skip_prefixes", None)
vllm/model_executor/model_loader/utils.py
+1
-1
@@ -281,6 +281,6 @@ def configure_quant_config(
281
282
# pass mappings by reference to quant_config
283
if hf_to_vllm_mapper is not None:
284
- quant_config.apply_vllm_mapper(hf_to_vllm_mapper.get_unstacked_mapper())
284
+ quant_config.apply_vllm_mapper(hf_to_vllm_mapper.get_rename_mapper())
285
if packed_mapping is not None:
286
quant_config.packed_modules_mapping = packed_mapping
vllm/model_executor/models/adapters.py
+8
-5
@@ -236,7 +236,8 @@ def _create_pooling_model_cls(orig_cls: type[_T]) -> type[_T]:
236
237
def default_load_weights(weights):
238
loader = AutoWeightsLoader(self)
239
- return loader.load_weights(weights)
239
+ mapper = getattr(self, "hf_to_vllm_mapper", None)
240
+ return loader.load_weights(weights, mapper=mapper)
241
242
load_weights = getattr(super(), "load_weights", default_load_weights)
243
return load_weights(mapped_weights)
@@ -584,10 +585,11 @@ def load_weights_using_from_2_way_softmax(
585
)
586
loaded_weights.add(score_weight_name)
587
587
- lm_head_name = "lm_head.weight"
588
+ lm_head_name: str | None = "lm_head.weight"
589
if hf_to_vllm_mapper := getattr(model, "hf_to_vllm_mapper", None):
590
lm_head_name = hf_to_vllm_mapper._map_name(lm_head_name)
590
- loaded_weights.discard(lm_head_name)
591
+ if lm_head_name is not None:
592
+ loaded_weights.discard(lm_head_name)
593
return loaded_weights
594
595
@@ -649,10 +651,11 @@ def load_weights_no_post_processing(model, weights: Iterable[tuple[str, torch.Te
651
)
652
loaded_weights.add(score_weight_name)
653
652
- lm_head_name = "lm_head.weight"
654
+ lm_head_name: str | None = "lm_head.weight"
655
if hf_to_vllm_mapper := getattr(model, "hf_to_vllm_mapper", None):
656
lm_head_name = hf_to_vllm_mapper._map_name(lm_head_name)
655
- loaded_weights.discard(lm_head_name)
657
+ if lm_head_name is not None:
658
+ loaded_weights.discard(lm_head_name)
659
return loaded_weights
660
661
vllm/model_executor/models/aimv2.py
+6
-9
@@ -219,6 +219,11 @@ class AIMv2Model(torch.nn.Module):
219
require_post_norm=require_post_norm,
220
prefix=f"{prefix}.trunk",
221
)
222
+ # post_trunk_norm is optional (absent for clip-skip backbones).
223
+ if self.trunk.post_trunk_norm is None:
224
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
225
+ orig_to_new_prefix={"trunk.post_trunk_norm.": None}
226
+ )
227
228
def forward(self, pixel_values: torch.Tensor) -> torch.Tensor:
229
x = self.preprocessor(pixel_values)
@@ -227,13 +232,5 @@ class AIMv2Model(torch.nn.Module):
232
return x
233
234
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
230
- loader = AutoWeightsLoader(
231
- self,
232
- # post_trunk_norm is optional (absent for clip-skip backbones).
233
- skip_prefixes=(
234
- ["trunk.post_trunk_norm."]
235
- if self.trunk.post_trunk_norm is None
236
- else None
237
- ),
238
- )
235
+ loader = AutoWeightsLoader(self)
236
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/arcee.py
+5
-2
@@ -285,7 +285,10 @@ class ArceeForCausalLM(
285
".q_proj": (".qkv_proj", "q"),
286
".k_proj": (".qkv_proj", "k"),
287
".v_proj": (".qkv_proj", "v"),
288
- }
288
+ },
289
+ orig_to_new_substr={
290
+ "gate_proj": None,
291
+ },
292
)
293
# Map fused module names to their submodule components
294
# (for quantization and LoRA)
@@ -356,7 +359,7 @@ class ArceeForCausalLM(
359
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
360
"""Load weights into the model (delegates to inner model and handles
361
tied embeddings)."""
359
- loader = AutoWeightsLoader(self, skip_substrs=["gate_proj"])
362
+ loader = AutoWeightsLoader(self)
363
# AutoWeightLoader handles weight name remapping, including fusing
364
# separate q_proj, k_proj, v_proj into qkv_proj
365
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/aria.py
+7
-15
@@ -13,18 +13,13 @@ from vllm.config import VllmConfig
13
from vllm.config.multimodal import BaseDummyOptions, ImageDummyOptions
14
from vllm.inputs import MultiModalDataDict
15
from vllm.model_executor.layers.activation import get_act_fn
16
-from vllm.model_executor.layers.fused_moe import (
17
- FusedMoEFactory,
18
-)
16
+from vllm.model_executor.layers.fused_moe import FusedMoEFactory
17
from vllm.model_executor.layers.linear import ColumnParallelLinear, RowParallelLinear
18
from vllm.model_executor.layers.logits_processor import LogitsProcessor
19
from vllm.model_executor.layers.quantization import QuantizationConfig
20
from vllm.model_executor.layers.vocab_parallel_embedding import ParallelLMHead
21
from vllm.multimodal import MULTIMODAL_REGISTRY
24
-from vllm.multimodal.inputs import (
25
- MultiModalFieldConfig,
26
- MultiModalKwargsItems,
27
-)
22
+from vllm.multimodal.inputs import MultiModalFieldConfig, MultiModalKwargsItems
23
from vllm.multimodal.parse import MultiModalDataItems
24
from vllm.multimodal.processing import (
25
BaseDummyInputsBuilder,
@@ -42,11 +37,7 @@ from .idefics2_vision_model import (
37
)
38
from .interfaces import MultiModalEmbeddings, SupportsMultiModal, SupportsQuant
39
from .llama import LlamaDecoderLayer, LlamaMLP, LlamaModel
45
-from .utils import (
46
- AutoWeightsLoader,
47
- WeightsMapper,
48
- maybe_prefix,
49
-)
40
+from .utils import AutoWeightsLoader, WeightsMapper, maybe_prefix
41
42
43
class AriaImagePixelInputs(TensorSchema):
@@ -88,16 +79,17 @@ class AriaVisionTransformer(Idefics3VisionTransformer, SupportsQuant):
79
self.post_layernorm = nn.Identity()
80
81
hf_to_vllm_mapper = WeightsMapper(
82
+ # NOTE: post_layernorm is not used in Aria.
83
+ orig_to_new_substr={"post_layernorm": None},
84
orig_to_new_stacked={
85
".q_proj": (".qkv_proj", "q"),
86
".k_proj": (".qkv_proj", "k"),
87
".v_proj": (".qkv_proj", "v"),
95
- }
88
+ },
89
)
90
91
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
99
- # NOTE: post_layernorm is not used in Aria.
100
- loader = AutoWeightsLoader(self, skip_substrs=["post_layernorm"])
92
+ loader = AutoWeightsLoader(self)
93
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
94
95
vllm/model_executor/models/bagel.py
+3
-9
@@ -338,14 +338,9 @@ class BagelForConditionalGeneration(
338
The image generation part is not supported in vLLM.
339
"""
340
341
- # Weight mapping from HF to vLLM
341
+ # pos_embed is handled by the PositionEmbedding module
342
hf_to_vllm_mapper = WeightsMapper(
343
- orig_to_new_prefix={
344
- "language_model.": "language_model.",
345
- "vit_model.": "vit_model.",
346
- "connector.": "connector.",
347
- "vit_pos_embed.": "vit_pos_embed.",
348
- }
343
+ orig_to_new_prefix={"vit_pos_embed.pos_embed": None}
344
)
345
346
@classmethod
@@ -580,6 +575,5 @@ class BagelForConditionalGeneration(
575
576
filtered_weights.append((name, tensor))
577
583
- # Skip vit_pos_embed.pos_embed as it's handled by PositionEmbedding module
584
- loader = AutoWeightsLoader(self, skip_prefixes=["vit_pos_embed.pos_embed"])
578
+ loader = AutoWeightsLoader(self)
579
return loader.load_weights(filtered_weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/bert.py
+10
-3
@@ -2,6 +2,7 @@
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
from collections.abc import Iterable, Set
5
+from dataclasses import replace
6
7
import torch
8
from torch import nn
@@ -382,6 +383,7 @@ class BertModel(nn.Module, SupportsQuant):
383
".self.key": (".self.qkv_proj", "k"),
384
".self.value": (".self.qkv_proj", "v"),
385
},
386
+ orig_to_new_prefix={"pooler.": None},
387
)
388
389
def __init__(
@@ -416,13 +418,16 @@ class BertModel(nn.Module, SupportsQuant):
418
return self.encoder(hidden_states)
419
420
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
419
- loader = AutoWeightsLoader(self, skip_prefixes=["pooler."])
421
+ loader = AutoWeightsLoader(self)
422
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
423
424
425
class BertPoolingModel(BertModel):
426
is_pooling_model = True
427
428
+ # Unlike `BertModel`, this model has a pooler to load weights into.
429
+ hf_to_vllm_mapper = replace(BertModel.hf_to_vllm_mapper, orig_to_new_prefix={})
430
+
431
def __init__(
432
self,
433
*,
@@ -488,11 +493,13 @@ class BertEmbeddingModel(nn.Module, SupportsQuant):
493
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
494
weights_list = list(weights)
495
496
+ orig_to_new_prefix: dict[str, str | None] = {"lm_head.": None}
497
has_model_prefix = any(name.startswith("model.") for name, _ in weights_list)
498
if not has_model_prefix:
493
- mapper = WeightsMapper(orig_to_new_prefix={"": "model."})
499
+ orig_to_new_prefix[""] = "model."
500
+ mapper = WeightsMapper(orig_to_new_prefix=orig_to_new_prefix)
501
495
- loader = AutoWeightsLoader(self, skip_prefixes=["lm_head."])
502
+ loader = AutoWeightsLoader(self)
503
return loader.load_weights(weights_list, mapper=mapper)
504
505
def _build_model(self, vllm_config: VllmConfig, prefix: str = "") -> BertModel:
vllm/model_executor/models/blip.py
+4
-4
@@ -313,6 +313,9 @@ class BlipVisionModel(nn.Module, SupportsQuant):
313
)
314
else:
315
self.post_layernorm = None
316
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
317
+ orig_to_new_prefix={"post_layernorm.": None}
318
+ )
319
320
def forward(self, pixel_values: torch.Tensor) -> torch.Tensor:
321
hidden_states = self.embeddings(pixel_values)
@@ -324,10 +327,7 @@ class BlipVisionModel(nn.Module, SupportsQuant):
327
return self.post_layernorm(hidden_states)
328
329
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
327
- skip_prefixes: list[str] = []
328
- if self.post_layernorm is None:
329
- skip_prefixes.append("post_layernorm.")
330
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
330
+ loader = AutoWeightsLoader(self)
331
332
# omit layers when num_hidden_layers_override is set
333
def _filter(ws):
vllm/model_executor/models/clip.py
+7
-6
@@ -669,6 +669,9 @@ class CLIPVisionTransformer(nn.Module):
669
self.post_layernorm = nn.LayerNorm(embed_dim, eps=config.layer_norm_eps)
670
else:
671
self.post_layernorm = None
672
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
673
+ orig_to_new_prefix={"post_layernorm.": None}
674
+ )
675
676
@property
677
def dtype(self):
@@ -707,10 +710,7 @@ class CLIPVisionTransformer(nn.Module):
710
return encoder_outputs
711
712
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
710
- skip_prefixes: list[str] = []
711
- if self.post_layernorm is None:
712
- skip_prefixes.append("post_layernorm.")
713
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
713
+ loader = AutoWeightsLoader(self)
714
715
# Drop layers beyond num_hidden_layers_override.
716
def _filter(ws):
@@ -775,6 +775,8 @@ class CLIPVisionModel(nn.Module):
775
class CLIPEmbeddingModel(nn.Module, SupportsMultiModal, SupportsQuant):
776
is_pooling_model = True
777
778
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_substr={".position_ids": None})
779
+
780
packed_modules_mapping = {"qkv_proj": ["q_proj", "k_proj", "v_proj"]}
781
782
@classmethod
@@ -981,8 +983,7 @@ class CLIPEmbeddingModel(nn.Module, SupportsMultiModal, SupportsQuant):
983
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
984
loader = AutoWeightsLoader(
985
self,
984
- skip_substrs=[".position_ids"],
986
ignore_unexpected_prefixes=["logit_scale."],
987
)
988
988
- return loader.load_weights(weights)
989
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/cohere2_moe.py
+3
-2
@@ -474,7 +474,8 @@ class Cohere2MoeForCausalLM(nn.Module, SupportsPP, SupportsQuant):
474
".mlp.up_proj": (".mlp.gate_up_proj", 1),
475
".shared_experts.gate_proj": (".shared_experts.gate_up_proj", 0),
476
".shared_experts.up_proj": (".shared_experts.gate_up_proj", 1),
477
- }
477
+ },
478
+ orig_to_new_prefix={"lm_head.": None},
479
)
480
packed_modules_mapping = {
481
"qkv_proj": [
@@ -529,5 +530,5 @@ class Cohere2MoeForCausalLM(nn.Module, SupportsPP, SupportsQuant):
530
return self.logits_processor(self.model.embed_tokens, hidden_states)
531
532
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
532
- loader = AutoWeightsLoader(self, skip_prefixes=["lm_head."])
533
+ loader = AutoWeightsLoader(self)
534
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/cohere_asr.py
+10
-9
@@ -2014,7 +2014,15 @@ class CohereAsrForConditionalGeneration(
2014
}
2015
2016
hf_to_vllm_mapper = WeightsMapper(
2017
- orig_to_new_substr={".fc1.": ".mlp.fc1.", ".fc2.": ".mlp.fc2."}
2017
+ orig_to_new_substr={
2018
+ ".fc1.": ".mlp.fc1.",
2019
+ ".fc2.": ".mlp.fc2.",
2020
+ "model.conv.batch_norm.num_batches_tracked": None,
2021
+ },
2022
+ orig_to_new_prefix={
2023
+ "model.preprocessor.featurizer.fb": None,
2024
+ "model.preprocessor.featurizer.window": None,
2025
+ },
2026
)
2027
2028
supports_transcription_only = True
@@ -2273,14 +2281,7 @@ class CohereAsrForConditionalGeneration(
2281
2282
return name, loaded_weight
2283
2276
- loader = AutoWeightsLoader(
2277
- self,
2278
- skip_prefixes=[
2279
- "model.preprocessor.featurizer.fb",
2280
- "model.preprocessor.featurizer.window",
2281
- ],
2282
- skip_substrs=["model.conv.batch_norm.num_batches_tracked"],
2283
- )
2284
+ loader = AutoWeightsLoader(self)
2285
2286
return loader.load_weights(
2287
map(transform, weights), mapper=self.hf_to_vllm_mapper
vllm/model_executor/models/cohere_eagle.py
+6
-8
@@ -22,6 +22,7 @@ from vllm.model_executor.models.commandr import (
22
23
from .utils import (
24
AutoWeightsLoader,
25
+ WeightsMapper,
26
get_draft_quant_config,
27
maybe_prefix,
28
process_eagle_weight,
@@ -145,6 +146,10 @@ class EagleCohereForCausalLM(CohereForCausalLM):
146
# use tied embeddings so these weights are absent from the draft file.
147
self.has_own_embed_tokens = False
148
self.has_own_lm_head = False
149
+ if self.config.tie_word_embeddings:
150
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
151
+ orig_to_new_prefix={"model.embed_tokens.": None}
152
+ )
153
target_layer_num = vllm_config.model_config.get_num_layers(
154
vllm_config.parallel_config
155
)
@@ -181,14 +186,7 @@ class EagleCohereForCausalLM(CohereForCausalLM):
186
process_eagle_weight(self, name)
187
return name, weight
188
184
- loader = AutoWeightsLoader(
185
- self,
186
- skip_prefixes=(
187
- ["lm_head.", "model.embed_tokens."]
188
- if self.config.tie_word_embeddings
189
- else None
190
- ),
191
- )
189
+ loader = AutoWeightsLoader(self)
190
191
loaded_weight_names = loader.load_weights(
192
map(_track_and_forward, weights), mapper=self.hf_to_vllm_mapper
vllm/model_executor/models/colbert.py
+5
-4
@@ -358,11 +358,12 @@ class ColBERTJinaRobertaModel(ColBERTMixin, nn.Module):
358
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
359
other_weights, colbert_loaded = self._load_colbert_weights(weights)
360
361
- mapper = WeightsMapper(orig_to_new_prefix={"roberta.": "model."})
362
-
363
- # Skip HF pooler weights (model.pooler.*) as they not used in ColBERT
364
- loader = AutoWeightsLoader(self, skip_prefixes=["model.pooler."])
361
+ # HF pooler weights are not used in ColBERT
362
+ mapper = WeightsMapper(
363
+ orig_to_new_prefix={"roberta.": "model.", "model.pooler.": None}
364
+ )
365
366
+ loader = AutoWeightsLoader(self)
367
loaded = loader.load_weights(other_weights, mapper=mapper)
368
return loaded | colbert_loaded
369
vllm/model_executor/models/colqwen3_5.py
+2
-4
@@ -140,6 +140,7 @@ class ColQwen3_5Model(
140
hf_to_vllm_mapper = WeightsMapper(
141
orig_to_new_prefix={
142
"language_model.": "language_model.model.",
143
+ "mtp.": None,
144
}
145
)
146
@@ -238,10 +239,7 @@ class ColQwen3_5Model(
239
else:
240
model_weights.append((name, weight))
241
241
- loader = AutoWeightsLoader(
242
- self,
243
- skip_prefixes=["mtp."],
244
- )
242
+ loader = AutoWeightsLoader(self)
243
loaded = loader.load_weights(model_weights, mapper=self.hf_to_vllm_mapper)
244
245
for name, weight in proj_weights:
vllm/model_executor/models/commandr.py
+2
-3
@@ -415,6 +415,7 @@ class CohereForCausalLM(nn.Module, SupportsLoRA, SupportsPP, SupportsQuant):
415
# (e.g. "*.weight_quantizer._double_scale"); drop them before loading.
416
# See #41925.
417
orig_to_new_substr={"_quantizer.": None},
418
+ orig_to_new_prefix={"lm_head": None},
419
)
420
packed_modules_mapping = {
421
"qkv_proj": ["q_proj", "k_proj", "v_proj"],
@@ -472,7 +473,5 @@ class CohereForCausalLM(nn.Module, SupportsLoRA, SupportsPP, SupportsQuant):
473
return logits
474
475
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
475
- loader = AutoWeightsLoader(
476
- self, skip_prefixes=["lm_head", "rotary_emb.inv_freq"]
477
- )
476
+ loader = AutoWeightsLoader(self)
477
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/deepseek_eagle.py
+1
-4
@@ -253,8 +253,5 @@ class EagleDeepseekV3ForCausalLM(DeepseekV3ForCausalLM):
253
process_eagle_weight(self, name)
254
return name, loaded_weight
255
256
- loader = AutoWeightsLoader(
257
- self,
258
- skip_prefixes=None,
259
- )
256
+ loader = AutoWeightsLoader(self)
257
loader.load_weights(map(transform, weights))
vllm/model_executor/models/deepseek_eagle3.py
+7
-8
@@ -384,18 +384,17 @@ class Eagle3DeepseekV2ForCausalLM(LocalArgmaxMixin, DeepseekV2ForCausalLM):
384
model_weights[name] = loaded_weight
385
process_eagle_weight(self, name)
386
387
- skip_substrs = []
387
+ orig_to_new_substr: dict[str, str | None] = {}
388
if not includes_draft_id_mapping:
389
- skip_substrs.append("draft_id_to_target_id")
389
+ orig_to_new_substr["draft_id_to_target_id"] = None
390
if not includes_embed_tokens:
391
- skip_substrs.append("embed_tokens")
391
+ orig_to_new_substr["embed_tokens"] = None
392
393
- loader = AutoWeightsLoader(
394
- self,
395
- skip_prefixes=None,
396
- skip_substrs=skip_substrs,
393
+ loader = AutoWeightsLoader(self)
394
+ loader.load_weights(
395
+ model_weights.items(),
396
+ mapper=WeightsMapper(orig_to_new_substr=orig_to_new_substr),
397
)
398
- loader.load_weights(model_weights.items())
398
399
400
# Aliases for compatibility
vllm/model_executor/models/ernie45_moe.py
+3
-6
@@ -403,7 +403,8 @@ class Ernie4_5_MoeModel(nn.Module):
403
".mlp.up_proj": (".mlp.gate_up_proj", 1),
404
".shared_experts.gate_proj": (".shared_experts.gate_up_proj", 0),
405
".shared_experts.up_proj": (".shared_experts.gate_up_proj", 1),
406
- }
406
+ },
407
+ orig_to_new_substr={"mtp": None},
408
)
409
410
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
@@ -497,11 +498,7 @@ class Ernie4_5_MoeModel(nn.Module):
498
yield name, loaded_weight
499
500
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
500
- loader = AutoWeightsLoader(
501
- self,
502
- skip_substrs=["mtp"],
503
- ignore_unexpected_suffixes=[".bias", "_bias"],
504
- )
501
+ loader = AutoWeightsLoader(self)
502
return loader.load_weights(
503
self._preprocess(weights), mapper=self.hf_to_vllm_mapper
504
)
vllm/model_executor/models/exaone4_5.py
+11
-5
@@ -52,7 +52,12 @@ from vllm.multimodal import MULTIMODAL_REGISTRY
52
53
from .qwen2_vl import Qwen2VLDummyInputsBuilder as Exaone4_5_DummyInputsBuilder
54
from .qwen2_vl import Qwen2VLMultiModalProcessor as Exaone4_5_MultiModalProcessor
55
-from .utils import AutoWeightsLoader, init_vllm_registered_model, maybe_prefix
55
+from .utils import (
56
+ AutoWeightsLoader,
57
+ WeightsMapper,
58
+ init_vllm_registered_model,
59
+ maybe_prefix,
60
+)
61
62
logger = init_logger(__name__)
63
@@ -317,6 +322,10 @@ class Exaone4_5_ProcessingInfo(Qwen2VLProcessingInfo):
322
dummy_inputs=Exaone4_5_DummyInputsBuilder,
323
)
324
class Exaone4_5_ForConditionalGeneration(Qwen2_5_VLForConditionalGeneration):
325
+ hf_to_vllm_mapper = Qwen2_5_VLForConditionalGeneration.hf_to_vllm_mapper | (
326
+ WeightsMapper(orig_to_new_prefix={"mtp.": None})
327
+ )
328
+
329
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
330
nn.Module.__init__(self)
331
@@ -353,10 +362,7 @@ class Exaone4_5_ForConditionalGeneration(Qwen2_5_VLForConditionalGeneration):
362
)
363
364
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
356
- loader = AutoWeightsLoader(
357
- self,
358
- skip_prefixes=(["mtp."]),
359
- )
365
+ loader = AutoWeightsLoader(self)
366
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
367
368
@classmethod
vllm/model_executor/models/exaone_moe.py
+2
-2
@@ -471,7 +471,8 @@ class ExaoneMoeForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
471
".mlp.up_proj": (".mlp.gate_up_proj", 1),
472
".shared_experts.gate_proj": (".shared_experts.gate_up_proj", 0),
473
".shared_experts.up_proj": (".shared_experts.gate_up_proj", 1),
474
- }
474
+ },
475
+ orig_to_new_prefix={"mtp.": None},
476
)
477
packed_modules_mapping = {
478
"qkv_proj": [
@@ -560,7 +561,6 @@ class ExaoneMoeForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
561
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
562
loader = AutoWeightsLoader(
563
self,
563
- skip_prefixes=["mtp."],
564
# Skip loading extra parameters for GPTQ/modelopt models.
565
ignore_unexpected_suffixes=[
566
".bias",
vllm/model_executor/models/fireredasr2.py
+5
-4
@@ -332,7 +332,10 @@ class FireRedASR2ForConditionalGeneration(
332
"net.0": "pre_layer_norm",
333
"net.1": "linear_expand",
334
"net.4": "linear_project",
335
- }
335
+ },
336
+ orig_to_new_prefix={
337
+ "model.encoder.audio_encoder.positional_encoding.pe": None,
338
+ },
339
)
340
341
supports_transcription_only = True
@@ -477,8 +480,6 @@ class FireRedASR2ForConditionalGeneration(
480
return logits
481
482
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
480
- loader = AutoWeightsLoader(
481
- self, skip_prefixes=["model.encoder.audio_encoder.positional_encoding.pe"]
482
- )
483
+ loader = AutoWeightsLoader(self)
484
485
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/fireredlid.py
+10
-12
@@ -589,7 +589,15 @@ class FireRedLIDForConditionalGeneration(
589
"net.0": "pre_layer_norm",
590
"net.1": "linear_expand",
591
"net.4": "linear_project",
592
- }
592
+ },
593
+ orig_to_new_prefix={
594
+ # Position encoding buffers are rebuilt at init, and the output
595
+ # projection is tied to the embedding.
596
+ "model.encoder.positional_encoding.pe": None,
597
+ "model.decoder.positional_encoding.pe": None,
598
+ "model.decoder.tgt_word_prj.weight": None,
599
+ "proj_out.": None,
600
+ },
601
)
602
603
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
@@ -778,15 +786,5 @@ class FireRedLIDForConditionalGeneration(
786
return text.strip()
787
788
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
781
- loader = AutoWeightsLoader(
782
- self,
783
- skip_prefixes=[
784
- # Position encoding buffers are rebuilt at init
785
- "model.encoder.positional_encoding.pe",
786
- "model.decoder.positional_encoding.pe",
787
- # Tied output projection (shared with embedding)
788
- "model.decoder.tgt_word_prj.weight",
789
- "proj_out.",
790
- ],
791
- )
789
+ loader = AutoWeightsLoader(self)
790
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/funaudiochat.py
+4
-2
@@ -760,6 +760,8 @@ class FunAudioChatMultiModalProcessor(
760
dummy_inputs=FunAudioChatDummyInputsBuilder,
761
)
762
class FunAudioChatForConditionalGeneration(nn.Module, SupportsMultiModal, SupportsPP):
763
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"audio_invert_tower.": None})
764
+
765
@classmethod
766
def get_placeholder_str(cls, modality: str, i: int) -> str | None:
767
if modality.startswith("audio"):
@@ -969,5 +971,5 @@ class FunAudioChatForConditionalGeneration(nn.Module, SupportsMultiModal, Suppor
971
return self.language_model.compute_logits(hidden_states)
972
973
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
972
- loader = AutoWeightsLoader(self, skip_prefixes=["audio_invert_tower."])
973
- return loader.load_weights(weights)
974
+ loader = AutoWeightsLoader(self)
975
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/gemma3n.py
+10
-7
@@ -1056,6 +1056,14 @@ class Gemma3nTextModel(nn.Module, SupportsQuant):
1056
1057
1058
class Gemma3nForCausalLM(nn.Module):
1059
+ hf_to_vllm_mapper = WeightsMapper(
1060
+ orig_to_new_substr={
1061
+ "embed_audio.": None,
1062
+ "embed_vision.": None,
1063
+ "audio_tower.": None,
1064
+ "vision_tower.": None,
1065
+ }
1066
+ )
1067
packed_modules_mapping = {
1068
"qkv_proj": [
1069
"q_proj",
@@ -1112,10 +1120,5 @@ class Gemma3nForCausalLM(nn.Module):
1120
return logits
1121
1122
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1115
- loader = AutoWeightsLoader(
1116
- self,
1117
- skip_substrs=(
1118
- ["embed_audio.", "embed_vision.", "audio_tower.", "vision_tower."]
1119
- ),
1120
- )
1121
- return loader.load_weights(weights)
1123
+ loader = AutoWeightsLoader(self)
1124
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/gemma4.py
+13
-10
@@ -1693,13 +1693,16 @@ class Gemma4ForCausalLM(
1693
1694
yield name, weight
1695
1696
- # Skip multimodal weights — handled by the multimodal wrapper.
1697
- skip = [
1698
- "audio_tower.",
1699
- "vision_tower.",
1700
- "embed_audio.",
1701
- "embed_vision.",
1702
- ]
1703
-
1704
- loader = AutoWeightsLoader(self, skip_substrs=skip)
1705
- return loader.load_weights(_weight_iterator())
1696
+ # Drop multimodal weights, which are handled by the multimodal wrapper.
1697
+ # `_weight_iterator` already applies this model's renames by hand, so
1698
+ # `hf_to_vllm_mapper` is deliberately not passed here.
1699
+ mapper = WeightsMapper(
1700
+ orig_to_new_substr={
1701
+ "audio_tower.": None,
1702
+ "vision_tower.": None,
1703
+ "embed_audio.": None,
1704
+ "embed_vision.": None,
1705
+ }
1706
+ )
1707
+ loader = AutoWeightsLoader(self)
1708
+ return loader.load_weights(_weight_iterator(), mapper=mapper)
vllm/model_executor/models/glm4.py
+13
-14
@@ -45,11 +45,7 @@ from vllm.v1.attention.backend import AttentionType
45
from .interfaces import SupportsLoRA, SupportsPP
46
from .llama import LlamaMLP as Glm4MLP
47
from .llama import LlamaModel
48
-from .utils import (
49
- AutoWeightsLoader,
50
- PPMissingLayer,
51
- maybe_prefix,
52
-)
48
+from .utils import AutoWeightsLoader, PPMissingLayer, WeightsMapper, maybe_prefix
49
50
51
class Glm4Attention(nn.Module):
@@ -269,6 +265,16 @@ class Glm4ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
265
self.model.make_empty_intermediate_tensors
266
)
267
268
+ # Drop the speculative (MTP) layers, which are loaded by the draft
269
+ # model instead. They are appended after the main decoder layers.
270
+ num_nextn_layers = getattr(config, "num_nextn_predict_layers", 0)
271
+ self.hf_to_vllm_mapper = WeightsMapper(
272
+ orig_to_new_prefix={
273
+ f"model.layers.{config.num_hidden_layers + i}.": None
274
+ for i in range(num_nextn_layers)
275
+ }
276
+ )
277
+
278
def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
279
return self.model.embed_input_ids(input_ids)
280
@@ -292,12 +298,5 @@ class Glm4ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
298
return logits
299
300
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
295
- # Skip the speculative (MTP) layers, which are loaded by the
296
- # draft model instead.
297
- num_nextn_layers = getattr(self.config, "num_nextn_predict_layers", 0)
298
- skip_prefixes = [
299
- f"model.layers.{self.config.num_hidden_layers + i}."
300
- for i in range(num_nextn_layers)
301
- ]
302
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
303
- return loader.load_weights(weights)
301
+ loader = AutoWeightsLoader(self)
302
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/glmasr.py
+6
-3
@@ -916,6 +916,10 @@ class GlmAsrForConditionalGeneration(
916
):
917
supported_languages = ISO639_1_SUPPORTED_LANGS
918
919
+ hf_to_vllm_mapper = WeightsMapper(
920
+ orig_to_new_prefix={"audio_tower.embed_positions": None}
921
+ )
922
+
923
packed_modules_mapping = {
924
"qkv_proj": ["q_proj", "k_proj", "v_proj"],
925
"gate_up_proj": ["gate_proj", "up_proj"],
@@ -1083,9 +1087,8 @@ class GlmAsrForConditionalGeneration(
1087
return self.language_model.compute_logits(hidden_states)
1088
1089
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1086
- skip_prefixes = ["audio_tower.embed_positions"]
1087
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
1088
- return loader.load_weights(weights)
1090
+ loader = AutoWeightsLoader(self)
1091
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1092
1093
@classmethod
1094
def _get_audio_token(cls, model_config: ModelConfig) -> str:
vllm/model_executor/models/gpt2.py
+9
-4
@@ -52,6 +52,7 @@ from vllm.sequence import IntermediateTensors
52
from .interfaces import SupportsCrossEncoding, SupportsPP
53
from .utils import (
54
AutoWeightsLoader,
55
+ WeightsMapper,
56
make_empty_intermediate_tensors_factory,
57
make_layers,
58
maybe_prefix,
@@ -182,6 +183,11 @@ class GPT2Block(nn.Module):
183
184
@support_torch_compile
185
class GPT2Model(nn.Module):
186
+ # Drop attention mask buffers; NOTE: "c_attn.bias" must not be dropped.
187
+ hf_to_vllm_mapper = WeightsMapper(
188
+ orig_to_new_substr={".attn.bias": None, ".attn.masked_bias": None}
189
+ )
190
+
191
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
192
super().__init__()
193
@@ -253,11 +259,10 @@ class GPT2Model(nn.Module):
259
yield name, loaded_weight
260
261
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
256
- # Skip attention mask buffers; NOTE: "c_attn.bias" must not be skipped.
257
- loader = AutoWeightsLoader(
258
- self, skip_substrs=[".attn.bias", ".attn.masked_bias"]
262
+ loader = AutoWeightsLoader(self)
263
+ return loader.load_weights(
264
+ self._transpose_conv1d(weights), mapper=self.hf_to_vllm_mapper
265
)
260
- return loader.load_weights(self._transpose_conv1d(weights))
266
267
268
class GPT2LMHeadModel(nn.Module, SupportsPP):
vllm/model_executor/models/gpt_j.py
+6
-2
@@ -243,7 +243,11 @@ class GPTJForCausalLM(nn.Module, SupportsPP):
243
".q_proj": (".qkv_proj", "q"),
244
".k_proj": (".qkv_proj", "k"),
245
".v_proj": (".qkv_proj", "v"),
246
- }
246
+ },
247
+ orig_to_new_substr={
248
+ "attn.bias": None,
249
+ "attn.masked_bias": None,
250
+ },
251
)
252
253
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
@@ -291,5 +295,5 @@ class GPTJForCausalLM(nn.Module, SupportsPP):
295
return logits
296
297
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
294
- loader = AutoWeightsLoader(self, skip_substrs=["attn.bias", "attn.masked_bias"])
298
+ loader = AutoWeightsLoader(self)
299
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/gpt_neox.py
+8
-3
@@ -48,6 +48,7 @@ from vllm.sequence import IntermediateTensors
48
from .interfaces import SupportsPP
49
from .utils import (
50
AutoWeightsLoader,
51
+ WeightsMapper,
52
make_empty_intermediate_tensors_factory,
53
make_layers,
54
maybe_prefix,
@@ -196,6 +197,10 @@ class GPTNeoXLayer(nn.Module):
197
198
@support_torch_compile
199
class GPTNeoXModel(nn.Module):
200
+ hf_to_vllm_mapper = WeightsMapper(
201
+ orig_to_new_substr={"attention.bias": None, "attention.masked_bias": None}
202
+ )
203
+
204
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
205
super().__init__()
206
@@ -262,10 +267,10 @@ class GPTNeoXModel(nn.Module):
267
yield name, loaded_weight
268
269
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
265
- loader = AutoWeightsLoader(
266
- self, skip_substrs=["attention.bias", "attention.masked_bias"]
270
+ loader = AutoWeightsLoader(self)
271
+ return loader.load_weights(
272
+ self._repack_qkv(weights), mapper=self.hf_to_vllm_mapper
273
)
268
- return loader.load_weights(self._repack_qkv(weights))
274
275
276
class GPTNeoXForCausalLM(nn.Module, SupportsPP):
vllm/model_executor/models/idefics2_vision_model.py
+9
-7
@@ -19,7 +19,6 @@
19
"""PyTorch Idefics2 model."""
20
21
from collections.abc import Iterable
22
-from typing import ClassVar
22
23
import torch
24
from torch import nn
@@ -360,7 +359,7 @@ class Idefics2Encoder(nn.Module):
359
360
361
class Idefics2VisionTransformer(nn.Module):
363
- hf_to_vllm_mapper: ClassVar[WeightsMapper] = WeightsMapper(
362
+ hf_to_vllm_mapper = WeightsMapper(
363
orig_to_new_stacked={
364
".q_proj": (".qkv_proj", "q"),
365
".k_proj": (".qkv_proj", "k"),
@@ -408,6 +407,13 @@ class Idefics2VisionTransformer(nn.Module):
407
if require_post_norm
408
else nn.Identity()
409
)
410
+ # head is a pooling header absent from this model.
411
+ orig_to_new_prefix: dict[str, str | None] = {"head.": None}
412
+ if not require_post_norm:
413
+ orig_to_new_prefix["post_layernorm."] = None
414
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
415
+ orig_to_new_prefix=orig_to_new_prefix
416
+ )
417
418
def get_input_embeddings(self):
419
return self.embeddings
@@ -469,11 +475,7 @@ class Idefics2VisionTransformer(nn.Module):
475
return last_hidden_state
476
477
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
472
- # head is a pooling header absent from this model.
473
- skip_prefixes = ["head."]
474
- if not self.require_post_norm:
475
- skip_prefixes.append("post_layernorm.")
476
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
478
+ loader = AutoWeightsLoader(self)
479
480
layer_count = len(self.encoder.layers)
481
vllm/model_executor/models/interfaces.py
+2
-3
@@ -1150,7 +1150,7 @@ class SupportsLateInteraction(Protocol):
1150
class SupportsQuant:
1151
"""The interface required for all models that support quantization."""
1152
1153
- hf_to_vllm_mapper: ClassVar["WeightsMapper | None"] = None
1153
+ hf_to_vllm_mapper: "WeightsMapper | None" = None
1154
packed_modules_mapping: ClassVar[dict[str, list[str]]]
1155
quant_config: QuantizationConfig | None = None
1156
@@ -1184,8 +1184,7 @@ class SupportsQuant:
1184
if self.quant_config is None:
1185
return
1186
if (hf_to_vllm_mapper := self.hf_to_vllm_mapper) is not None:
1187
- unstacked_mapper = hf_to_vllm_mapper.get_unstacked_mapper()
1188
- self.quant_config.apply_vllm_mapper(unstacked_mapper)
1187
+ self.quant_config.apply_vllm_mapper(hf_to_vllm_mapper.get_rename_mapper())
1188
if packed_modules_mapping := getattr(self, "packed_modules_mapping", None):
1189
self.quant_config.packed_modules_mapping.update(packed_modules_mapping)
1190
vllm/model_executor/models/interns1_pro.py
+9
-8
@@ -616,17 +616,18 @@ class InternS1ProForConditionalGeneration(
616
617
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
618
"""load weights"""
619
- skip_prefixes = ["model.time_series."]
619
+ orig_to_new_prefix: dict[str, str | None] = {
620
+ "model.visual.": "visual.",
621
+ "lm_head.": "language_model.lm_head.",
622
+ "model.language_model.": "language_model.model.",
623
+ "model.time_series.": None,
624
+ }
625
if self.visual is None:
621
- skip_prefixes.append("visual.")
626
+ orig_to_new_prefix["visual."] = None
627
# FIXME(Isotr0py): See if we can avoid tighing FoPE to PP layers
628
weights_mapper = WeightsMapper(
624
- orig_to_new_prefix={
625
- "model.visual.": "visual.",
626
- "lm_head.": "language_model.lm_head.",
627
- "model.language_model.": "language_model.model.",
628
- },
629
+ orig_to_new_prefix=orig_to_new_prefix,
630
orig_to_new_suffix=self.get_frope_params_map(),
631
)
631
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
632
+ loader = AutoWeightsLoader(self)
633
return loader.load_weights(weights, mapper=weights_mapper)
vllm/model_executor/models/interns2_preview.py
+9
-5
@@ -13,7 +13,7 @@ from .qwen3_vl import (
13
Qwen3VLMultiModalProcessor,
14
Qwen3VLProcessingInfo,
15
)
16
-from .utils import AutoWeightsLoader
16
+from .utils import AutoWeightsLoader, WeightsMapper
17
18
19
class InternS2PreviewProcessingInfo(Qwen3VLProcessingInfo):
@@ -30,9 +30,13 @@ class InternS2PreviewProcessingInfo(Qwen3VLProcessingInfo):
30
dummy_inputs=Qwen3VLDummyInputsBuilder,
31
)
32
class InternS2PreviewForConditionalGeneration(Qwen3_5MoeForConditionalGeneration):
33
- def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
34
- loader = AutoWeightsLoader(
35
- self,
36
- skip_prefixes=["mtp.", "model.time_series.", "time_series."],
33
+ # `mtp.` is already dropped by `Qwen3_5ForConditionalGeneration`.
34
+ hf_to_vllm_mapper = Qwen3_5MoeForConditionalGeneration.hf_to_vllm_mapper | (
35
+ WeightsMapper(
36
+ orig_to_new_prefix={"model.time_series.": None, "time_series.": None}
37
)
38
+ )
39
+
40
+ def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
41
+ loader = AutoWeightsLoader(self)
42
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/internvl.py
+27
-18
@@ -59,7 +59,12 @@ from .interfaces import (
59
SupportsMultiModal,
60
SupportsPP,
61
)
62
-from .utils import AutoWeightsLoader, init_vllm_registered_model, maybe_prefix
62
+from .utils import (
63
+ AutoWeightsLoader,
64
+ WeightsMapper,
65
+ init_vllm_registered_model,
66
+ maybe_prefix,
67
+)
68
69
70
class InternVLImagePixelInputs(TensorSchema):
@@ -554,6 +559,25 @@ class InternVLChatModel(
559
):
560
supports_encoder_tp_data = True
561
562
+ hf_to_vllm_mapper = WeightsMapper(
563
+ orig_to_new_prefix=dict.fromkeys(
564
+ [
565
+ "action_embed",
566
+ "temporal_embed",
567
+ "track_embed",
568
+ "track_embed_decoder",
569
+ "box_token",
570
+ "cg_criterion",
571
+ "cg_model",
572
+ "loc_encoder",
573
+ "loc_decoder",
574
+ "sam",
575
+ "temporal_token",
576
+ "track_token",
577
+ ]
578
+ )
579
+ )
580
+
581
@classmethod
582
def get_placeholder_str(cls, modality: str, i: int) -> str | None:
583
if modality.startswith("image"):
@@ -865,23 +889,8 @@ class InternVLChatModel(
889
return self.language_model.compute_logits(hidden_states)
890
891
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
868
- # unused modules appear in OpenGVLab/InternVideo2_5_Chat_8B
869
- skip_prefixes = [
870
- "action_embed",
871
- "temporal_embed",
872
- "track_embed",
873
- "track_embed_decoder",
874
- "box_token",
875
- "cg_criterion",
876
- "cg_model",
877
- "loc_encoder",
878
- "loc_decoder",
879
- "sam",
880
- "temporal_token",
881
- "track_token",
882
- ]
883
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
884
- return loader.load_weights(weights)
892
+ loader = AutoWeightsLoader(self)
893
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
894
895
def get_mm_mapping(self) -> MultiModelKeys:
896
"""
vllm/model_executor/models/jina.py
+4
-2
@@ -43,6 +43,8 @@ logger = logging.getLogger(__name__)
43
class JinaForRanking(nn.Module, SupportsLateInteraction):
44
is_pooling_model = True
45
46
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"lm_head.": None})
47
+
48
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
49
super().__init__()
50
config = vllm_config.model_config.hf_config
@@ -87,8 +89,8 @@ class JinaForRanking(nn.Module, SupportsLateInteraction):
89
return hidden_states
90
91
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
90
- loader = AutoWeightsLoader(self, skip_prefixes=(["lm_head."]))
91
- return loader.load_weights(weights)
92
+ loader = AutoWeightsLoader(self)
93
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
94
95
96
class JinaForRankingPool(StepPool):
vllm/model_executor/models/keye.py
+3
-2
@@ -721,7 +721,8 @@ class KeyeSiglipVisionModel(nn.Module):
721
".q_proj": (".qkv_proj", "q"),
722
".k_proj": (".qkv_proj", "k"),
723
".v_proj": (".qkv_proj", "v"),
724
- }
724
+ },
725
+ orig_to_new_prefix={"vision_model.head.": None},
726
)
727
728
def __init__(
@@ -782,7 +783,7 @@ class KeyeSiglipVisionModel(nn.Module):
783
)
784
785
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
785
- loader = AutoWeightsLoader(self, skip_prefixes=["vision_model.head."])
786
+ loader = AutoWeightsLoader(self)
787
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
788
789
vllm/model_executor/models/kimi_audio.py
+8
-15
@@ -380,6 +380,12 @@ class KimiAudioForConditionalGeneration(
380
"model.embed_tokens.": "language_model.model.embed_tokens.",
381
"model.norm.": "language_model.model.norm.",
382
"lm_head.": "language_model.lm_head.",
383
+ # MIMO/TTS weights and any `model.` residue no rule above
384
+ # claimed: this model only does ASR (speech-to-text).
385
+ "model.": None,
386
+ "mimo_layers.": None,
387
+ "mimo_output.": None,
388
+ "mimo_norm.": None,
389
},
390
orig_to_new_substr={
391
".fc1.": ".mlp.fc1.",
@@ -573,21 +579,8 @@ class KimiAudioForConditionalGeneration(
579
return self.language_model.compute_logits(hidden_states)
580
581
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
576
- """Load weights, skipping MIMO layers (TTS-only) for ASR."""
577
- # Filter out MIMO/TTS weights since we only do ASR (speech-to-text)
578
- skipped_patterns = [
579
- # Audio tower
580
- "model.",
581
- # MIMO/TTS
582
- "mimo_layers.",
583
- "mimo_output.",
584
- "mimo_norm.",
585
- ]
586
-
587
- # Load main model weights (LLM + projector) with mapper
588
- loader = AutoWeightsLoader(self, skip_prefixes=skipped_patterns)
589
- loaded = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
590
- return loaded
582
+ loader = AutoWeightsLoader(self)
583
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
584
585
@classmethod
586
def get_speech_to_text_config(
vllm/model_executor/models/lfm2_siglip2.py
+5
-4
@@ -484,6 +484,10 @@ class Siglip2Model(torch.nn.Module):
484
require_post_norm=require_post_norm,
485
prefix=maybe_prefix(prefix, "vision_model"),
486
)
487
+ if self.vision_model.post_layernorm is None:
488
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
489
+ orig_to_new_prefix={"vision_model.post_layernorm.": None}
490
+ )
491
492
def forward(
493
self,
@@ -510,10 +514,7 @@ class Siglip2Model(torch.nn.Module):
514
)
515
516
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
513
- skip_prefixes = []
514
- if self.vision_model.post_layernorm is None:
515
- skip_prefixes.append("vision_model.post_layernorm.")
516
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
517
+ loader = AutoWeightsLoader(self)
518
519
# Drop layers omitted by num_hidden_layers_override.
520
layer_count = len(self.vision_model.encoder.layers)
vllm/model_executor/models/llama.py
+1
-2
@@ -26,7 +26,6 @@
26
27
from collections.abc import Iterable
28
from itertools import islice
29
-from typing import ClassVar
29
30
import torch
31
from torch import nn
@@ -343,7 +342,7 @@ class LlamaDecoderLayer(nn.Module):
342
},
343
)
344
class LlamaModel(nn.Module, EagleModelMixin):
346
- hf_to_vllm_mapper: ClassVar[WeightsMapper] = WeightsMapper(
345
+ hf_to_vllm_mapper = WeightsMapper(
346
orig_to_new_stacked={
347
# weight_name: (param_name, shard_id)
348
".q_proj": (".qkv_proj", "q"),
vllm/model_executor/models/llama4_eagle.py
+1
-5
@@ -206,9 +206,5 @@ class EagleLlama4ForCausalLM(Llama4ForCausalLM, SupportsMultiModalEmbeddings):
206
process_eagle_weight(self, name)
207
return name, weight
208
209
- loader = AutoWeightsLoader(
210
- self,
211
- # lm_head is tied with target model (Llama4ForCausalLM)
212
- skip_prefixes=([]),
213
- )
209
+ loader = AutoWeightsLoader(self)
210
loader.load_weights(map(transform, weights))
vllm/model_executor/models/llama_eagle.py
+1
-4
@@ -175,8 +175,5 @@ class EagleLlamaForCausalLM(LlamaForCausalLM):
175
process_eagle_weight(self, name)
176
return name, loaded_weight
177
178
- loader = AutoWeightsLoader(
179
- self,
180
- skip_prefixes=None,
181
- )
178
+ loader = AutoWeightsLoader(self)
179
loader.load_weights(map(transform, weights))
vllm/model_executor/models/llama_eagle3.py
+9
-10
@@ -415,18 +415,17 @@ class Eagle3LlamaForCausalLM(LlamaForCausalLM):
415
"Please provide mask_hidden in the weights."
416
)
417
418
- skip_substrs = ["mask_hidden"]
418
+ orig_to_new_substr = {"mask_hidden": None}
419
if not includes_draft_id_mapping:
420
- skip_substrs.append("draft_id_to_target_id")
420
+ orig_to_new_substr["draft_id_to_target_id"] = None
421
if not includes_embed_tokens:
422
- skip_substrs.append("embed_tokens")
422
+ orig_to_new_substr["embed_tokens"] = None
423
if not self.model.use_aux_hidden_state:
424
- skip_substrs.append("fc.")
424
+ orig_to_new_substr["fc."] = None
425
if not self.model.norm_before_fc:
426
- skip_substrs.append("input_norm.")
427
- loader = AutoWeightsLoader(
428
- self,
429
- skip_prefixes=None,
430
- skip_substrs=skip_substrs,
426
+ orig_to_new_substr["input_norm."] = None
427
+ loader = AutoWeightsLoader(self)
428
+ loader.load_weights(
429
+ model_weights.items(),
430
+ mapper=WeightsMapper(orig_to_new_substr=orig_to_new_substr),
431
)
432
- loader.load_weights(model_weights.items())
vllm/model_executor/models/longcat_flash_ngram.py
+7
-5
@@ -31,7 +31,7 @@ from vllm.v1.worker.gpu.states import RequestState
31
32
from .interfaces import SupportsLoRA, SupportsPP
33
from .longcat_flash import FlashConfig, FlashModel
34
-from .utils import AutoWeightsLoader, PPMissingLayer, maybe_prefix
34
+from .utils import AutoWeightsLoader, PPMissingLayer, WeightsMapper, maybe_prefix
35
36
37
def uses_ngram_embedding(config: FlashConfig) -> bool:
@@ -204,6 +204,9 @@ class FlashNgramModel(FlashModel):
204
class LongcatFlashNgramForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
205
"""LongCat-Flash-Lite for causal LM (MRV2-only, n-gram embedding)."""
206
207
+ # MTP weights are not part of this model.
208
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"model.mtp.": None})
209
+
210
packed_modules_mapping = {
211
"qkv_proj": ["q_proj", "k_proj", "v_proj"],
212
"gate_up_proj": ["gate_proj", "up_proj"],
@@ -266,10 +269,9 @@ class LongcatFlashNgramForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
269
270
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
271
# AutoWeightsLoader routes ``model.*`` to FlashNgramModel.load_weights
269
- # (which handles the ngram split) and ``lm_head.*`` to the head. MTP
270
- # weights are not part of this model.
271
- loader = AutoWeightsLoader(self, skip_prefixes=["model.mtp."])
272
- return loader.load_weights(weights)
272
+ # (which handles the ngram split) and ``lm_head.*`` to the head.
273
+ loader = AutoWeightsLoader(self)
274
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
275
276
277
class LongcatNgramModelState(DefaultModelState):
vllm/model_executor/models/mimo.py
+6
-4
@@ -41,7 +41,7 @@ from vllm.model_executor.layers.vocab_parallel_embedding import ParallelLMHead
41
from vllm.model_executor.models.qwen2 import Qwen2ForCausalLM, Qwen2Model
42
from vllm.sequence import IntermediateTensors
43
44
-from .utils import AutoWeightsLoader, PPMissingLayer, maybe_prefix
44
+from .utils import AutoWeightsLoader, PPMissingLayer, WeightsMapper, maybe_prefix
45
46
logger = init_logger(__name__)
47
@@ -87,6 +87,9 @@ class MiMoModel(Qwen2Model):
87
88
89
class MiMoForCausalLM(Qwen2ForCausalLM, nn.Module):
90
+ # MTP layers are loaded by the draft model, not the main model.
91
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"model.mtp_layers.": None})
92
+
93
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
94
nn.Module.__init__(self)
95
config = vllm_config.model_config.hf_config
@@ -119,9 +122,8 @@ class MiMoForCausalLM(Qwen2ForCausalLM, nn.Module):
122
)
123
124
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
122
- # MTP layers are loaded by the draft model, not the main model.
123
- loader = AutoWeightsLoader(self, skip_prefixes=["model.mtp_layers."])
124
- return loader.load_weights(weights)
125
+ loader = AutoWeightsLoader(self)
126
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
127
128
def compute_logits(
129
self,
vllm/model_executor/models/mimo_v2_omni.py
+2
-1
@@ -1189,6 +1189,7 @@ class MiMoV2OmniForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, SupportsQ
1189
# mapping for original checkpoint
1190
"lm_head.": "language_model.lm_head.",
1191
"model.": "language_model.model.",
1192
+ "audio_tokenizer.": None,
1193
}
1194
)
1195
@@ -1490,6 +1491,6 @@ class MiMoV2OmniForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, SupportsQ
1491
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1492
audio_loaded: set[str] = set()
1493
1493
- loader = AutoWeightsLoader(self, skip_prefixes=["audio_tokenizer."])
1494
+ loader = AutoWeightsLoader(self)
1495
auto_loaded = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1496
return audio_loaded | auto_loaded
vllm/model_executor/models/minicpmo.py
+11
-3
@@ -71,7 +71,12 @@ from .minicpmv import (
71
MiniCPMVProcessingInfo,
72
_minicpmv_field_config,
73
)
74
-from .utils import AutoWeightsLoader, cast_overflow_tensors, maybe_prefix
74
+from .utils import (
75
+ AutoWeightsLoader,
76
+ WeightsMapper,
77
+ cast_overflow_tensors,
78
+ maybe_prefix,
79
+)
80
81
CPU_DEVICE = torch.device("cpu")
82
@@ -672,6 +677,9 @@ class MiniCPMWhisperEncoder(WhisperEncoder):
677
class MiniCPMOBaseModel:
678
"""Base mixin class for MiniCPM-O models with audio support."""
679
680
+ # Unlike the vision-only MiniCPM-V models, audio weights are loaded here.
681
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"tts": None})
682
+
683
packed_modules_mapping = {
684
"qkv_proj": [
685
"q_proj",
@@ -718,8 +726,8 @@ class MiniCPMOBaseModel:
726
return model
727
728
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
721
- loader = AutoWeightsLoader(self, skip_prefixes=["tts"])
722
- loaded = loader.load_weights(weights)
729
+ loader = AutoWeightsLoader(self)
730
+ loaded = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
731
self._ensure_resampler_device()
732
return loaded
733
vllm/model_executor/models/minicpmv.py
+13
-7
@@ -109,7 +109,7 @@ from .interfaces import (
109
SupportsMultiModal,
110
SupportsPP,
111
)
112
-from .utils import AutoWeightsLoader, flatten_bn, maybe_prefix
112
+from .utils import AutoWeightsLoader, WeightsMapper, flatten_bn, maybe_prefix
113
114
# For profile run
115
_MAX_FRAMES_PER_VIDEO = 16
@@ -1567,6 +1567,10 @@ class MiniCPMV2_5(MiniCPMVBaseModel, SupportsLoRA):
1567
1568
1569
class MiniCPMV2_6(MiniCPMVBaseModel, SupportsLoRA):
1570
+ hf_to_vllm_mapper = WeightsMapper(
1571
+ # The vision-only models have no audio tower or TTS head to load weights into.
1572
+ orig_to_new_prefix={"apm.": None, "audio": None, "tts": None}
1573
+ )
1574
packed_modules_mapping = {
1575
"qkv_proj": [
1576
"q_proj",
@@ -1660,13 +1664,14 @@ class MiniCPMV2_6(MiniCPMVBaseModel, SupportsLoRA):
1664
return self.resampler(vision_embedding, tgt_sizes)
1665
1666
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1663
- loader = AutoWeightsLoader(self, skip_prefixes=["apm.", "audio", "tts"])
1664
- loaded = loader.load_weights(weights)
1667
+ loader = AutoWeightsLoader(self)
1668
+ loaded = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1669
self._ensure_resampler_device()
1670
return loaded
1671
1672
1673
class MiniCPMV4_0(MiniCPMVBaseModel, SupportsLoRA):
1674
+ hf_to_vllm_mapper = MiniCPMV2_6.hf_to_vllm_mapper
1675
packed_modules_mapping = {
1676
"qkv_proj": [
1677
"q_proj",
@@ -1758,13 +1763,14 @@ class MiniCPMV4_0(MiniCPMVBaseModel, SupportsLoRA):
1763
return self.resampler(vision_embedding, tgt_sizes)
1764
1765
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1761
- loader = AutoWeightsLoader(self, skip_prefixes=["apm.", "audio", "tts"])
1762
- loaded = loader.load_weights(weights)
1766
+ loader = AutoWeightsLoader(self)
1767
+ loaded = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1768
self._ensure_resampler_device()
1769
return loaded
1770
1771
1772
class MiniCPMV4_5(MiniCPMVBaseModel, SupportsLoRA):
1773
+ hf_to_vllm_mapper = MiniCPMV2_6.hf_to_vllm_mapper
1774
packed_modules_mapping = {
1775
"qkv_proj": [
1776
"q_proj",
@@ -1861,8 +1867,8 @@ class MiniCPMV4_5(MiniCPMVBaseModel, SupportsLoRA):
1867
return self.resampler(vision_embedding, tgt_sizes, all_temporal_ids)
1868
1869
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1864
- loader = AutoWeightsLoader(self, skip_prefixes=["apm.", "audio", "tts"])
1865
- loaded = loader.load_weights(weights)
1870
+ loader = AutoWeightsLoader(self)
1871
+ loaded = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1872
self._ensure_resampler_device()
1873
return loaded
1874
vllm/model_executor/models/minicpmv4_6.py
+2
-1
@@ -958,6 +958,7 @@ class MiniCPMV4_6ForConditionalGeneration(
958
"model.merger.": "merger.",
959
"model.language_model.": "language_model.model.",
960
"lm_head.": "language_model.lm_head.",
961
+ "mtp.": None,
962
}
963
)
964
@@ -1281,7 +1282,7 @@ class MiniCPMV4_6ForConditionalGeneration(
1282
self,
1283
weights: Iterable[tuple[str, torch.Tensor]],
1284
) -> set[str]:
1284
- loader = AutoWeightsLoader(self, skip_prefixes=["mtp."])
1285
+ loader = AutoWeightsLoader(self)
1286
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1287
1288
def get_mm_mapping(self) -> MultiModelKeys:
vllm/model_executor/models/minimax_m2.py
+9
-11
@@ -371,6 +371,14 @@ class MiniMaxM2Model(nn.Module, EagleModelMixin):
371
["hidden_states", "residual"], config.hidden_size
372
)
373
374
+ # Drop spec-decode (MTP) layers; they are appended after the main
375
+ # decoder layers and have no destination in the main model.
376
+ if num_mtp := getattr(config, "num_mtp_modules", 0):
377
+ base = config.num_hidden_layers
378
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
379
+ orig_to_new_prefix={f"layers.{base + i}.": None for i in range(num_mtp)}
380
+ )
381
+
382
def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
383
return self.embed_tokens(input_ids)
384
@@ -413,17 +421,7 @@ class MiniMaxM2Model(nn.Module, EagleModelMixin):
421
return hidden_states
422
423
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
416
- # Skip spec-decode (MTP) layers; they are appended after the main
417
- # decoder layers and have no destination in the main model.
418
- skip_prefixes = None
419
- num_mtp = getattr(self.config, "num_mtp_modules", 0)
420
- if num_mtp:
421
- base = self.config.num_hidden_layers
422
- skip_prefixes = [f"layers.{base + i}." for i in range(num_mtp)]
423
- loader = AutoWeightsLoader(
424
- self,
425
- skip_prefixes=skip_prefixes,
426
- )
424
+ loader = AutoWeightsLoader(self)
425
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
426
427
vllm/model_executor/models/modernbert.py
+4
-2
@@ -434,6 +434,8 @@ class ModernBertPredictionHead(nn.Module):
434
class ModernBertForTokenClassification(nn.Module):
435
is_pooling_model = True
436
437
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"drop": None})
438
+
439
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
440
super().__init__()
441
config = vllm_config.model_config.hf_config
@@ -456,8 +458,8 @@ class ModernBertForTokenClassification(nn.Module):
458
return self.model.embed_input_ids(input_ids)
459
460
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
459
- loader = AutoWeightsLoader(self, skip_prefixes=["drop"])
460
- loaded_params = loader.load_weights(weights)
461
+ loader = AutoWeightsLoader(self)
462
+ loaded_params = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
463
return loaded_params
464
465
def forward(
vllm/model_executor/models/moss_audio.py
+2
-4
@@ -1450,6 +1450,7 @@ class MossAudioModel(nn.Module, SupportsMultiModal, SupportsPP, SupportsLoRA):
1450
"language_model.embed_tokens.": "language_model.model.embed_tokens.",
1451
"language_model.layers.": "language_model.model.layers.",
1452
"language_model.norm.": "language_model.model.norm.",
1453
+ "audio_encoder.embed_positions": None,
1454
},
1455
orig_to_new_stacked={
1456
".gate_proj": (".gate_up_proj", 0),
@@ -1865,8 +1866,5 @@ class MossAudioModel(nn.Module, SupportsMultiModal, SupportsPP, SupportsLoRA):
1866
return self.language_model.compute_logits(hidden_states)
1867
1868
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1868
- loader = AutoWeightsLoader(
1869
- self,
1870
- skip_prefixes=["audio_encoder.embed_positions"],
1871
- )
1869
+ loader = AutoWeightsLoader(self)
1870
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/nemotron_h.py
+2
-2
@@ -708,7 +708,7 @@ class NemotronHForCausalLM(
708
is_non_gated_moe: bool = True
709
710
hf_to_vllm_mapper = WeightsMapper(
711
- orig_to_new_prefix={"backbone": "model"},
711
+ orig_to_new_prefix={"backbone": "model", "mtp": None},
712
orig_to_new_substr={"A_log": "A", "embeddings": "embed_tokens"},
713
orig_to_new_stacked={
714
".q_proj": (".qkv_proj", "q"),
@@ -887,5 +887,5 @@ class NemotronHForCausalLM(
887
return logits
888
889
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
890
- loader = AutoWeightsLoader(self, skip_prefixes=["mtp"])
890
+ loader = AutoWeightsLoader(self)
891
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/nemotron_vl.py
+8
-5
@@ -89,6 +89,12 @@ class NemotronVLProcessingInfo(BaseInternVLProcessingInfo):
89
dummy_inputs=BaseInternVLDummyInputsBuilder[NemotronVLProcessingInfo],
90
)
91
class LlamaNemotronVLChatModel(nn.Module, SupportsMultiModal, SupportsPP, SupportsLoRA):
92
+ # Ignore registered buffers, see
93
+ # https://huggingface.co/nvidia/C-RADIOv2-H/blob/main/input_conditioner.py#L28
94
+ hf_to_vllm_mapper = WeightsMapper(
95
+ orig_to_new_substr={"norm_mean": None, "norm_std": None}
96
+ )
97
+
98
@classmethod
99
def get_placeholder_str(cls, modality: str, i: int) -> str | None:
100
if modality.startswith("image"):
@@ -377,11 +383,8 @@ class LlamaNemotronVLChatModel(nn.Module, SupportsMultiModal, SupportsPP, Suppor
383
return self.language_model.compute_logits(hidden_states)
384
385
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
380
- ## Ignore registered_buffers
381
- ## see https://huggingface.co/nvidia/C-RADIOv2-H/blob/main/input_conditioner.py#L28 # noqa: E501
382
- skip_substrs = ["norm_mean", "norm_std"]
383
- loader = AutoWeightsLoader(self, skip_substrs=skip_substrs)
384
- return loader.load_weights(weights)
386
+ loader = AutoWeightsLoader(self)
387
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
388
389
def get_mm_mapping(self) -> MultiModelKeys:
390
"""
vllm/model_executor/models/paddleocr_vl.py
+11
-13
@@ -887,7 +887,16 @@ class SiglipVisionModel(nn.Module):
887
".q_proj": (".qkv_proj", "q"),
888
".k_proj": (".qkv_proj", "k"),
889
".v_proj": (".qkv_proj", "v"),
890
- }
890
+ },
891
+ # The SigLIP attention pooling head and packing pos embedding are
892
+ # present in the checkpoint but absent from this vision tower.
893
+ orig_to_new_substr={
894
+ "head.attention": None,
895
+ "head.layernorm": None,
896
+ "head.mlp": None,
897
+ "head.probe": None,
898
+ "packing_position_embedding": None,
899
+ },
900
)
901
902
def __init__(
@@ -934,18 +943,7 @@ class SiglipVisionModel(nn.Module):
943
)
944
945
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
937
- # Skip the SigLIP attention pooling head and packing pos embedding
938
- # present in the checkpoint but absent from this vision tower.
939
- loader = AutoWeightsLoader(
940
- self,
941
- skip_substrs=[
942
- "head.attention",
943
- "head.layernorm",
944
- "head.mlp",
945
- "head.probe",
946
- "packing_position_embedding",
947
- ],
948
- )
946
+ loader = AutoWeightsLoader(self)
947
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
948
949
vllm/model_executor/models/phi4mm.py
+2
-1
@@ -1016,6 +1016,7 @@ class Phi4MMForCausalLM(nn.Module, SupportsLoRA, SupportsMultiModal):
1016
hf_to_vllm_mapper = WeightsMapper(
1017
orig_to_new_substr={
1018
"base_layer.": "",
1019
+ "lora": None,
1020
},
1021
orig_to_new_prefix={
1022
"model.embed_tokens_extend.audio_embed.audio_projection.vision.": "embed_tokens_extend.audio_projection_for_vision.", # noqa: E501
@@ -1258,7 +1259,7 @@ class Phi4MMForCausalLM(nn.Module, SupportsLoRA, SupportsMultiModal):
1259
return logits
1260
1261
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> None:
1261
- loader = AutoWeightsLoader(self, skip_substrs=["lora"])
1262
+ loader = AutoWeightsLoader(self)
1263
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1264
1265
def get_mm_mapping(self) -> MultiModelKeys:
vllm/model_executor/models/qwen2_5_omni_thinker.py
+3
-1
@@ -1112,6 +1112,8 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
1112
"thinker.lm_head.": "language_model.lm_head.",
1113
"thinker.model.": "language_model.model.",
1114
"thinker.": "",
1115
+ "talker.": None,
1116
+ "token2wav.": None,
1117
}
1118
)
1119
packed_modules_mapping = {
@@ -1591,7 +1593,7 @@ class Qwen2_5OmniThinkerForConditionalGeneration(
1593
return self.language_model.compute_logits(hidden_states)
1594
1595
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1594
- loader = AutoWeightsLoader(self, skip_prefixes=["talker.", "token2wav."])
1596
+ loader = AutoWeightsLoader(self)
1597
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1598
1599
def get_mm_mapping(self) -> MultiModelKeys:
vllm/model_executor/models/qwen3_5.py
+8
-9
@@ -319,7 +319,7 @@ class Qwen3_5ForCausalLMBase(
319
# `model.language_model.` prefix inherited from the VL training stack.
320
# Strip it so both prefixed and clean checkpoints load correctly.
321
hf_to_vllm_mapper = WeightsMapper(
322
- orig_to_new_prefix={"model.language_model.": "model."},
322
+ orig_to_new_prefix={"model.language_model.": "model.", "mtp.": None},
323
)
324
325
def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
@@ -430,10 +430,7 @@ class Qwen3_5ForCausalLMBase(
430
return self.logits_processor(self.lm_head, hidden_states)
431
432
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
433
- loader = AutoWeightsLoader(
434
- self,
435
- skip_prefixes=["mtp."],
436
- )
433
+ loader = AutoWeightsLoader(self)
434
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
435
436
def get_mrope_input_positions(
@@ -470,6 +467,11 @@ class Qwen3_5MoeForCausalLM(Qwen3_5ForCausalLMBase, QwenNextMixtureOfExperts):
467
class Qwen3_5ForConditionalGeneration(Qwen3VLForConditionalGeneration, IsHybrid):
468
supports_multimodal_pruning = True
469
470
+ hf_to_vllm_mapper = (
471
+ Qwen3VLForConditionalGeneration.hf_to_vllm_mapper
472
+ | WeightsMapper(orig_to_new_prefix={"mtp.": None})
473
+ )
474
+
475
packed_modules_mapping = Qwen3VLForConditionalGeneration.packed_modules_mapping | {
476
"in_proj_qkvz": ["in_proj_qkv", "in_proj_z"],
477
"in_proj_ba": ["in_proj_b", "in_proj_a"],
@@ -590,10 +592,7 @@ class Qwen3_5ForConditionalGeneration(Qwen3VLForConditionalGeneration, IsHybrid)
592
return hidden_states
593
594
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
593
- loader = AutoWeightsLoader(
594
- self,
595
- skip_prefixes=["mtp."],
596
- )
595
+ loader = AutoWeightsLoader(self)
596
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
597
598
@classmethod
vllm/model_executor/models/qwen3_asr.py
+3
-4
@@ -372,6 +372,8 @@ class Qwen3ASRForConditionalGeneration(
372
"model.language_model.": "language_model.model.",
373
"model.multi_modal_projector.linear_1.": "audio_tower.proj1.",
374
"model.multi_modal_projector.linear_2.": "audio_tower.proj2.",
375
+ "talker.": None,
376
+ "code2wav.": None,
377
}
378
)
379
@@ -545,10 +547,7 @@ class Qwen3ASRForConditionalGeneration(
547
return self.language_model.compute_logits(hidden_states)
548
549
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
548
- loader = AutoWeightsLoader(
549
- self,
550
- skip_prefixes=["talker.", "code2wav."],
551
- )
550
+ loader = AutoWeightsLoader(self)
551
loaded_weights = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
552
553
return loaded_weights
vllm/model_executor/models/qwen3_asr_forced_aligner.py
+3
-4
@@ -59,6 +59,8 @@ class Qwen3ASRForcedAlignerForTokenClassification(
59
"thinker.lm_head.": "classifier.",
60
"thinker.model.": "language_model.model.",
61
"thinker.": "",
62
+ "talker.": None,
63
+ "code2wav.": None,
64
}
65
)
66
@@ -113,8 +115,5 @@ class Qwen3ASRForcedAlignerForTokenClassification(
115
return self.classifier(hidden_states)
116
117
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
116
- loader = AutoWeightsLoader(
117
- self,
118
- skip_prefixes=["talker.", "code2wav."],
119
- )
118
+ loader = AutoWeightsLoader(self)
119
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/qwen3_dflash.py
+8
-11
@@ -835,21 +835,18 @@ class DFlashQwen3ForCausalLM(Qwen3ForCausalLM):
835
model_weights["model.mask_embedding"] = mask_embedding
836
self.model.has_separate_mask_embedding = True
837
838
- skip_substrs = []
838
+ orig_to_new_substr = {}
839
if not includes_draft_id_mapping:
840
- skip_substrs.append("draft_id_to_target_id")
840
+ orig_to_new_substr["draft_id_to_target_id"] = None
841
if not includes_embed_tokens:
842
- skip_substrs.append("embed_tokens")
842
+ orig_to_new_substr["embed_tokens"] = None
843
if not self.model.use_aux_hidden_state:
844
- skip_substrs.append("fc.")
844
+ orig_to_new_substr["fc."] = None
845
if not self.model.has_separate_mask_embedding:
846
- skip_substrs.append("mask_embedding")
847
- loader = AutoWeightsLoader(
848
- self,
849
- skip_prefixes=None,
850
- skip_substrs=skip_substrs,
851
- )
852
- loader.load_weights(model_weights.items())
846
+ orig_to_new_substr["mask_embedding"] = None
847
+ mapper = WeightsMapper(orig_to_new_substr=orig_to_new_substr)
848
+ loader = AutoWeightsLoader(self)
849
+ loader.load_weights(model_weights.items(), mapper=mapper)
850
self.model._build_fused_kv_buffers()
851
852
def _read_mask_embedding(self) -> torch.Tensor | None:
vllm/model_executor/models/qwen3_dspark.py
+14
-8
@@ -30,7 +30,12 @@ from vllm.model_executor.layers.vocab_parallel_embedding import (
30
)
31
32
from .qwen3_dflash import DFlashQwen3ForCausalLM, DFlashQwen3Model
33
-from .utils import AutoWeightsLoader, maybe_prefix, process_eagle_weight
33
+from .utils import (
34
+ AutoWeightsLoader,
35
+ WeightsMapper,
36
+ maybe_prefix,
37
+ process_eagle_weight,
38
+)
39
40
logger = init_logger(__name__)
41
@@ -275,16 +280,17 @@ class Qwen3DSparkForCausalLM(DFlashQwen3ForCausalLM):
280
# mask_embedding is an unused placeholder param; DSpark masks via the vocab row.
281
# embed_tokens / lm_head are optional; when omitted they are shared from
282
# the target by load_dspark_model, so skip the unloaded params here.
278
- skip_substrs = ["mask_embedding"]
283
+ orig_to_new_substr = {"mask_embedding": None}
284
if not includes_embed_tokens:
280
- skip_substrs.append("embed_tokens")
285
+ orig_to_new_substr["embed_tokens"] = None
286
if not includes_lm_head:
282
- skip_substrs.append("lm_head")
287
+ orig_to_new_substr["lm_head"] = None
288
if not includes_draft_id_mapping:
284
- skip_substrs.append("draft_id_to_target_id")
289
+ orig_to_new_substr["draft_id_to_target_id"] = None
290
if self.model.confidence_head is None or not includes_confidence_head:
291
self.model.confidence_head = None
287
- skip_substrs.append("confidence_head")
288
- loader = AutoWeightsLoader(self, skip_substrs=skip_substrs)
289
- loader.load_weights(model_weights.items())
292
+ orig_to_new_substr["confidence_head"] = None
293
+ mapper = WeightsMapper(orig_to_new_substr=orig_to_new_substr)
294
+ loader = AutoWeightsLoader(self)
295
+ loader.load_weights(model_weights.items(), mapper=mapper)
296
self.model._build_fused_kv_buffers()
vllm/model_executor/models/qwen3_eagle3.py
+8
-11
@@ -425,18 +425,15 @@ class Eagle3Qwen3ForCausalLM(Qwen3ForCausalLM):
425
"Please provide mask_hidden in the weights."
426
)
427
428
- skip_substrs = ["mask_hidden"]
428
+ orig_to_new_substr = {"mask_hidden": None}
429
if not includes_draft_id_mapping:
430
- skip_substrs.append("draft_id_to_target_id")
430
+ orig_to_new_substr["draft_id_to_target_id"] = None
431
if not includes_embed_tokens:
432
- skip_substrs.append("embed_tokens")
432
+ orig_to_new_substr["embed_tokens"] = None
433
if not self.model.use_aux_hidden_state:
434
- skip_substrs.append("fc.")
434
+ orig_to_new_substr["fc."] = None
435
if not self.model.norm_before_fc:
436
- skip_substrs.append("input_norm.")
437
- loader = AutoWeightsLoader(
438
- self,
439
- skip_prefixes=None,
440
- skip_substrs=skip_substrs,
441
- )
442
- loader.load_weights(model_weights.items())
436
+ orig_to_new_substr["input_norm."] = None
437
+ mapper = WeightsMapper(orig_to_new_substr=orig_to_new_substr)
438
+ loader = AutoWeightsLoader(self)
439
+ loader.load_weights(model_weights.items(), mapper=mapper)
vllm/model_executor/models/qwen3_next.py
+5
-2
@@ -727,6 +727,9 @@ class Qwen3NextForCausalLM(
727
IsHybrid,
728
SupportsEagle3,
729
):
730
+ # MTP weights are loaded by the draft model, not this one.
731
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_prefix={"mtp.": None})
732
+
733
packed_modules_mapping = {
734
"qkv_proj": [
735
"q_proj",
@@ -833,5 +836,5 @@ class Qwen3NextForCausalLM(
836
return self.logits_processor(self.lm_head, hidden_states)
837
838
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
836
- loader = AutoWeightsLoader(self, skip_prefixes=["mtp."])
837
- return loader.load_weights(weights)
839
+ loader = AutoWeightsLoader(self)
840
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/qwen3_omni_moe_thinker.py
+3
-4
@@ -1587,6 +1587,8 @@ class Qwen3OmniMoeThinkerForConditionalGeneration(
1587
"thinker.lm_head.": "language_model.lm_head.",
1588
"thinker.model.": "language_model.model.",
1589
"thinker.": "",
1590
+ "talker.": None,
1591
+ "code2wav.": None,
1592
}
1593
)
1594
@@ -1943,10 +1945,7 @@ class Qwen3OmniMoeThinkerForConditionalGeneration(
1945
return self.language_model.compute_logits(hidden_states)
1946
1947
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1946
- loader = AutoWeightsLoader(
1947
- self,
1948
- skip_prefixes=["talker.", "code2wav."],
1949
- )
1948
+ loader = AutoWeightsLoader(self)
1949
loaded_weights = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1950
1951
return loaded_weights
vllm/model_executor/models/roberta.py
+5
-3
@@ -147,19 +147,21 @@ class RobertaEmbeddingModel(BertEmbeddingModel):
147
148
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
149
weights_list = list(weights)
150
+ orig_to_new_prefix: dict[str, str | None] = {"lm_head.": None}
151
has_roberta_prefix = any(
152
name.startswith("roberta.") for name, _ in weights_list
153
)
154
if has_roberta_prefix:
155
# For models with the `roberta.` prefix e.g.
156
# `FacebookAI/roberta-base`
156
- mapper = WeightsMapper(orig_to_new_prefix={"roberta.": "model."})
157
+ orig_to_new_prefix["roberta."] = "model."
158
else:
159
# For models without the `roberta.` prefix e.g.
160
# `sentence-transformers/stsb-roberta-base-v2`
160
- mapper = WeightsMapper(orig_to_new_prefix={"": "model."})
161
+ orig_to_new_prefix[""] = "model."
162
+ mapper = WeightsMapper(orig_to_new_prefix=orig_to_new_prefix)
163
162
- loader = AutoWeightsLoader(self, skip_prefixes=["lm_head."])
164
+ loader = AutoWeightsLoader(self)
165
return loader.load_weights(weights_list, mapper=mapper)
166
167
vllm/model_executor/models/siglip.py
+14
-8
@@ -738,6 +738,16 @@ class SiglipVisionTransformer(nn.Module):
738
)
739
self.last_hs_proc = partial(self.maybe_layer_norm_and_apply_head)
740
741
+ drops = dict[str, None]()
742
+ if self.post_layernorm is None:
743
+ drops["post_layernorm."] = None
744
+ if self.head is None:
745
+ drops["head."] = None
746
+ if drops:
747
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
748
+ orig_to_new_prefix=drops
749
+ )
750
+
751
@property
752
def dtype(self):
753
return next(self.parameters()).dtype
@@ -797,12 +807,7 @@ class SiglipVisionTransformer(nn.Module):
807
return encoder_outputs
808
809
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
800
- skip_prefixes = []
801
- if self.post_layernorm is None:
802
- skip_prefixes.append("post_layernorm.")
803
- if self.head is None:
804
- skip_prefixes.append("head.")
805
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
810
+ loader = AutoWeightsLoader(self)
811
812
layer_count = len(self.encoder.layers)
813
@@ -912,6 +917,8 @@ class SiglipTextEmbeddings(nn.Module):
917
class SiglipEmbeddingModel(nn.Module, SupportsMultiModal, SupportsQuant):
918
is_pooling_model = True
919
920
+ hf_to_vllm_mapper = WeightsMapper(orig_to_new_substr={".position_ids": None})
921
+
922
packed_modules_mapping = {"qkv_proj": ["q_proj", "k_proj", "v_proj"]}
923
924
@classmethod
@@ -1154,8 +1161,7 @@ class SiglipEmbeddingModel(nn.Module, SupportsMultiModal, SupportsQuant):
1161
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
1162
loader = AutoWeightsLoader(
1163
self,
1157
- skip_substrs=[".position_ids"],
1164
ignore_unexpected_prefixes=["logit_scale.", "logit_bias."],
1165
)
1166
1161
- return loader.load_weights(weights)
1167
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/skyworkr1v.py
+27
-17
@@ -35,7 +35,12 @@ from .internvl import (
35
BaseInternVLMultiModalProcessor,
36
BaseInternVLProcessingInfo,
37
)
38
-from .utils import AutoWeightsLoader, init_vllm_registered_model, maybe_prefix
38
+from .utils import (
39
+ AutoWeightsLoader,
40
+ WeightsMapper,
41
+ init_vllm_registered_model,
42
+ maybe_prefix,
43
+)
44
45
46
class SkyworkR1VImagePixelInputs(TensorSchema):
@@ -120,6 +125,25 @@ class SkyworkR1VProcessingInfo(BaseInternVLProcessingInfo):
125
dummy_inputs=BaseInternVLDummyInputsBuilder,
126
)
127
class SkyworkR1VChatModel(nn.Module, SupportsMultiModal, SupportsPP):
128
+ hf_to_vllm_mapper = WeightsMapper(
129
+ orig_to_new_prefix=dict.fromkeys(
130
+ [
131
+ "action_embed",
132
+ "temporal_embed",
133
+ "track_embed",
134
+ "track_embed_decoder",
135
+ "box_token",
136
+ "cg_criterion",
137
+ "cg_model",
138
+ "loc_encoder",
139
+ "loc_decoder",
140
+ "sam",
141
+ "temporal_token",
142
+ "track_token",
143
+ ]
144
+ )
145
+ )
146
+
147
@classmethod
148
def get_placeholder_str(cls, modality: str, i: int) -> str | None:
149
if modality.startswith("image"):
@@ -381,19 +405,5 @@ class SkyworkR1VChatModel(nn.Module, SupportsMultiModal, SupportsPP):
405
return self.language_model.compute_logits(hidden_states)
406
407
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
384
- skip_prefixes = [
385
- "action_embed",
386
- "temporal_embed",
387
- "track_embed",
388
- "track_embed_decoder",
389
- "box_token",
390
- "cg_criterion",
391
- "cg_model",
392
- "loc_encoder",
393
- "loc_decoder",
394
- "sam",
395
- "temporal_token",
396
- "track_token",
397
- ]
398
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
399
- return loader.load_weights(weights)
408
+ loader = AutoWeightsLoader(self)
409
+ return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/transformers/base.py
-6
@@ -122,10 +122,6 @@ class Base(
122
self.tp_group = get_tp_group()
123
124
# Attrs for weight loading (see self.load_weights)
125
- self.skip_prefixes: list[str] = []
126
- """Skip loading weights whose qualname starts with these prefixes."""
127
- self.skip_substrs: list[str] = []
128
- """Skip loading weights whose qualname contains these substrings."""
125
self.ignore_unexpected_prefixes: list[str] = []
126
"""Ignore unexpected weights whose qualname starts with these prefixes."""
127
self.ignore_unexpected_suffixes: list[str] = []
@@ -731,8 +727,6 @@ class Base(
727
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
728
loader = AutoWeightsLoader(
729
self,
734
- skip_prefixes=self.skip_prefixes,
735
- skip_substrs=self.skip_substrs,
730
ignore_unexpected_prefixes=self.ignore_unexpected_prefixes,
731
ignore_unexpected_suffixes=self.ignore_unexpected_suffixes,
732
)
vllm/model_executor/models/transformers/legacy.py
+15
-17
@@ -30,26 +30,24 @@ class LegacyMixin:
30
def __init__(self, *, vllm_config: "VllmConfig", prefix: str = ""):
31
super().__init__(vllm_config=vllm_config, prefix=prefix)
32
33
- # Skip unsupported/unwanted output embeddings layers
34
- self.skip_prefixes.extend(
35
- [
36
- "model.lm_head.",
37
- "model.predictions.",
38
- "model.qa_outputs.",
39
- "model.embeddings_project.",
40
- "model.discriminator_predictions.",
41
- ]
33
+ # Drop unsupported/unwanted output embeddings layers.
34
+ self.hf_to_vllm_mapper.orig_to_new_prefix.update(
35
+ {
36
+ "model.lm_head.": None,
37
+ "model.predictions.": None,
38
+ "model.qa_outputs.": None,
39
+ "model.embeddings_project.": None,
40
+ "model.discriminator_predictions.": None,
41
+ }
42
)
43
44
- # Some encoder models have the position_ids buffer in the checkpoint.
45
- # vLLM will always pass position_ids as an argument, so we skip loading
46
- # the buffer if it exists
47
- self.skip_substrs.append("position_ids")
44
+ # Some encoder models have the position_ids buffer in the checkpoint. vLLM will
45
+ # always pass position_ids as an argument, so we drop the buffer if it exists.
46
+ self.hf_to_vllm_mapper.orig_to_new_substr["position_ids"] = None
47
49
- # Some encoder models have the bias of the final classifier layer
50
- # in the checkpoint. vLLM does not use this bias, so we skip loading
51
- # it if it exists
52
- self.skip_substrs.append("score.bias")
48
+ # Some encoder models have the bias of the final classifier layer in the
49
+ # checkpoint. vLLM does not use this bias, so we drop it if it exists.
50
+ self.hf_to_vllm_mapper.orig_to_new_substr["score.bias"] = None
51
52
# roberta-like models an extra padding in positions.
53
# FIXME(Isotr0py): This is quite hacky for roberta edge case,
vllm/model_executor/models/utils.py
+35
-37
@@ -160,14 +160,26 @@ class WeightsMapper:
160
if (out_name := self._map_name(name)) is not None
161
}
162
163
- def get_unstacked_mapper(self) -> "WeightsMapper":
164
- """Mapper variant that drops stacked maps, keeping all genuine renames/prefixes.
165
-
166
- Consumers that reference the checkpoint's *unstacked* module names (LoRA name
167
- parsing and the quantization config's layer lists) need the constituent names
168
- (e.g. `q_proj`) to survive rather than being rewritten to the stacked vLLM name
169
- (`qkv_proj`)."""
170
- return replace(self, orig_to_new_stacked={})
163
+ def get_rename_mapper(self) -> "WeightsMapper":
164
+ """Mapper variant keeping only the renames.
165
+
166
+ This is what consumers that *name* modules rather than load them need:
167
+ LoRA name parsing and the quantization config's layer lists.
168
+
169
+ Stacked maps are dropped so that constituent names (e.g. `q_proj`) survive
170
+ rather than being rewritten to the stacked vLLM name (`qkv_proj`). Mappings to
171
+ `None` are dropped because "do not load this weight" is meaningless to such a
172
+ consumer, and applying it would silently shrink a quantization config's ignore
173
+ list or make LoRA name parsing fail."""
174
+ remove_none = lambda d: {k: v for k, v in d.items() if v is not None}
175
+ return replace(
176
+ self,
177
+ orig_to_new_regex=remove_none(self.orig_to_new_regex),
178
+ orig_to_new_substr=remove_none(self.orig_to_new_substr),
179
+ orig_to_new_stacked={},
180
+ orig_to_new_prefix=remove_none(self.orig_to_new_prefix),
181
+ orig_to_new_suffix=remove_none(self.orig_to_new_suffix),
182
+ )
183
184
185
def _get_tied_embedding_params(module: nn.Module) -> dict[str, str]:
@@ -201,32 +213,28 @@ class AutoWeightsLoader:
213
"""
214
215
# Models trained using early version ColossalAI or quantized by
204
- # GPTQModel may include these tensors in checkpoint. Skip them.
205
- ROTARY_EMBEDS_UNUSED_WEIGHTS = [
206
- "rotary_pos_emb.inv_freq",
207
- "rotary_emb.inv_freq",
208
- "rotary_emb.cos_cached",
209
- "rotary_emb.sin_cached",
210
- ]
216
+ # GPTQModel may include these tensors in checkpoint. Drop them.
217
+ REMOVE_UNUSED_ROTARY_EMBEDS_MAPPER = WeightsMapper(
218
+ orig_to_new_substr={
219
+ "rotary_pos_emb.inv_freq": None,
220
+ "rotary_emb.inv_freq": None,
221
+ "rotary_emb.cos_cached": None,
222
+ "rotary_emb.sin_cached": None,
223
+ }
224
+ )
225
226
def __init__(
227
self,
228
module: nn.Module,
229
*,
216
- skip_prefixes: list[str] | None = None,
217
- skip_substrs: list[str] | None = None,
230
ignore_unexpected_prefixes: list[str] | None = None,
231
ignore_unexpected_suffixes: list[str] | None = None,
232
) -> None:
233
super().__init__()
234
235
self.module = module
224
- self.skip_prefixes = skip_prefixes or []
225
- self.skip_substrs = skip_substrs or []
236
self.ignore_unexpected_prefixes = ignore_unexpected_prefixes or []
237
self.ignore_unexpected_suffixes = ignore_unexpected_suffixes or []
228
- # update default skip_substrs
229
- self.skip_substrs += self.ROTARY_EMBEDS_UNUSED_WEIGHTS
238
239
# Weight tying makes two qualnames point at the same `nn.Parameter`
240
# (e.g. `lm_head.weight` and `model.embed_tokens.weight`). Loading both
@@ -265,11 +273,7 @@ class AutoWeightsLoader:
273
return ".".join((prefix, rest))
274
275
def _can_skip(self, qualname: str) -> bool:
268
- return (
269
- qualname in self.aliased_params
270
- or any(qualname.startswith(p) for p in self.skip_prefixes)
271
- or any(substr in qualname for substr in self.skip_substrs)
272
- )
276
+ return qualname in self.aliased_params
277
278
def _can_ignore_unexpected(self, qualname: str) -> bool:
279
iup = (qualname.startswith(p) for p in self.ignore_unexpected_prefixes)
@@ -375,11 +379,6 @@ class AutoWeightsLoader:
379
prefix = self._get_qualname(base_prefix, child_prefix)
380
381
if child_prefix in child_modules:
378
- if self._can_skip(prefix + "."):
379
- logger.debug("Skipping module %s", prefix)
380
-
381
- continue
382
-
382
yield from self._load_module(
383
prefix, child_modules[child_prefix], child_weights
384
)
@@ -393,9 +392,7 @@ class AutoWeightsLoader:
392
prefix, child_params[child_prefix], child_weights
393
)
394
else:
396
- can_skip_module = self._can_skip(prefix + ".")
397
- can_skip_param = self._can_skip(prefix)
398
- if can_skip_module or can_skip_param:
395
+ if self._can_skip(prefix):
396
logger.debug("Skipping missing %s", prefix)
397
398
continue
@@ -429,18 +426,19 @@ class AutoWeightsLoader:
426
# Ignore unexpected biases (typically from GPTQ models)
427
self.ignore_unexpected_suffixes.append(".bias")
428
429
+ mapper = mapper or WeightsMapper()
430
# Many models store quant_config in the base model instead of the causal model.
431
# We look at the causal model's direct children for this reason.
432
modules = (self.module, *self.module.children())
433
iterator = (m.quant_config for m in modules if hasattr(m, "quant_config"))
434
if quant_config := next(iterator, None):
435
# Get mappings and ignore prefixes for KV cache quantization scales
438
- mapper = mapper or WeightsMapper()
436
mapper |= quant_config.get_cache_scale_mapper()
437
ignore_unexpected_suffixes = quant_config._ignore_unexpected_suffixes
438
self.ignore_unexpected_suffixes.extend(ignore_unexpected_suffixes)
442
- if mapper is not None:
443
- weights = mapper.apply(weights)
439
+ mapper |= self.REMOVE_UNUSED_ROTARY_EMBEDS_MAPPER
440
+
441
+ weights = mapper.apply(weights)
442
weights = self._filter_skipped(weights)
443
444
autoloaded_weights = set(self._load_module("", self.module, weights))
vllm/model_executor/models/whisper.py
+2
-1
@@ -838,6 +838,7 @@ class WhisperForConditionalGeneration(
838
".encoder_attn.k_proj": (".encoder_attn.kv_proj", 0),
839
".encoder_attn.v_proj": (".encoder_attn.kv_proj", 1),
840
},
841
+ orig_to_new_prefix={"proj_out.": None},
842
)
843
844
# Whisper only supports audio-conditioned generation.
@@ -1048,7 +1049,7 @@ class WhisperForConditionalGeneration(
1049
return logits
1050
1051
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1051
- loader = AutoWeightsLoader(self, skip_prefixes=["proj_out."])
1052
+ loader = AutoWeightsLoader(self)
1053
1054
# add fake zeros bias for k_proj to state_dict
1055
weights = _create_fake_bias_for_k_proj(weights, ".k_proj.weight")
vllm/models/deepseek_v4/amd/model.py
+4
-3
@@ -947,11 +947,12 @@ def _make_deepseek_v4_weights_mapper(
947
# When shared experts are fused into the routed MXFP4 grouped GEMM, the
948
# shared_experts tensors are redirected to routed expert slots ; leave
949
# their names untouched here.
950
- substr_map = (
950
+ orig_to_new_substr: dict[str, str | None] = (
951
{}
952
if fuse_shared_experts
953
else {".shared_experts.w2": ".shared_experts.down_proj"}
954
)
955
+ orig_to_new_substr["mtp."] = None
956
return WeightsMapper(
957
orig_to_new_prefix={
958
"layers.": "model.layers.",
@@ -967,7 +968,7 @@ def _make_deepseek_v4_weights_mapper(
968
".ffn.gate.bias": ".ffn.gate.e_score_correction_bias",
969
".input_scale": ".input_scale_2",
970
},
970
- orig_to_new_substr=substr_map,
971
+ orig_to_new_substr=orig_to_new_substr,
972
)
973
974
@@ -1038,7 +1039,7 @@ class DeepseekV4ForCausalLM(nn.Module, SupportsPP, SupportsEagle3):
1039
return getattr(self.model, "_mtp_hidden_buffer", None)
1040
1041
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1041
- loader = AutoWeightsLoader(self, skip_substrs=["mtp."])
1042
+ loader = AutoWeightsLoader(self)
1043
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1044
1045
def process_weights_after_loading(self) -> None:
vllm/models/deepseek_v4/nvidia/model.py
+2
-1
@@ -1392,6 +1392,7 @@ def _make_deepseek_v4_weights_mapper(expert_dtype: str) -> WeightsMapper:
1392
},
1393
orig_to_new_substr={
1394
".shared_experts.w2": ".shared_experts.down_proj",
1395
+ "mtp.": None,
1396
},
1397
)
1398
@@ -1517,7 +1518,7 @@ class DeepseekV4ForCausalLM(
1518
return getattr(self.model, "_mtp_hidden_buffer", None)
1519
1520
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1520
- loader = AutoWeightsLoader(self, skip_substrs=["mtp."])
1521
+ loader = AutoWeightsLoader(self)
1522
loaded_params = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1523
self.process_weights_after_loading()
1524
return loaded_params
vllm/models/deepseek_v4/xpu/model.py
+2
-1
@@ -1299,6 +1299,7 @@ def _make_deepseek_v4_weights_mapper(expert_dtype: str) -> WeightsMapper:
1299
},
1300
orig_to_new_substr={
1301
".shared_experts.w2": ".shared_experts.down_proj",
1302
+ "mtp.": None,
1303
},
1304
)
1305
@@ -1364,7 +1365,7 @@ class DeepseekV4ForCausalLM(nn.Module, SupportsPP, SupportsEagle3):
1365
return getattr(self.model, "_mtp_hidden_buffer", None)
1366
1367
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
1367
- loader = AutoWeightsLoader(self, skip_substrs=["mtp."])
1368
+ loader = AutoWeightsLoader(self)
1369
loaded_params = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1370
self.model.finalize_mega_moe_weights()
1371
return loaded_params
vllm/models/dots3_note/nvidia/multimodal.py
+11
-6
@@ -141,6 +141,16 @@ class Dots3NoteForCausalLM(nn.Module, SupportsMultiModal, SupportsPP):
141
self.language_model.make_empty_intermediate_tensors
142
)
143
144
+ orig_to_new_prefix = dict[str, None]()
145
+ if self.visual is None:
146
+ orig_to_new_prefix["visual."] = None
147
+ if self.audio_tower is None:
148
+ orig_to_new_prefix["audio_tower."] = None
149
+ if orig_to_new_prefix:
150
+ self.hf_to_vllm_mapper = self.hf_to_vllm_mapper | WeightsMapper(
151
+ orig_to_new_prefix=orig_to_new_prefix
152
+ )
153
+
154
def _process_image_input(
155
self,
156
pixel_values: torch.Tensor,
@@ -283,12 +293,7 @@ class Dots3NoteForCausalLM(nn.Module, SupportsMultiModal, SupportsPP):
293
return self.language_model.compute_logits(hidden_states)
294
295
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
286
- skip_prefixes = []
287
- if self.visual is None:
288
- skip_prefixes.append("visual.")
289
- if self.audio_tower is None:
290
- skip_prefixes.append("audio_tower.")
291
- return AutoWeightsLoader(self, skip_prefixes=skip_prefixes).load_weights(
296
+ return AutoWeightsLoader(self).load_weights(
297
weights,
298
mapper=self.hf_to_vllm_mapper,
299
)
vllm/models/inkling/amd/model.py
+3
-2
@@ -656,8 +656,9 @@ def _load_inkling_weights(
656
657
yield name, weight
658
659
- loader = AutoWeightsLoader(module, skip_prefixes=["model.mtp."])
660
- loaded |= loader.load_weights(_iter_loadable_weights())
659
+ mapper = WeightsMapper(orig_to_new_prefix={"model.mtp.": None})
660
+ loader = AutoWeightsLoader(module)
661
+ loaded |= loader.load_weights(_iter_loadable_weights(), mapper=mapper)
662
663
# Post-load MoE fixups (default input scales, zeroed EP-padding experts).
664
for moe_name, moe in moe_modules.items():
vllm/models/inkling/nvidia/model.py
+3
-2
@@ -693,8 +693,9 @@ def _load_inkling_weights(
693
694
# The release checkpoint also carries auxiliary prediction-head weights;
695
# they are not part of the causal LM served by this implementation.
696
- loader = AutoWeightsLoader(module, skip_prefixes=["model.mtp."])
697
- loaded |= loader.load_weights(_iter_loadable_weights())
696
+ mapper = WeightsMapper(orig_to_new_prefix={"model.mtp.": None})
697
+ loader = AutoWeightsLoader(module)
698
+ loaded |= loader.load_weights(_iter_loadable_weights(), mapper=mapper)
699
700
# Post-load MoE fixups (default input scales, zeroed EP-padding experts).
701
for moe_name, moe in moe_modules.items():
vllm/models/kimi_k3/nvidia/dspark_mla.py
+8
-8
@@ -399,9 +399,14 @@ class K3DSparkForCausalLM(nn.Module):
399
has_own_embed_tokens = False
400
has_own_lm_head = False
401
draft_id_to_target_id = None
402
- checkpoint_skip_substrs = ("confidence_head", "embed_tokens", "lm_head")
403
-
402
hf_to_vllm_mapper = WeightsMapper(
403
+ # confidence_head is training-only. The frozen target embedding and LM
404
+ # head are shared after this draft-specific checkpoint is loaded.
405
+ orig_to_new_substr={
406
+ "confidence_head": None,
407
+ "embed_tokens": None,
408
+ "lm_head": None,
409
+ },
410
orig_to_new_prefix={"": "model."},
411
orig_to_new_stacked={
412
".gate_proj": (".gate_up_proj", 0),
@@ -477,12 +482,7 @@ class K3DSparkForCausalLM(nn.Module):
482
return self.model.markov_head.bias(markov_embed, self.logits_processor)
483
484
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
480
- # confidence_head is training-only. The frozen target embedding and LM
481
- # head are shared after this draft-specific checkpoint is loaded.
482
- loader = AutoWeightsLoader(
483
- self,
484
- skip_substrs=list(self.checkpoint_skip_substrs),
485
- )
485
+ loader = AutoWeightsLoader(self)
486
# read: 1. all weights. 2. context kv weights
487
weights = _duplicate_context_kv_weights(weights, len(self.model.layers))
488
loaded_weights = loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)