main
py 144 lines 4.47 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 from collections.abc import Callable, Set
4 from typing import TypeAlias
5
6 import torch
7
8 from vllm.config import PoolerConfig, get_current_vllm_config
9 from vllm.model_executor.layers.pooler import (
10 ClassifierFn,
11 PoolingParamsUpdate,
12 ProjectorFn,
13 )
14 from vllm.model_executor.layers.pooler.abstract import Pooler
15 from vllm.model_executor.layers.pooler.activations import (
16 PoolerActivation,
17 PoolerNormalize,
18 resolve_classifier_act_fn,
19 )
20 from vllm.model_executor.models.adapters import _load_st_projector
21 from vllm.tasks import POOLING_TASKS, PoolingTask
22 from vllm.v1.pool.metadata import PoolingMetadata
23
24 from .heads import (
25 TokenClassifierPoolerHead,
26 TokenEmbeddingPoolerHead,
27 TokenPoolerHead,
28 TokenPoolerHeadOutputItem,
29 )
30 from .methods import (
31 TokenPoolingMethod,
32 TokenPoolingMethodOutputItem,
33 get_tok_pooling_method,
34 )
35
36 TokenPoolingFn: TypeAlias = Callable[
37 [torch.Tensor, PoolingMetadata],
38 list[TokenPoolingMethodOutputItem],
39 ]
40 TokenPoolingHeadFn: TypeAlias = Callable[
41 [list[TokenPoolingMethodOutputItem], PoolingMetadata],
42 list[TokenPoolerHeadOutputItem],
43 ]
44
45 TokenPoolerOutput: TypeAlias = list[torch.Tensor | None]
46
47
48 class TokenPooler(Pooler):
49 """A layer that pools specific information from hidden states.
50
51 This layer does the following:
52 1. Extracts specific tokens or aggregates data based on pooling method.
53 2. Postprocesses the output based on pooling head.
54 3. Returns structured results as `PoolerOutput`.
55 """
56
57 def __init__(
58 self,
59 pooling: TokenPoolingMethod | TokenPoolingFn,
60 head: TokenPoolerHead | TokenPoolingHeadFn | None = None,
61 ) -> None:
62 super().__init__()
63
64 self.pooling = pooling
65 self.head = head
66
67 def extra_repr(self) -> str:
68 head_name = self.head.__class__.__name__ if self.head is not None else None
69 return f"pooling={self.pooling.__class__.__name__}, head={head_name}"
70
71 def get_supported_tasks(self) -> Set[PoolingTask]:
72 tasks = set(POOLING_TASKS)
73
74 if isinstance(self.pooling, TokenPoolingMethod):
75 tasks &= self.pooling.get_supported_tasks()
76 if isinstance(self.head, TokenPoolerHead):
77 tasks &= self.head.get_supported_tasks()
78
79 return tasks
80
81 def get_pooling_updates(self, task: PoolingTask) -> PoolingParamsUpdate:
82 updates = PoolingParamsUpdate()
83
84 if isinstance(self.pooling, TokenPoolingMethod):
85 updates |= self.pooling.get_pooling_updates(task)
86
87 return updates
88
89 def forward(
90 self,
91 hidden_states: torch.Tensor,
92 pooling_metadata: PoolingMetadata,
93 ) -> TokenPoolerOutput:
94 pooled_data = self.pooling(hidden_states, pooling_metadata)
95 if self.head is not None:
96 pooled_data = self.head(pooled_data, pooling_metadata)
97 return pooled_data
98
99
100 def pooler_for_token_embed(
101 pooler_config: PoolerConfig, projector: ProjectorFn | None = None
102 ) -> TokenPooler:
103 pooling = get_tok_pooling_method(pooler_config.get_tok_pooling_type())
104
105 vllm_config = get_current_vllm_config()
106 model_config = vllm_config.model_config
107 head = TokenEmbeddingPoolerHead(
108 head_dtype=model_config.head_dtype,
109 projector=projector
110 if projector is not None
111 else _load_st_projector(model_config),
112 activation=PoolerNormalize(),
113 )
114
115 return TokenPooler(pooling=pooling, head=head)
116
117
118 def pooler_for_token_classify(
119 pooler_config: PoolerConfig,
120 *,
121 pooling: TokenPoolingMethod | TokenPoolingFn | None = None,
122 classifier: ClassifierFn | None = None,
123 act_fn: PoolerActivation | None = None,
124 ) -> TokenPooler:
125 if pooling is None:
126 pooling = get_tok_pooling_method(pooler_config.get_tok_pooling_type())
127
128 vllm_config = get_current_vllm_config()
129 model_config = vllm_config.model_config
130 if model_config.pooler_config is None:
131 raise ValueError(
132 "model_config.pooler_config must be set for token classification pooling"
133 )
134 head = TokenClassifierPoolerHead(
135 head_dtype=model_config.head_dtype,
136 classifier=classifier,
137 logit_mean=model_config.pooler_config.logit_mean,
138 logit_sigma=model_config.pooler_config.logit_sigma,
139 activation=resolve_classifier_act_fn(
140 model_config, static_num_labels=False, act_fn=act_fn
141 ),
142 )
143
144 return TokenPooler(pooling=pooling, head=head)