A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 15, 09:45 UTC
[Misc] Allow `AutoWeightsLoader` to skip loading weights with specific substr in name (#18358)
Signed-off-by: Isotr0py <2037008807@qq.com>
Isotr0py committed
May 20, 2025 at 11:20 UTC
f07a673eb2fc4eb6f4e18eadb3512702877f5c3a
18 files changed
+116
-109
tests/models/test_utils.py
+70
@@ -77,3 +77,73 @@ def test_module_with_child_containing_batchnorm_can_autoload():
77
assert torch.all(
78
new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
79
assert new_mod.nested_mod.bn.num_batches_tracked.item() == 1
80
+
81
+
82
+def test_module_skip_prefix():
83
+ """Ensure the auto weight loader can skip prefix."""
84
+ mod = ModuleWithNestedBatchNorm()
85
+ # Run some data through the module with batchnorm
86
+ mod(torch.Tensor([[1, 2], [3, 4]]))
87
+
88
+ # Try to load the weights to a new instance
89
+ def weight_generator():
90
+ # weights needed to be filtered out
91
+ redundant_weights = {
92
+ "prefix.bn.weight": torch.Tensor([1, 2]),
93
+ "prefix.bn.bias": torch.Tensor([3, 4]),
94
+ }
95
+ yield from (mod.state_dict() | redundant_weights).items()
96
+
97
+ new_mod = ModuleWithNestedBatchNorm()
98
+
99
+ assert not torch.all(
100
+ new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean)
101
+ assert not torch.all(
102
+ new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
103
+ assert new_mod.nested_mod.bn.num_batches_tracked.item() == 0
104
+
105
+ loader = AutoWeightsLoader(new_mod, skip_prefixes=["prefix."])
106
+ loader.load_weights(weight_generator())
107
+
108
+ # Ensure the stats are updated
109
+ assert torch.all(
110
+ new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean)
111
+ assert torch.all(
112
+ new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
113
+ assert new_mod.nested_mod.bn.num_batches_tracked.item() == 1
114
+
115
+
116
+def test_module_skip_substr():
117
+ """Ensure the auto weight loader can skip prefix."""
118
+ mod = ModuleWithNestedBatchNorm()
119
+ # Run some data through the module with batchnorm
120
+ mod(torch.Tensor([[1, 2], [3, 4]]))
121
+
122
+ # Try to load the weights to a new instance
123
+ def weight_generator():
124
+ # weights needed to be filtered out
125
+ redundant_weights = {
126
+ "nested_mod.0.substr.weight": torch.Tensor([1, 2]),
127
+ "nested_mod.0.substr.bias": torch.Tensor([3, 4]),
128
+ "nested_mod.substr.weight": torch.Tensor([1, 2]),
129
+ "nested_mod.substr.bias": torch.Tensor([3, 4]),
130
+ }
131
+ yield from (mod.state_dict() | redundant_weights).items()
132
+
133
+ new_mod = ModuleWithNestedBatchNorm()
134
+
135
+ assert not torch.all(
136
+ new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean)
137
+ assert not torch.all(
138
+ new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
139
+ assert new_mod.nested_mod.bn.num_batches_tracked.item() == 0
140
+
141
+ loader = AutoWeightsLoader(new_mod, skip_substrs=["substr."])
142
+ loader.load_weights(weight_generator())
143
+
144
+ # Ensure the stats are updated
145
+ assert torch.all(
146
+ new_mod.nested_mod.bn.running_mean == mod.nested_mod.bn.running_mean)
147
+ assert torch.all(
148
+ new_mod.nested_mod.bn.running_var == mod.nested_mod.bn.running_var)
149
+ assert new_mod.nested_mod.bn.num_batches_tracked.item() == 1
vllm/model_executor/models/granite.py
+6
-10
@@ -478,18 +478,14 @@ class GraniteForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
478
479
def load_weights(self, weights: Iterable[tuple[str,
480
torch.Tensor]]) -> set[str]:
481
- skip_prefixes = [
482
- "rotary_emb.inv_freq",
483
- # Models trained using ColossalAI may include these tensors in
484
- # the checkpoint. Skip them.
485
- "rotary_emb.cos_cached",
486
- "rotary_emb.sin_cached",
487
- ]
481
# With tie_word_embeddings, we can skip lm_head.weight
482
# The weight might appear unnecessarily in the files if the model is
483
# processed with quantization, LoRA, fine-tuning, etc.
491
- if self.config.tie_word_embeddings:
492
- skip_prefixes.append("lm_head.weight")
484
+ skip_prefixes = (["lm_head."]
485
+ if self.config.tie_word_embeddings else None)
486
494
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
487
+ loader = AutoWeightsLoader(
488
+ self,
489
+ skip_prefixes=skip_prefixes,
490
+ )
491
return loader.load_weights(weights)
vllm/model_executor/models/grok1.py
+6
-4
@@ -550,10 +550,12 @@ class Grok1ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
550
551
def load_weights(self, weights: Iterable[tuple[str,
552
torch.Tensor]]) -> set[str]:
553
- skip_prefixes = ["rotary_emb.inv_freq"]
553
# Skip lm_head when tie_word_embeddings is True
555
- if self.config.tie_word_embeddings:
556
- skip_prefixes.append("lm_head")
554
+ skip_prefixes = (["lm_head"]
555
+ if self.config.tie_word_embeddings else None)
556
558
- loader = AutoWeightsLoader(self, skip_prefixes=skip_prefixes)
557
+ loader = AutoWeightsLoader(
558
+ self,
559
+ skip_prefixes=skip_prefixes,
560
+ )
561
return loader.load_weights(weights)
vllm/model_executor/models/mixtral.py
+1
-1
@@ -482,5 +482,5 @@ class MixtralForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
482
483
def load_weights(self, weights: Iterable[tuple[str,
484
torch.Tensor]]) -> set[str]:
485
- loader = AutoWeightsLoader(self, skip_prefixes=["rotary_emb.inv_freq"])
485
+ loader = AutoWeightsLoader(self)
486
return loader.load_weights(weights)
vllm/model_executor/models/mixtral_quant.py
+1
-4
@@ -447,8 +447,5 @@ class MixtralForCausalLM(nn.Module, SupportsPP):
447
448
def load_weights(self, weights: Iterable[tuple[str,
449
torch.Tensor]]) -> set[str]:
450
- loader = AutoWeightsLoader(
451
- self,
452
- skip_prefixes=(["rotary_emb.inv_freq"]),
453
- )
450
+ loader = AutoWeightsLoader(self)
451
return loader.load_weights(weights)
vllm/model_executor/models/nemotron.py
+1
-10
@@ -502,14 +502,5 @@ class NemotronForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
502
503
def load_weights(self, weights: Iterable[tuple[str,
504
torch.Tensor]]) -> set[str]:
505
- loader = AutoWeightsLoader(
506
- self,
507
- skip_prefixes=([
508
- "rotary_emb.inv_freq",
509
- # Models trained using ColossalAI may include these tensors in
510
- # the checkpoint. Skip them.
511
- "rotary_emb.cos_cached",
512
- "rotary_emb.sin_cached"
513
- ]),
514
- )
505
+ loader = AutoWeightsLoader(self)
506
return loader.load_weights(weights)
vllm/model_executor/models/olmo.py
+2
-14
@@ -382,19 +382,7 @@ class OlmoForCausalLM(nn.Module, SupportsPP):
382
torch.Tensor]]) -> set[str]:
383
loader = AutoWeightsLoader(
384
self,
385
- skip_prefixes=([
386
- "rotary_emb.inv_freq",
387
- # Models trained using ColossalAI may include these tensors in
388
- # the checkpoint. Skip them.
389
- "rotary_emb.cos_cached",
390
- "rotary_emb.sin_cached",
391
- "lm_head.weight"
392
- ] if self.config.tie_word_embeddings else [
393
- "rotary_emb.inv_freq",
394
- # Models trained using ColossalAI may include these tensors in
395
- # the checkpoint. Skip them.
396
- "rotary_emb.cos_cached",
397
- "rotary_emb.sin_cached"
398
- ]),
385
+ skip_prefixes=(["lm_head.weight"]
386
+ if self.config.tie_word_embeddings else None),
387
)
388
return loader.load_weights(weights)
vllm/model_executor/models/olmo2.py
+2
-14
@@ -403,19 +403,7 @@ class Olmo2ForCausalLM(nn.Module, SupportsPP):
403
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
404
loader = AutoWeightsLoader(
405
self,
406
- skip_prefixes=([
407
- "rotary_emb.inv_freq",
408
- # Models trained using ColossalAI may include these tensors in
409
- # the checkpoint. Skip them.
410
- "rotary_emb.cos_cached",
411
- "rotary_emb.sin_cached",
412
- "lm_head.weight"
413
- ] if self.config.tie_word_embeddings else [
414
- "rotary_emb.inv_freq",
415
- # Models trained using ColossalAI may include these tensors in
416
- # the checkpoint. Skip them.
417
- "rotary_emb.cos_cached",
418
- "rotary_emb.sin_cached"
419
- ]),
406
+ skip_prefixes=(["lm_head.weight"]
407
+ if self.config.tie_word_embeddings else None),
408
)
409
return loader.load_weights(weights)
vllm/model_executor/models/olmoe.py
+1
-4
@@ -442,8 +442,5 @@ class OlmoeForCausalLM(nn.Module, SupportsPP):
442
443
def load_weights(self, weights: Iterable[tuple[str,
444
torch.Tensor]]) -> set[str]:
445
- loader = AutoWeightsLoader(
446
- self,
447
- skip_prefixes=["rotary_emb.inv_freq"],
448
- )
445
+ loader = AutoWeightsLoader(self)
446
return loader.load_weights(weights)
vllm/model_executor/models/orion.py
+1
-10
@@ -344,14 +344,5 @@ class OrionForCausalLM(nn.Module, SupportsPP):
344
345
def load_weights(self, weights: Iterable[tuple[str,
346
torch.Tensor]]) -> set[str]:
347
- loader = AutoWeightsLoader(
348
- self,
349
- skip_prefixes=([
350
- "rotary_emb.inv_freq",
351
- # Models trained using ColossalAI may include these tensors in
352
- # the checkpoint. Skip them.
353
- "rotary_emb.cos_cached",
354
- "rotary_emb.sin_cached"
355
- ]),
356
- )
347
+ loader = AutoWeightsLoader(self)
348
return loader.load_weights(weights)
vllm/model_executor/models/phi4mm.py
+1
-3
@@ -1228,9 +1228,7 @@ class Phi4MMForCausalLM(nn.Module, SupportsLoRA, SupportsMultiModal):
1228
1229
def load_weights(self, weights: Iterable[tuple[str,
1230
torch.Tensor]]) -> None:
1231
- weights = ((name, data) for name, data in weights
1232
- if "lora" not in name)
1233
- loader = AutoWeightsLoader(self)
1231
+ loader = AutoWeightsLoader(self, skip_substrs=["lora"])
1232
return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
1233
1234
def get_mm_mapping(self) -> MultiModelKeys:
vllm/model_executor/models/phimoe.py
+1
-4
@@ -660,8 +660,5 @@ class PhiMoEForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
660
661
def load_weights(self, weights: Iterable[tuple[str,
662
torch.Tensor]]) -> set[str]:
663
- loader = AutoWeightsLoader(
664
- self,
665
- skip_prefixes=(["rotary_emb.inv_freq"]),
666
- )
663
+ loader = AutoWeightsLoader(self)
664
return loader.load_weights(weights)
vllm/model_executor/models/qwen2_moe.py
+1
-4
@@ -535,8 +535,5 @@ class Qwen2MoeForCausalLM(nn.Module, SupportsPP):
535
536
def load_weights(self, weights: Iterable[tuple[str,
537
torch.Tensor]]) -> set[str]:
538
- loader = AutoWeightsLoader(
539
- self,
540
- skip_prefixes=(["rotary_emb.inv_freq"]),
541
- )
538
+ loader = AutoWeightsLoader(self)
539
return loader.load_weights(weights)
vllm/model_executor/models/qwen3_moe.py
+1
-4
@@ -530,8 +530,5 @@ class Qwen3MoeForCausalLM(nn.Module, SupportsPP):
530
531
def load_weights(self, weights: Iterable[tuple[str,
532
torch.Tensor]]) -> set[str]:
533
- loader = AutoWeightsLoader(
534
- self,
535
- skip_prefixes=(["rotary_emb.inv_freq"]),
536
- )
533
+ loader = AutoWeightsLoader(self)
534
return loader.load_weights(weights)
vllm/model_executor/models/solar.py
+1
-10
@@ -500,14 +500,5 @@ class SolarForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
500
501
def load_weights(self, weights: Iterable[tuple[str,
502
torch.Tensor]]) -> set[str]:
503
- loader = AutoWeightsLoader(
504
- self,
505
- skip_prefixes=([
506
- "rotary_emb.inv_freq",
507
- # Models trained using ColossalAI may include these tensors in
508
- # the checkpoint. Skip them.
509
- "rotary_emb.cos_cached",
510
- "rotary_emb.sin_cached"
511
- ]),
512
- )
503
+ loader = AutoWeightsLoader(self)
504
return loader.load_weights(weights)
vllm/model_executor/models/stablelm.py
+1
-9
@@ -338,13 +338,5 @@ class StablelmForCausalLM(nn.Module, SupportsPP):
338
339
def load_weights(self, weights: Iterable[tuple[str,
340
torch.Tensor]]) -> set[str]:
341
- loader = AutoWeightsLoader(
342
- self,
343
- # Models trained using ColossalAI may include these tensors in
344
- # the checkpoint. Skip them.
345
- skip_prefixes=[
346
- "rotary_emb.inv_freq", "rotary_emb.cos_cached",
347
- "rotary_emb.sin_cached"
348
- ],
349
- )
341
+ loader = AutoWeightsLoader(self)
342
return loader.load_weights(weights)
vllm/model_executor/models/starcoder2.py
+2
-3
@@ -349,8 +349,7 @@ class Starcoder2ForCausalLM(nn.Module, SupportsPP):
349
self,
350
# Models trained using ColossalAI may include these tensors in
351
# the checkpoint. Skip them.
352
- skip_prefixes=([
353
- "rotary_emb.inv_freq", "lm_head.weight"
354
- ] if self.config.tie_word_embeddings else ["rotary_emb.inv_freq"]),
352
+ skip_prefixes=(["lm_head.weight"]
353
+ if self.config.tie_word_embeddings else None),
354
)
355
return loader.load_weights(weights)
vllm/model_executor/models/utils.py
+17
-1
@@ -80,18 +80,30 @@ class AutoWeightsLoader:
80
environment variable ``VLLM_LOGGING_LEVEL=DEBUG``.
81
"""
82
83
+ # Models trained using early version ColossalAI
84
+ # may include these tensors in checkpoint. Skip them.
85
+ ROTARY_EMBEDS_UNUSED_WEIGHTS = [
86
+ "rotary_emb.inv_freq",
87
+ "rotary_emb.cos_cached",
88
+ "rotary_emb.sin_cached",
89
+ ]
90
+
91
def __init__(
92
self,
93
module: nn.Module,
94
*,
95
skip_prefixes: Optional[list[str]] = None,
96
+ skip_substrs: Optional[list[str]] = None,
97
ignore_unexpected_prefixes: Optional[list[str]] = None,
98
) -> None:
99
super().__init__()
100
101
self.module = module
102
self.skip_prefixes = skip_prefixes or []
103
+ self.skip_substrs = skip_substrs or []
104
self.ignore_unexpected_prefixes = ignore_unexpected_prefixes or []
105
+ # update default skip_substrs
106
+ self.skip_substrs += self.ROTARY_EMBEDS_UNUSED_WEIGHTS
107
108
def _groupby_prefix(
109
self,
@@ -119,7 +131,8 @@ class AutoWeightsLoader:
131
return ".".join((prefix, rest))
132
133
def _can_skip(self, qualname: str) -> bool:
122
- return any(qualname.startswith(p) for p in self.skip_prefixes)
134
+ return (any(qualname.startswith(p) for p in self.skip_prefixes)
135
+ or any(substr in qualname for substr in self.skip_substrs))
136
137
def _can_ignore_unexpected(self, qualname: str) -> bool:
138
return any(
@@ -257,6 +270,9 @@ class AutoWeightsLoader:
270
) -> set[str]:
271
if mapper is not None:
272
weights = mapper.apply(weights)
273
+ # filter out weights with first-prefix/substr to skip in name
274
+ weights = ((name, weight) for name, weight in weights
275
+ if not self._can_skip(name))
276
277
autoloaded_weights = set(self._load_module("", self.module, weights))
278
return autoloaded_weights