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

A high-throughput and memory-efficient inference and serving engine for LLMs

Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git

Synced Nov 10, 07:45 UTC

[Model] Avoid hardcoding pooling type (#32119)

Signed-off-by: DarkLight1337 <tlleungac@connect.ust.hk>

Cyrus Leung committed Jan 12, 2026 at 13:28 UTC 9101dc756c14b6467c192e7bfc67036f40d76320
6 files changed +47 -22
vllm/model_executor/models/bert.py
+10 -4
@@ -25,11 +25,11 @@ from vllm.model_executor.layers.pooler import (
25 PoolingParamsUpdate,
26 )
27 from vllm.model_executor.layers.pooler.seqwise import (
28 - CLSPool,
28 SequencePooler,
29 SequencePoolerHeadOutput,
30 SequencePoolerOutput,
31 SequencePoolingMethodOutput,
32 + get_seq_pooling_method,
33 )
34 from vllm.model_executor.layers.pooler.tokwise import (
35 pooler_for_token_classify,
@@ -94,9 +94,9 @@ class BertEmbedding(nn.Module):
94
95
96 class BertPooler(SequencePooler):
97 - def __init__(self, config: BertConfig):
97 + def __init__(self, config: BertConfig, pooler_config: PoolerConfig):
98 super().__init__(
99 - pooling=CLSPool(),
99 + pooling=get_seq_pooling_method(pooler_config.seq_pooling_type),
100 head=self.head,
101 )
102
@@ -450,7 +450,11 @@ class BertPoolingModel(BertModel):
450 )
451
452 config = vllm_config.model_config.hf_config
453 - self.pooler = BertPooler(config)
453 +
454 + pooler_config = vllm_config.model_config.pooler_config
455 + assert pooler_config is not None
456 +
457 + self.pooler = BertPooler(config, pooler_config)
458
459 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
460 other_weights, loaded_stacked_params = self._load_weights(weights)
@@ -711,6 +715,8 @@ class BertSpladeSparseEmbeddingModel(BertEmbeddingModel):
715 layer_norm_eps=getattr(cfg, "layer_norm_eps", 1e-12),
716 )
717
718 + # None of vLLM's built-in sequence pooling types are
719 + # applicable so it is overwritten by SPLADESparsePooler
720 pooling_mode = getattr(self, "_splade_pooling", "max")
721
722 cls_id = getattr(cfg, "cls_token_id", None)
vllm/model_executor/models/bert_with_rope.py
+9 -1
@@ -453,6 +453,7 @@ class BertWithRope(nn.Module, SupportsQuant):
453 add_pooling_layer: bool = False,
454 ):
455 super().__init__()
456 +
457 self.vllm_config = vllm_config
458 self.add_pooling_layer = add_pooling_layer
459 self.config = vllm_config.model_config.hf_config
@@ -463,7 +464,14 @@ class BertWithRope(nn.Module, SupportsQuant):
464 rotary_kwargs=self.config.rotary_kwargs,
465 prefix=f"{prefix}.encoder",
466 )
466 - self.pooler = BertPooler(self.config) if add_pooling_layer else None
467 +
468 + if add_pooling_layer:
469 + pooler_config = vllm_config.model_config.pooler_config
470 + assert pooler_config is not None
471 +
472 + self.pooler = BertPooler(self.config, pooler_config)
473 + else:
474 + self.pooler = None
475
476 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
477 return self.embeddings(input_ids)
vllm/model_executor/models/gritlm.py
+9 -4
@@ -5,7 +5,7 @@ from collections.abc import Set
5 import numpy as np
6 import torch
7
8 -from vllm.config import ModelConfig, VllmConfig
8 +from vllm.config import ModelConfig, PoolerConfig, VllmConfig
9 from vllm.logger import init_logger
10 from vllm.model_executor.layers.pooler import (
11 DispatchPooler,
@@ -17,6 +17,7 @@ from vllm.model_executor.layers.pooler.seqwise import (
17 SequencePoolerHeadOutput,
18 SequencePoolingMethod,
19 SequencePoolingMethodOutput,
20 + get_seq_pooling_method,
21 )
22 from vllm.model_executor.layers.pooler.tokwise import pooler_for_token_embed
23 from vllm.model_executor.models.llama import LlamaForCausalLM
@@ -177,9 +178,13 @@ class GritLMMeanPool(SequencePoolingMethod):
178
179
180 class GritLMPooler(SequencePooler):
180 - def __init__(self, model_config: ModelConfig):
181 + def __init__(self, model_config: ModelConfig, pooler_config: PoolerConfig):
182 super().__init__(
182 - pooling=GritLMMeanPool(model_config),
183 + pooling=(
184 + GritLMMeanPool(model_config)
185 + if pooler_config.seq_pooling_type == "MEAN"
186 + else get_seq_pooling_method(pooler_config.seq_pooling_type)
187 + ),
188 head=self.head,
189 )
190
@@ -235,6 +240,6 @@ class GritLM(LlamaForCausalLM):
240 self.pooler = DispatchPooler(
241 {
242 "token_embed": pooler_for_token_embed(pooler_config),
238 - "embed": GritLMPooler(vllm_config.model_config),
243 + "embed": GritLMPooler(vllm_config.model_config, pooler_config),
244 }
245 )
vllm/model_executor/models/modernbert.py
+12 -4
@@ -8,7 +8,7 @@ from transformers import ModernBertConfig
8 from transformers.activations import ACT2FN
9
10 from vllm.compilation.decorators import support_torch_compile
11 -from vllm.config import VllmConfig
11 +from vllm.config import PoolerConfig, VllmConfig
12 from vllm.distributed import get_tensor_model_parallel_world_size
13 from vllm.model_executor.layers.attention.encoder_only_attention import (
14 EncoderOnlyAttention,
@@ -282,9 +282,14 @@ class ModernBertModel(nn.Module):
282
283
284 class ModernBertPooler(SequencePooler):
285 - def __init__(self, config: ModernBertConfig):
285 + def __init__(self, config: ModernBertConfig, pooler_config: PoolerConfig):
286 + hf_pooling_type = config.classifier_pooling.upper()
287 + # vllm_pooling_type = pooler_config.seq_pooling_type
288 + # Currently we don't have a way to see if the user set the pooling type
289 + # explicitly or not, so we always use the HF pooling type for now.
290 +
291 super().__init__(
287 - pooling=get_seq_pooling_method(config.classifier_pooling.upper()),
292 + pooling=get_seq_pooling_method(hf_pooling_type),
293 head=self.head,
294 )
295
@@ -314,7 +319,9 @@ class ModernBertForSequenceClassification(nn.Module, SupportsCrossEncoding):
319
320 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
321 super().__init__()
322 +
323 config = vllm_config.model_config.hf_config
324 +
325 self.config = config
326 self.model = ModernBertModel(
327 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "modernbert")
@@ -324,11 +331,12 @@ class ModernBertForSequenceClassification(nn.Module, SupportsCrossEncoding):
331 config.num_labels,
332 dtype=vllm_config.model_config.head_dtype,
333 )
327 - self.pooling = ModernBertPooler(config)
334
335 pooler_config = vllm_config.model_config.pooler_config
336 assert pooler_config is not None
337
338 + self.pooling = ModernBertPooler(config, pooler_config)
339 +
340 self.pooler = DispatchPooler.for_seq_cls(
341 pooler_config,
342 pooling=self.pooling,
vllm/model_executor/models/roberta.py
+1 -3
@@ -9,7 +9,6 @@ from transformers import RobertaConfig
9
10 from vllm.config import ModelConfig, VllmConfig
11 from vllm.model_executor.layers.pooler import DispatchPooler
12 -from vllm.model_executor.layers.pooler.seqwise import CLSPool
12 from vllm.model_executor.layers.vocab_parallel_embedding import VocabParallelEmbedding
13 from vllm.model_executor.models.bert import (
14 TOKEN_TYPE_SHIFT,
@@ -86,7 +85,7 @@ class RobertaClassificationHead(nn.Module):
85 )
86
87 def forward(self, x: torch.Tensor) -> torch.Tensor:
89 - # CLSPool has already been applied in `pooling`
88 + # Token extraction has already been applied in `pooler.pooling`
89 x = self.dense(x)
90 x = torch.tanh(x)
91 x = self.out_proj(x)
@@ -194,7 +193,6 @@ class RobertaForSequenceClassification(nn.Module, SupportsCrossEncoding):
193
194 self.pooler = DispatchPooler.for_seq_cls(
195 pooler_config,
197 - pooling=CLSPool(),
196 classifier=self.classifier,
197 )
198
vllm/model_executor/models/transformers/pooling.py
+6 -6
@@ -23,7 +23,6 @@ from transformers import AutoModelForSequenceClassification
23
24 from vllm.config.utils import getattr_iter
25 from vllm.model_executor.layers.pooler import DispatchPooler
26 -from vllm.model_executor.layers.pooler.seqwise import CLSPool
26 from vllm.model_executor.models.interfaces import SupportsCrossEncoding
27 from vllm.model_executor.models.interfaces_base import VllmModelForPooling
28
@@ -32,7 +31,7 @@ if TYPE_CHECKING:
31
32
33 class EmbeddingMixin(VllmModelForPooling):
35 - default_pooling_type = "CLS"
34 + default_seq_pooling_type = "CLS"
35
36 def __init__(self, *, vllm_config: "VllmConfig", prefix: str = ""):
37 # Skip VllmModelForPooling.__init__ and call the next class in MRO
@@ -47,7 +46,7 @@ class EmbeddingMixin(VllmModelForPooling):
46
47
48 class SequenceClassificationMixin(SupportsCrossEncoding, VllmModelForPooling):
50 - default_pooling_type = "CLS"
49 + default_seq_pooling_type = "CLS"
50
51 def __init__(self, *, vllm_config: "VllmConfig", prefix: str = ""):
52 # Skip VllmModelForPooling.__init__ and call the next class in MRO
@@ -85,8 +84,10 @@ class SequenceClassificationMixin(SupportsCrossEncoding, VllmModelForPooling):
84 self.init_parameters(self.classifier, dtype=self.model_config.head_dtype)
85
86 class ClassifierWithReshape(self.classifier.__class__):
88 - """CLSPool has already been applied in `pooling`.
89 - Add dim to match expected input shape of `classifier.forward`."""
87 + """
88 + Token extraction has already been applied in `pooler.pooling`.
89 + Add dim to match expected input shape of `classifier.forward`.
90 + """
91
92 def forward(self, *args, **kwargs):
93 if len(args) > 0:
@@ -97,6 +98,5 @@ class SequenceClassificationMixin(SupportsCrossEncoding, VllmModelForPooling):
98
99 self.pooler = DispatchPooler.for_seq_cls(
100 pooler_config,
100 - pooling=CLSPool(),
101 classifier=self.classifier,
102 )