main
py 301 lines 10.4 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # Adapted from
5 # https://github.com/huggingface/transformers/blob/v4.28.0/src/transformers/models/gptj/modeling_gptj.py
6 # Copyright 2023 The vLLM team.
7 # Copyright 2021 The EleutherAI and HuggingFace Teams. All rights reserved.
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 # http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 """Inference-only GPT-J model compatible with HuggingFace weights."""
21
22 from collections.abc import Iterable
23 from itertools import islice
24
25 import torch
26 from torch import nn
27 from transformers import GPTJConfig
28
29 from vllm.compilation.decorators import support_torch_compile
30 from vllm.config import CacheConfig, VllmConfig
31 from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
32 from vllm.model_executor.layers.activation import get_act_fn
33 from vllm.model_executor.layers.attention import Attention
34 from vllm.model_executor.layers.layernorm import LayerNorm
35 from vllm.model_executor.layers.linear import (
36 ColumnParallelLinear,
37 QKVParallelLinear,
38 RowParallelLinear,
39 )
40 from vllm.model_executor.layers.logits_processor import LogitsProcessor
41 from vllm.model_executor.layers.quantization import QuantizationConfig
42 from vllm.model_executor.layers.rotary_embedding import get_rope
43 from vllm.model_executor.layers.vocab_parallel_embedding import (
44 ParallelLMHead,
45 VocabParallelEmbedding,
46 )
47 from vllm.sequence import IntermediateTensors
48
49 from .interfaces import SupportsPP
50 from .utils import (
51 AutoWeightsLoader,
52 WeightsMapper,
53 make_empty_intermediate_tensors_factory,
54 make_layers,
55 maybe_prefix,
56 )
57
58
59 class GPTJAttention(nn.Module):
60 def __init__(
61 self,
62 config: GPTJConfig,
63 cache_config: CacheConfig | None = None,
64 quant_config: QuantizationConfig | None = None,
65 prefix: str = "",
66 ):
67 super().__init__()
68 self.total_num_heads = config.num_attention_heads
69 self.hidden_size = config.hidden_size
70 self.head_size = self.hidden_size // self.total_num_heads
71
72 self.qkv_proj = QKVParallelLinear(
73 config.hidden_size,
74 self.head_size,
75 self.total_num_heads,
76 bias=False,
77 quant_config=quant_config,
78 prefix=f"{prefix}.qkv_proj",
79 )
80 self.out_proj = RowParallelLinear(
81 config.hidden_size,
82 config.hidden_size,
83 bias=False,
84 quant_config=quant_config,
85 prefix=f"{prefix}.out_proj",
86 )
87
88 tp_world_size = get_tensor_model_parallel_world_size()
89 assert self.total_num_heads % tp_world_size == 0
90 self.num_heads = self.total_num_heads // tp_world_size
91
92 scaling = self.head_size**-0.5
93 assert getattr(config, "rotary", True)
94 assert config.rotary_dim % 2 == 0
95 rope_parameters = getattr(config, "rope_parameters", {})
96 rope_parameters["partial_rotary_factor"] = config.rotary_dim / self.head_size
97 max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
98 self.rotary_emb = get_rope(
99 self.head_size,
100 max_position=max_position_embeddings,
101 rope_parameters=rope_parameters,
102 is_neox_style=False,
103 )
104 self.attn = Attention(
105 self.num_heads,
106 self.head_size,
107 scaling,
108 cache_config=cache_config,
109 quant_config=quant_config,
110 prefix=f"{prefix}.attn",
111 )
112
113 def forward(
114 self,
115 position_ids: torch.Tensor,
116 hidden_states: torch.Tensor,
117 ) -> torch.Tensor:
118 qkv, _ = self.qkv_proj(hidden_states)
119 q, k, v = qkv.chunk(chunks=3, dim=-1)
120 q, k = self.rotary_emb(position_ids, q, k)
121 attn_output = self.attn(q, k, v)
122 attn_output, _ = self.out_proj(attn_output)
123 return attn_output
124
125
126 class GPTJMLP(nn.Module):
127 def __init__(
128 self,
129 intermediate_size: int,
130 config: GPTJConfig,
131 quant_config: QuantizationConfig | None = None,
132 prefix: str = "",
133 ):
134 super().__init__()
135 hidden_size = config.n_embd
136 self.fc_in = ColumnParallelLinear(
137 hidden_size,
138 intermediate_size,
139 quant_config=quant_config,
140 prefix=f"{prefix}.fc_in",
141 )
142 self.fc_out = RowParallelLinear(
143 intermediate_size,
144 hidden_size,
145 quant_config=quant_config,
146 prefix=f"{prefix}.fc_out",
147 )
148 self.act = get_act_fn(config.activation_function)
149
150 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
151 hidden_states, _ = self.fc_in(hidden_states)
152 hidden_states = self.act(hidden_states)
153 hidden_states, _ = self.fc_out(hidden_states)
154 return hidden_states
155
156
157 class GPTJBlock(nn.Module):
158 def __init__(
159 self,
160 config: GPTJConfig,
161 cache_config: CacheConfig | None = None,
162 quant_config: QuantizationConfig | None = None,
163 prefix: str = "",
164 ):
165 super().__init__()
166 inner_dim = 4 * config.n_embd if config.n_inner is None else config.n_inner
167 self.ln_1 = LayerNorm(config.n_embd, eps=config.layer_norm_epsilon)
168 self.attn = GPTJAttention(
169 config, cache_config, quant_config, prefix=f"{prefix}.attn"
170 )
171 self.mlp = GPTJMLP(inner_dim, config, quant_config, prefix=f"{prefix}.mlp")
172
173 def forward(
174 self,
175 position_ids: torch.Tensor,
176 hidden_states: torch.Tensor,
177 ) -> torch.Tensor:
178 residual = hidden_states
179 hidden_states = self.ln_1(hidden_states)
180 attn_output = self.attn(
181 position_ids=position_ids,
182 hidden_states=hidden_states,
183 )
184 mlp_output = self.mlp(hidden_states)
185 hidden_states = attn_output + mlp_output + residual
186 return hidden_states
187
188
189 @support_torch_compile
190 class GPTJModel(nn.Module):
191 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
192 super().__init__()
193
194 config = vllm_config.model_config.hf_config
195 cache_config = vllm_config.cache_config
196 quant_config = vllm_config.quant_config
197
198 self.config = config
199 self.quant_config = quant_config
200 self.embed_dim = config.n_embd
201 self.wte = VocabParallelEmbedding(
202 config.vocab_size,
203 self.embed_dim,
204 )
205 self.start_layer, self.end_layer, self.h = make_layers(
206 config.n_layer,
207 lambda prefix: GPTJBlock(config, cache_config, quant_config, prefix=prefix),
208 prefix=f"{prefix}.h",
209 )
210 self.ln_f = LayerNorm(self.embed_dim, eps=config.layer_norm_epsilon)
211 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
212 ["hidden_states"], config.n_embd
213 )
214
215 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
216 return self.wte(input_ids)
217
218 def forward(
219 self,
220 input_ids: torch.Tensor | None,
221 position_ids: torch.Tensor,
222 intermediate_tensors: IntermediateTensors | None,
223 inputs_embeds: torch.Tensor | None = None,
224 ) -> torch.Tensor | IntermediateTensors:
225 if get_pp_group().is_first_rank:
226 if inputs_embeds is not None:
227 hidden_states = inputs_embeds
228 else:
229 hidden_states = self.embed_input_ids(input_ids)
230 else:
231 assert intermediate_tensors is not None
232 hidden_states = intermediate_tensors["hidden_states"]
233 for layer in islice(self.h, self.start_layer, self.end_layer):
234 hidden_states = layer(position_ids, hidden_states)
235 if not get_pp_group().is_last_rank:
236 return IntermediateTensors({"hidden_states": hidden_states})
237 hidden_states = self.ln_f(hidden_states)
238 return hidden_states
239
240
241 class GPTJForCausalLM(nn.Module, SupportsPP):
242 hf_to_vllm_mapper = WeightsMapper(
243 orig_to_new_stacked={
244 # weight_name: (param_name, shard_id)
245 ".q_proj": (".qkv_proj", "q"),
246 ".k_proj": (".qkv_proj", "k"),
247 ".v_proj": (".qkv_proj", "v"),
248 },
249 orig_to_new_substr={
250 "attn.bias": None,
251 "attn.masked_bias": None,
252 },
253 )
254
255 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
256 super().__init__()
257 config = vllm_config.model_config.hf_config
258 quant_config = vllm_config.quant_config
259 self.config = config
260 self.quant_config = quant_config
261 assert not config.tie_word_embeddings
262 self.transformer = GPTJModel(
263 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "transformer")
264 )
265 self.lm_head = ParallelLMHead(
266 config.vocab_size,
267 config.n_embd,
268 bias=True,
269 quant_config=quant_config,
270 prefix=maybe_prefix(prefix, "lm_head"),
271 )
272 self.logits_processor = LogitsProcessor(config.vocab_size)
273 self.make_empty_intermediate_tensors = (
274 self.transformer.make_empty_intermediate_tensors
275 )
276
277 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
278 return self.transformer.embed_input_ids(input_ids)
279
280 def forward(
281 self,
282 input_ids: torch.Tensor | None,
283 positions: torch.Tensor,
284 intermediate_tensors: IntermediateTensors | None = None,
285 inputs_embeds: torch.Tensor | None = None,
286 ) -> torch.Tensor | IntermediateTensors:
287 hidden_states = self.transformer(
288 input_ids, positions, intermediate_tensors, inputs_embeds
289 )
290 return hidden_states
291
292 def compute_logits(
293 self,
294 hidden_states: torch.Tensor,
295 ) -> torch.Tensor | None:
296 logits = self.logits_processor(self.lm_head, hidden_states, self.lm_head.bias)
297 return logits
298
299 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
300 loader = AutoWeightsLoader(self)
301 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)