@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / b7036c87a1
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, 14:00 UTC

[Refactor] Clean up pooler modules (#31897)

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

Cyrus Leung committed Jan 8, 2026 at 00:07 UTC b7036c87a13bd94fabf9e46436d3c1e67688f729
7 files changed +167 -120
vllm/model_executor/layers/pooler.py
+102 -81
@@ -5,7 +5,7 @@ from collections.abc import Callable, Mapping, Set
5 from dataclasses import dataclass
6 from enum import IntEnum
7 from itertools import groupby
8 -from typing import TypeVar
8 +from typing import TypeAlias, TypeVar
9
10 import torch
11 import torch.nn as nn
@@ -18,8 +18,8 @@ from vllm.model_executor.models.adapters import _load_st_projector
18 from vllm.pooling_params import PoolingParams
19 from vllm.tasks import PoolingTask
20 from vllm.utils.import_utils import resolve_obj_by_qualname
21 -from vllm.v1.outputs import PoolerOutput
22 -from vllm.v1.pool.metadata import PoolingCursor, PoolingMetadata
21 +from vllm.v1.outputs import PoolerOutput, TokenPoolerOutput, TokensPoolerOutput
22 +from vllm.v1.pool.metadata import PoolingMetadata
23
24 logger = init_logger(__name__)
25
@@ -30,6 +30,15 @@ PoolingFn = Callable[
30 ClassifierFn = Callable[[torch.Tensor], torch.Tensor]
31
32
33 +TokenPoolingMethodOutput: TypeAlias = torch.Tensor | list[torch.Tensor]
34 +TokensPoolingMethodOutput: TypeAlias = list[torch.Tensor] | list[torch.Tensor | None]
35 +TokensPoolingMethodOutputItem: TypeAlias = torch.Tensor | None
36 +PoolingMethodOutput: TypeAlias = TokenPoolingMethodOutput | TokensPoolingMethodOutput
37 +
38 +TokenPoolerHeadOutput: TypeAlias = torch.Tensor | list[torch.Tensor]
39 +TokensPoolerHeadOutput: TypeAlias = torch.Tensor | None
40 +
41 +
42 class PoolingType(IntEnum):
43 """Enumeration for different types of pooling methods."""
44
@@ -123,31 +132,24 @@ class PoolingMethod(nn.Module, ABC):
132 return PoolingParamsUpdate()
133
134 @abstractmethod
126 - def forward_all(
127 - self,
128 - hidden_states: torch.Tensor,
129 - pooling_cursor: PoolingCursor,
130 - ) -> PoolerOutput:
131 - raise NotImplementedError
132 -
135 def forward(
136 self,
137 hidden_states: torch.Tensor,
138 pooling_metadata: PoolingMetadata,
137 - ) -> PoolerOutput:
138 - pooling_cursor = pooling_metadata.pooling_cursor
139 - return self.forward_all(hidden_states, pooling_cursor)
139 + ) -> PoolingMethodOutput:
140 + raise NotImplementedError
141
142
143 class CLSPool(PoolingMethod):
144 def get_supported_tasks(self) -> Set[PoolingTask]:
145 return {"token_embed", "token_classify", "embed", "classify", "score"}
146
146 - def forward_all(
147 + def forward(
148 self,
149 hidden_states: torch.Tensor,
149 - pooling_cursor: PoolingCursor,
150 - ) -> PoolerOutput:
150 + pooling_metadata: PoolingMetadata,
151 + ) -> TokenPoolingMethodOutput:
152 + pooling_cursor = pooling_metadata.get_pooling_cursor()
153 assert not pooling_cursor.is_partial_prefill(), (
154 "partial prefill not supported with CLS pooling"
155 )
@@ -159,11 +161,12 @@ class LastPool(PoolingMethod):
161 def get_supported_tasks(self) -> Set[PoolingTask]:
162 return {"token_embed", "token_classify", "embed", "classify", "score"}
163
162 - def forward_all(
164 + def forward(
165 self,
166 hidden_states: torch.Tensor,
165 - pooling_cursor: PoolingCursor,
166 - ) -> PoolerOutput:
167 + pooling_metadata: PoolingMetadata,
168 + ) -> TokenPoolingMethodOutput:
169 + pooling_cursor = pooling_metadata.get_pooling_cursor()
170 return hidden_states[pooling_cursor.last_token_indices_gpu]
171
172
@@ -179,19 +182,12 @@ class AllPool(PoolingMethod):
182 def get_supported_tasks(self) -> Set[PoolingTask]:
183 return {"token_embed", "token_classify"}
184
182 - def forward_all(
183 - self, hidden_states: torch.Tensor, pooling_cursor: PoolingCursor
184 - ) -> PoolerOutput:
185 - raise NotImplementedError(
186 - "forward_all is not implemented for AllPool. Use forward instead."
187 - )
188 -
185 def forward(
186 self,
187 hidden_states: torch.Tensor,
188 pooling_metadata: PoolingMetadata,
193 - ) -> PoolerOutput:
194 - pooling_cursor = pooling_metadata.pooling_cursor
189 + ) -> TokensPoolingMethodOutput:
190 + pooling_cursor = pooling_metadata.get_pooling_cursor()
191 is_finished = pooling_cursor.is_finished()
192 hidden_states_lst = list(
193 hidden_states.split(pooling_cursor.num_scheduled_tokens_cpu.tolist())
@@ -209,7 +205,7 @@ class AllPool(PoolingMethod):
205 p.hidden_states_cache.append(hs_chunk)
206
207 # 2. Once prefill is finished, send hidden_states_cache to PoolerHead
212 - output_list: PoolerOutput = []
208 + output_list = list[torch.Tensor | None]()
209 for p, finished in zip(pooling_states, is_finished):
210 if finished:
211 hidden_states_cache = p.hidden_states_cache
@@ -228,11 +224,12 @@ class MeanPool(PoolingMethod):
224 def get_supported_tasks(self) -> Set[PoolingTask]:
225 return {"token_embed", "token_classify", "embed", "classify", "score"}
226
231 - def forward_all(
227 + def forward(
228 self,
229 hidden_states: torch.Tensor,
234 - pooling_cursor: PoolingCursor,
235 - ) -> PoolerOutput:
230 + pooling_metadata: PoolingMetadata,
231 + ) -> TokenPoolingMethodOutput:
232 + pooling_cursor = pooling_metadata.get_pooling_cursor()
233 assert not pooling_cursor.is_partial_prefill(), (
234 "partial prefill not supported with MEAN pooling"
235 )
@@ -410,7 +407,7 @@ class Pooler(nn.Module, ABC):
407 @abstractmethod
408 def forward(
409 self,
413 - hidden_states: list[torch.Tensor] | torch.Tensor,
410 + hidden_states: torch.Tensor,
411 pooling_metadata: PoolingMetadata,
412 ) -> PoolerOutput:
413 raise NotImplementedError
@@ -422,41 +419,42 @@ class DummyPooler(Pooler):
419
420 def forward(
421 self,
425 - hidden_states: list[torch.Tensor] | torch.Tensor,
422 + hidden_states: torch.Tensor,
423 pooling_metadata: PoolingMetadata,
424 ) -> PoolerOutput:
425 return hidden_states
426
427
431 -class PoolerHead(nn.Module):
432 - def __init__(self, activation: PoolerActivation) -> None:
433 - super().__init__()
434 - self.activation = activation
428 +class TokenPoolerHead(nn.Module, ABC):
429 + """Applicable to pooling strategies that output one token."""
430
431 + @abstractmethod
432 def forward(
433 self,
438 - pooled_data: list[torch.Tensor] | torch.Tensor,
434 + pooled_data: TokenPoolingMethodOutput,
435 pooling_metadata: PoolingMetadata,
440 - ) -> PoolerOutput:
441 - return self.activation(pooled_data)
436 + ) -> TokenPoolerHeadOutput:
437 + raise NotImplementedError
438
439
444 -class EmbeddingPoolerHead(PoolerHead):
440 +class EmbeddingPoolerHead(TokenPoolerHead):
441 def __init__(self) -> None:
446 - super().__init__(activation=PoolerNormalize())
442 + super().__init__()
443
444 # Load ST projector if available
445 vllm_config = get_current_vllm_config()
450 - self.projector: nn.Module | None = (
446 + self.projector = (
447 _load_st_projector(vllm_config.model_config) if vllm_config else None
448 )
449 self.head_dtype = vllm_config.model_config.head_dtype
450
451 + self.activation = PoolerNormalize()
452 +
453 def forward(
454 self,
457 - pooled_data: list[torch.Tensor] | torch.Tensor,
455 + pooled_data: TokenPoolingMethodOutput,
456 pooling_metadata: PoolingMetadata,
459 - ) -> PoolerOutput:
457 + ) -> TokenPoolerHeadOutput:
458 if isinstance(pooled_data, list):
459 pooled_data = torch.stack(pooled_data)
460 # pooled_data shape: [batchsize, hidden_dimension]
@@ -509,7 +507,7 @@ class SimplePooler(Pooler):
507 3. Returns structured results as `PoolerOutput`.
508 """
509
512 - def __init__(self, pooling: PoolingMethod, head: PoolerHead) -> None:
510 + def __init__(self, pooling: PoolingMethod, head: TokenPoolerHead) -> None:
511 super().__init__()
512
513 self.pooling = pooling
@@ -523,9 +521,9 @@ class SimplePooler(Pooler):
521
522 def forward(
523 self,
526 - hidden_states: torch.Tensor | list[torch.Tensor],
524 + hidden_states: torch.Tensor,
525 pooling_metadata: PoolingMetadata,
528 - ) -> PoolerOutput:
526 + ) -> TokenPoolerHeadOutput:
527 pooled_data = self.pooling(hidden_states, pooling_metadata)
528 pooled_data = self.head(pooled_data, pooling_metadata)
529 return pooled_data
@@ -591,9 +589,9 @@ class ClassifierPooler(Pooler):
589
590 def forward(
591 self,
594 - hidden_states: torch.Tensor | list[torch.Tensor],
592 + hidden_states: torch.Tensor,
593 pooling_metadata: PoolingMetadata,
596 - ) -> PoolerOutput:
594 + ) -> TokenPoolerOutput:
595 pooled_data = self.pooling(hidden_states, pooling_metadata)
596 if isinstance(pooled_data, list):
597 pooled_data = torch.stack(pooled_data)
@@ -622,10 +620,36 @@ class ClassifierPooler(Pooler):
620 return scores
621
622
625 -class TokenEmbeddingPoolerHead(EmbeddingPoolerHead):
623 +class TokensPoolerHead(nn.Module, ABC):
624 + """Applicable to pooling strategies that output multiple tokens."""
625 +
626 + @abstractmethod
627 def forward(
627 - self, pooled_data: torch.Tensor | None, pooling_param: PoolingParams
628 - ) -> PoolerOutput:
628 + self,
629 + pooled_data: TokensPoolingMethodOutputItem,
630 + pooling_param: PoolingParams,
631 + ) -> TokensPoolerHeadOutput:
632 + raise NotImplementedError
633 +
634 +
635 +class TokenEmbeddingPoolerHead(TokensPoolerHead):
636 + def __init__(self) -> None:
637 + super().__init__()
638 +
639 + # Load ST projector if available
640 + vllm_config = get_current_vllm_config()
641 + self.projector = (
642 + _load_st_projector(vllm_config.model_config) if vllm_config else None
643 + )
644 + self.head_dtype = vllm_config.model_config.head_dtype
645 +
646 + self.activation = PoolerNormalize()
647 +
648 + def forward(
649 + self,
650 + pooled_data: TokensPoolingMethodOutputItem,
651 + pooling_param: PoolingParams,
652 + ) -> TokensPoolerHeadOutput:
653 # for unfinished chunked prefill
654 if pooled_data is None:
655 return None
@@ -649,57 +673,56 @@ class TokenEmbeddingPoolerHead(EmbeddingPoolerHead):
673 return pooled_data
674
675
652 -class TokenClassifierPoolerHead(nn.Module):
676 +class TokenClassifierPoolerHead(TokensPoolerHead):
677 def __init__(
678 self,
679 classifier: ClassifierFn | None,
680 act_fn: PoolerActivation | str | None = None,
681 ) -> None:
682 super().__init__()
683 +
684 vllm_config = get_current_vllm_config()
685
686 self.classifier = classifier
662 - self.act_fn = ClassifierPooler.resolve_act_fn(
663 - vllm_config.model_config, static_num_labels=False, act_fn=act_fn
664 - )
687 self.logit_bias: float | None = (
688 vllm_config.model_config.pooler_config.logit_bias
689 )
690 self.head_dtype = vllm_config.model_config.head_dtype
691
670 - def get_supported_tasks(self) -> Set[PoolingTask]:
671 - return {"token_classify"}
692 + self.activation = ClassifierPooler.resolve_act_fn(
693 + vllm_config.model_config, static_num_labels=False, act_fn=act_fn
694 + )
695
696 def forward(
697 self,
675 - hidden_states: torch.Tensor | None,
698 + pooled_data: TokensPoolingMethodOutputItem,
699 pooling_param: PoolingParams,
677 - ) -> PoolerOutput:
700 + ) -> TokensPoolerHeadOutput:
701 # for unfinished chunked prefill
679 - if hidden_states is None:
702 + if pooled_data is None:
703 return None
704
682 - hidden_states = hidden_states.to(self.head_dtype)
705 + pooled_data = pooled_data.to(self.head_dtype)
706 # hidden_states shape: [n_token, hidden_size]
707
708 if self.classifier is not None:
686 - scores = self.classifier(hidden_states)
709 + scores = self.classifier(pooled_data)
710 else:
688 - scores = hidden_states
711 + scores = pooled_data
712 # scores shape: [n_token, num_labels]
713
714 if self.logit_bias is not None:
715 scores -= self.logit_bias
716
717 if pooling_param.use_activation:
695 - scores = self.act_fn(scores)
718 + scores = self.activation(scores)
719
720 # scores shape: [n_token, num_labels]
721 return scores
722
723
724 class AllPooler(Pooler):
702 - def __init__(self, head: nn.Module | PoolerHead) -> None:
725 + def __init__(self, head: TokensPoolerHead) -> None:
726 super().__init__()
727
728 self.pooling = AllPool()
@@ -712,17 +735,16 @@ class AllPooler(Pooler):
735 self,
736 hidden_states: torch.Tensor,
737 pooling_metadata: PoolingMetadata,
715 - ) -> PoolerOutput:
738 + ) -> TokensPoolerOutput:
739 pooled_data = self.pooling(hidden_states, pooling_metadata)
740 pooling_params = pooling_metadata.pooling_params
741 assert len(pooled_data) == len(pooling_params)
742
720 - pooled_data = [self.head(d, p) for d, p in zip(pooled_data, pooling_params)]
721 - return pooled_data
743 + return [self.head(d, p) for d, p in zip(pooled_data, pooling_params)]
744
745
746 class StepPooler(Pooler):
725 - def __init__(self, head: nn.Module | PoolerHead) -> None:
747 + def __init__(self, head: TokensPoolerHead) -> None:
748 super().__init__()
749
750 self.pooling = AllPool()
@@ -730,14 +752,14 @@ class StepPooler(Pooler):
752
753 def extract_states(
754 self,
733 - hidden_states: torch.Tensor | list[torch.Tensor],
755 + hidden_states: torch.Tensor,
756 pooling_metadata: PoolingMetadata,
735 - ) -> PoolerOutput:
757 + ) -> list[torch.Tensor | None]:
758 pooled_data_lst = self.pooling(hidden_states, pooling_metadata)
759 prompt_token_ids = pooling_metadata.get_prompt_token_ids()
760 pooling_params = pooling_metadata.pooling_params
761
740 - pooled_data: PoolerOutput = []
762 + pooled_data = list[torch.Tensor | None]()
763 for data, token_id, pooling_param in zip(
764 pooled_data_lst, prompt_token_ids, pooling_params
765 ):
@@ -766,15 +788,14 @@ class StepPooler(Pooler):
788
789 def forward(
790 self,
769 - hidden_states: torch.Tensor | list[torch.Tensor],
791 + hidden_states: torch.Tensor,
792 pooling_metadata: PoolingMetadata,
771 - ) -> PoolerOutput:
793 + ) -> TokensPoolerOutput:
794 pooled_data = self.extract_states(hidden_states, pooling_metadata)
795 pooling_params = pooling_metadata.pooling_params
796 assert len(pooled_data) == len(pooling_params)
797
776 - pooled_data = [self.head(d, p) for d, p in zip(pooled_data, pooling_params)]
777 - return pooled_data
798 + return [self.head(d, p) for d, p in zip(pooled_data, pooling_params)]
799
800
801 class DispatchPooler(Pooler):
@@ -800,12 +821,12 @@ class DispatchPooler(Pooler):
821
822 def forward(
823 self,
803 - hidden_states: torch.Tensor | list[torch.Tensor],
824 + hidden_states: torch.Tensor,
825 pooling_metadata: PoolingMetadata,
826 ) -> PoolerOutput:
827 poolers_by_task = self.poolers_by_task
828
808 - outputs = list[torch.Tensor]()
829 + outputs = list[torch.Tensor | None]()
830 offset = 0
831 for task, group in groupby(pooling_metadata.tasks):
832 if not (pooler := poolers_by_task.get(task)):
vllm/model_executor/models/bert.py
+19 -14
@@ -24,11 +24,14 @@ from vllm.model_executor.layers.pooler import (
24 PoolingMethod,
25 PoolingParamsUpdate,
26 PoolingType,
27 + TokenPoolerHeadOutput,
28 + TokenPoolingMethodOutput,
29 )
30 from vllm.model_executor.layers.quantization import QuantizationConfig
31 from vllm.model_executor.layers.vocab_parallel_embedding import VocabParallelEmbedding
32 from vllm.sequence import IntermediateTensors
33 from vllm.tasks import PoolingTask
34 +from vllm.v1.outputs import TokenPoolerOutput
35 from vllm.v1.pool.metadata import PoolingMetadata
36
37 from .interfaces import SupportsCrossEncoding, SupportsQuant
@@ -97,24 +100,26 @@ class BertPooler(Pooler):
100 def get_pooling_updates(self, task: PoolingTask) -> PoolingParamsUpdate:
101 return self.pooling.get_pooling_updates(task)
102
100 - def _head(self, pooled_output: torch.Tensor):
101 - pooled_output = self.dense(pooled_output)
102 - pooled_output = self.activation(pooled_output)
103 - return pooled_output
104 -
105 - def forward(
103 + def head(
104 self,
107 - hidden_states: torch.Tensor | list[torch.Tensor],
105 + pooled_data: TokenPoolingMethodOutput,
106 pooling_metadata: PoolingMetadata,
109 - ) -> torch.Tensor | list[torch.Tensor]:
110 - pooled_output = self.pooling(hidden_states, pooling_metadata)
107 + ) -> TokenPoolerHeadOutput:
108 + if isinstance(pooled_data, list):
109 + pooled_data = torch.stack(pooled_data)
110
112 - if isinstance(pooled_output, list):
113 - pooled_output = [self._head(output) for output in pooled_output]
114 - else:
115 - pooled_output = self._head(pooled_output)
111 + pooled_data = self.dense(pooled_data)
112 + pooled_data = self.activation(pooled_data)
113 + return pooled_data
114
117 - return pooled_output
115 + def forward(
116 + self,
117 + hidden_states: torch.Tensor,
118 + pooling_metadata: PoolingMetadata,
119 + ) -> TokenPoolerOutput:
120 + pooled_data = self.pooling(hidden_states, pooling_metadata)
121 + pooled_data = self.head(pooled_data, pooling_metadata)
122 + return pooled_data
123
124
125 class BertEncoder(nn.Module):
vllm/model_executor/models/gritlm.py
+17 -9
@@ -4,21 +4,22 @@ from collections.abc import Set
4
5 import numpy as np
6 import torch
7 -import torch.nn as nn
7
8 from vllm.config import ModelConfig, VllmConfig
9 from vllm.logger import init_logger
10 from vllm.model_executor.layers.pooler import (
11 DispatchPooler,
12 Pooler,
14 - PoolerHead,
13 PoolerNormalize,
14 + PoolingMethod,
15 PoolingParamsUpdate,
16 + TokenPoolerHeadOutput,
17 + TokenPoolingMethodOutput,
18 )
19 from vllm.model_executor.models.llama import LlamaForCausalLM
20 from vllm.tasks import PoolingTask
21 from vllm.tokenizers import cached_tokenizer_from_config
21 -from vllm.v1.outputs import PoolerOutput
22 +from vllm.v1.outputs import TokenPoolerOutput
23 from vllm.v1.pool.metadata import PoolingMetadata
24
25 from .interfaces_base import default_pooling_type
@@ -26,7 +27,7 @@ from .interfaces_base import default_pooling_type
27 logger = init_logger(__name__)
28
29
29 -class GritLMMeanPool(nn.Module):
30 +class GritLMMeanPool(PoolingMethod):
31 """As `MeanPool`, but only includes non-instruction tokens."""
32
33 def __init__(self, model_config: ModelConfig):
@@ -141,16 +142,16 @@ class GritLMMeanPool(nn.Module):
142 return instruction_len
143
144 def get_supported_tasks(self) -> Set[PoolingTask]:
144 - return {"encode", "embed"}
145 + return {"embed"}
146
147 def get_pooling_updates(self, task: PoolingTask) -> PoolingParamsUpdate:
148 return PoolingParamsUpdate(requires_token_ids=True)
149
150 def forward(
151 self,
151 - hidden_states: torch.Tensor | list[torch.Tensor],
152 + hidden_states: torch.Tensor,
153 pooling_metadata: PoolingMetadata,
153 - ) -> list[torch.Tensor] | torch.Tensor:
154 + ) -> TokenPoolingMethodOutput:
155 prompt_lens = pooling_metadata.prompt_lens
156 instr_lens = torch.tensor(
157 [
@@ -178,7 +179,7 @@ class GritLMPooler(Pooler):
179 super().__init__()
180
181 self.pooling = GritLMMeanPool(model_config)
181 - self.head = PoolerHead(PoolerNormalize())
182 + self.activation = PoolerNormalize()
183
184 def get_supported_tasks(self) -> Set[PoolingTask]:
185 return self.pooling.get_supported_tasks()
@@ -186,11 +187,18 @@ class GritLMPooler(Pooler):
187 def get_pooling_updates(self, task: PoolingTask) -> PoolingParamsUpdate:
188 return self.pooling.get_pooling_updates(task)
189
190 + def head(
191 + self,
192 + pooled_data: TokenPoolingMethodOutput,
193 + pooling_metadata: PoolingMetadata,
194 + ) -> TokenPoolerHeadOutput:
195 + return self.activation(pooled_data)
196 +
197 def forward(
198 self,
199 hidden_states: torch.Tensor,
200 pooling_metadata: PoolingMetadata,
193 - ) -> PoolerOutput:
201 + ) -> TokenPoolerOutput:
202 pooled_data = self.pooling(hidden_states, pooling_metadata)
203 pooled_data = self.head(pooled_data, pooling_metadata)
204 return pooled_data
vllm/model_executor/models/modernbert.py
+18 -13
@@ -19,12 +19,15 @@ from vllm.model_executor.layers.pooler import (
19 PoolingMethod,
20 PoolingParamsUpdate,
21 PoolingType,
22 + TokenPoolerHeadOutput,
23 + TokenPoolingMethodOutput,
24 )
25 from vllm.model_executor.layers.rotary_embedding import get_rope
26 from vllm.model_executor.layers.vocab_parallel_embedding import VocabParallelEmbedding
27 from vllm.model_executor.model_loader.weight_utils import default_weight_loader
28 from vllm.sequence import IntermediateTensors
29 from vllm.tasks import PoolingTask
30 +from vllm.v1.outputs import TokenPoolerOutput
31 from vllm.v1.pool.metadata import PoolingMetadata
32
33 from .interfaces import SupportsCrossEncoding
@@ -300,23 +303,25 @@ class ModernBertPooler(Pooler):
303 def get_pooling_updates(self, task: PoolingTask) -> PoolingParamsUpdate:
304 return self.pooling.get_pooling_updates(task)
305
303 - def _head(self, pooled_output: torch.Tensor):
304 - pooled_output = pooled_output.to(self.dense.weight.dtype)
305 - return self.norm(self.act(self.dense(pooled_output)))
306 -
307 - def forward(
306 + def head(
307 self,
309 - hidden_states: torch.Tensor | list[torch.Tensor],
308 + pooled_data: TokenPoolingMethodOutput,
309 pooling_metadata: PoolingMetadata,
311 - ) -> torch.Tensor | list[torch.Tensor]:
312 - pooled_output = self.pooling(hidden_states, pooling_metadata)
310 + ) -> TokenPoolerHeadOutput:
311 + if isinstance(pooled_data, list):
312 + pooled_data = torch.stack(pooled_data)
313
314 - if isinstance(pooled_output, list):
315 - pooled_output = [self._head(output) for output in pooled_output]
316 - else:
317 - pooled_output = self._head(pooled_output)
314 + pooled_data = pooled_data.to(self.dense.weight.dtype)
315 + return self.norm(self.act(self.dense(pooled_data)))
316
319 - return pooled_output
317 + def forward(
318 + self,
319 + hidden_states: torch.Tensor,
320 + pooling_metadata: PoolingMetadata,
321 + ) -> TokenPoolerOutput:
322 + pooled_data = self.pooling(hidden_states, pooling_metadata)
323 + pooled_data = self.head(pooled_data, pooling_metadata)
324 + return pooled_data
325
326
327 @default_pooling_type("CLS")
vllm/v1/outputs.py
+4 -2
@@ -3,7 +3,7 @@
3
4 from abc import ABC, abstractmethod
5 from dataclasses import dataclass, field
6 -from typing import TYPE_CHECKING, NamedTuple
6 +from typing import TYPE_CHECKING, NamedTuple, TypeAlias
7
8 import numpy as np
9 import torch
@@ -91,7 +91,9 @@ class LogprobsTensors(NamedTuple):
91
92 # [num_reqs, <dynamic>]
93 # The shape of each element depends on the pooler used
94 -PoolerOutput = list[torch.Tensor | None] | torch.Tensor | None
94 +TokenPoolerOutput: TypeAlias = torch.Tensor | list[torch.Tensor]
95 +TokensPoolerOutput: TypeAlias = list[torch.Tensor] | list[torch.Tensor | None]
96 +PoolerOutput: TypeAlias = TokenPoolerOutput | TokensPoolerOutput
97
98
99 @dataclass
vllm/v1/pool/metadata.py
+6
@@ -90,6 +90,12 @@ class PoolingMetadata:
90
91 return [prompt_token_ids[i, :num] for i, num in enumerate(self.prompt_lens)]
92
93 + def get_pooling_cursor(self) -> PoolingCursor:
94 + pooling_cursor = self.pooling_cursor
95 + assert pooling_cursor is not None, "Should call `build_pooling_cursor` first"
96 +
97 + return pooling_cursor
98 +
99 def build_pooling_cursor(
100 self,
101 num_scheduled_tokens_np: np.ndarray,
vllm/v1/worker/gpu_model_runner.py
+1 -1
@@ -4680,7 +4680,7 @@ class GPUModelRunner(
4680 for task in supported_pooling_tasks:
4681 # Run a full batch with each task to ensure none of them OOMs
4682 output = self._dummy_pooler_run_task(hidden_states, task)
4683 - output_size[task] = sum(o.nbytes for o in output)
4683 + output_size[task] = sum(o.nbytes for o in output if o is not None)
4684 del output # Allow GC
4685
4686 max_task = max(output_size.items(), key=lambda x: x[1])[0]