main
py 392 lines 13.9 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/opt/modeling_opt.py
6 # Copyright 2023 The vLLM team.
7 # Copyright 2022 The Fairseq Authors and The HuggingFace Inc. team. All rights
8 # reserved.
9 #
10 # Licensed under the Apache License, Version 2.0 (the "License");
11 # you may not use this file except in compliance with the License.
12 # You may obtain a copy of the License at
13 #
14 # http://www.apache.org/licenses/LICENSE-2.0
15 #
16 # Unless required by applicable law or agreed to in writing, software
17 # distributed under the License is distributed on an "AS IS" BASIS,
18 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 # See the License for the specific language governing permissions and
20 # limitations under the License.
21 """Inference-only OPT model compatible with HuggingFace weights."""
22
23 from collections.abc import Iterable
24 from itertools import islice
25
26 import torch
27 from torch import nn
28 from transformers import OPTConfig
29
30 from vllm.compilation.decorators import support_torch_compile
31 from vllm.config import CacheConfig, VllmConfig
32 from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
33 from vllm.model_executor.layers.activation import get_act_fn
34 from vllm.model_executor.layers.attention import Attention
35 from vllm.model_executor.layers.layernorm import LayerNorm
36 from vllm.model_executor.layers.linear import (
37 ColumnParallelLinear,
38 QKVParallelLinear,
39 ReplicatedLinear,
40 RowParallelLinear,
41 )
42 from vllm.model_executor.layers.logits_processor import LogitsProcessor
43 from vllm.model_executor.layers.quantization import QuantizationConfig
44 from vllm.model_executor.layers.vocab_parallel_embedding import (
45 ParallelLMHead,
46 VocabParallelEmbedding,
47 )
48 from vllm.sequence import IntermediateTensors
49
50 from .interfaces import SupportsLoRA, SupportsPP
51 from .utils import (
52 AutoWeightsLoader,
53 WeightsMapper,
54 make_empty_intermediate_tensors_factory,
55 make_layers,
56 maybe_prefix,
57 )
58
59
60 class OPTLearnedPositionalEmbedding(nn.Embedding):
61 def __init__(self, num_embeddings: int, embedding_dim: int):
62 # OPT is set up so that if padding_idx is specified then offset the
63 # embedding ids by 2 and adjust num_embeddings appropriately. Other
64 # models don't have this hack
65 self.offset = 2
66 super().__init__(num_embeddings + self.offset, embedding_dim)
67
68 def forward(self, positions: torch.Tensor):
69 return super().forward(positions + self.offset)
70
71
72 class OPTAttention(nn.Module):
73 def __init__(
74 self,
75 embed_dim: int,
76 num_heads: int,
77 bias: bool = True,
78 cache_config: CacheConfig | None = None,
79 quant_config: QuantizationConfig | None = None,
80 prefix: str = "",
81 ) -> None:
82 super().__init__()
83 self.embed_dim = embed_dim
84 tensor_model_parallel_world_size = get_tensor_model_parallel_world_size()
85 total_num_heads = num_heads
86 assert num_heads % tensor_model_parallel_world_size == 0
87 self.num_heads = total_num_heads // tensor_model_parallel_world_size
88 self.head_dim = embed_dim // total_num_heads
89 self.scaling = self.head_dim**-0.5
90
91 self.qkv_proj = QKVParallelLinear(
92 embed_dim,
93 self.head_dim,
94 total_num_heads,
95 bias=bias,
96 quant_config=quant_config,
97 prefix=f"{prefix}.qkv_proj",
98 )
99 self.out_proj = RowParallelLinear(
100 embed_dim,
101 embed_dim,
102 bias=bias,
103 quant_config=quant_config,
104 prefix=f"{prefix}.out_proj",
105 )
106 self.attn = Attention(
107 self.num_heads,
108 self.head_dim,
109 scale=self.scaling,
110 cache_config=cache_config,
111 quant_config=quant_config,
112 prefix=f"{prefix}.attn",
113 )
114
115 def forward(
116 self,
117 hidden_states: torch.Tensor,
118 ) -> torch.Tensor:
119 qkv, _ = self.qkv_proj(hidden_states)
120 q, k, v = qkv.chunk(chunks=3, dim=-1)
121 attn_output = self.attn(q, k, v)
122 output, _ = self.out_proj(attn_output)
123 return output
124
125
126 class OPTDecoderLayer(nn.Module):
127 def __init__(
128 self,
129 config: OPTConfig,
130 cache_config: CacheConfig | None = None,
131 quant_config: QuantizationConfig | None = None,
132 prefix: str = "",
133 ):
134 super().__init__()
135 self.config = config
136 self.embed_dim = config.hidden_size
137 self.self_attn = OPTAttention(
138 embed_dim=self.embed_dim,
139 num_heads=config.num_attention_heads,
140 bias=config.enable_bias,
141 cache_config=cache_config,
142 quant_config=quant_config,
143 prefix=f"{prefix}.self_attn",
144 )
145 self.do_layer_norm_before = config.do_layer_norm_before
146
147 self.self_attn_layer_norm = LayerNorm(
148 self.embed_dim, elementwise_affine=config.layer_norm_elementwise_affine
149 )
150 self.fc1 = ColumnParallelLinear(
151 self.embed_dim,
152 config.ffn_dim,
153 bias=config.enable_bias,
154 quant_config=quant_config,
155 prefix=f"{prefix}.fc1",
156 )
157 self.activation_fn = get_act_fn(config.activation_function)
158 self.fc2 = RowParallelLinear(
159 config.ffn_dim,
160 self.embed_dim,
161 bias=config.enable_bias,
162 quant_config=quant_config,
163 prefix=f"{prefix}.fc2",
164 )
165 self.final_layer_norm = LayerNorm(
166 self.embed_dim, elementwise_affine=config.layer_norm_elementwise_affine
167 )
168
169 def forward(
170 self,
171 hidden_states: torch.Tensor,
172 ) -> torch.Tensor:
173 # Self Attention
174 residual = hidden_states
175 # 125m, 1.7B, ..., 175B applies layer norm BEFORE attention
176 if self.do_layer_norm_before:
177 hidden_states = self.self_attn_layer_norm(hidden_states)
178 hidden_states = self.self_attn(hidden_states=hidden_states)
179 hidden_states = residual + hidden_states
180 # 350m applies layer norm AFTER attention
181 if not self.do_layer_norm_before:
182 hidden_states = self.self_attn_layer_norm(hidden_states)
183
184 # Fully Connected
185 residual = hidden_states
186 # 125m, 1.7B, ..., 175B applies layer norm BEFORE attention
187 if self.do_layer_norm_before:
188 hidden_states = self.final_layer_norm(hidden_states)
189 hidden_states, _ = self.fc1(hidden_states)
190 hidden_states = self.activation_fn(hidden_states)
191 hidden_states, _ = self.fc2(hidden_states)
192 hidden_states = residual + hidden_states
193 # 350m applies layer norm AFTER attention
194 if not self.do_layer_norm_before:
195 hidden_states = self.final_layer_norm(hidden_states)
196 return hidden_states
197
198
199 class OPTDecoder(nn.Module):
200 def __init__(
201 self,
202 config: OPTConfig,
203 cache_config: CacheConfig | None = None,
204 quant_config: QuantizationConfig | None = None,
205 prefix: str = "",
206 ):
207 super().__init__()
208 self.config = config
209 self.max_target_positions = config.max_position_embeddings
210 self.vocab_size = config.vocab_size
211
212 self.embed_tokens = VocabParallelEmbedding(
213 config.vocab_size,
214 config.word_embed_proj_dim,
215 )
216 # Positional embeddings are replicated (not sharded).
217 self.embed_positions = OPTLearnedPositionalEmbedding(
218 config.max_position_embeddings, config.hidden_size
219 )
220
221 # Project out & in will be replicated if they exist.
222 self.project_out: ReplicatedLinear | None
223 if config.word_embed_proj_dim != config.hidden_size:
224 self.project_out = ReplicatedLinear(
225 config.hidden_size,
226 config.word_embed_proj_dim,
227 bias=False,
228 quant_config=quant_config,
229 prefix=f"{prefix}.project_out",
230 )
231 else:
232 self.project_out = None
233
234 self.project_in: ReplicatedLinear | None
235 if config.word_embed_proj_dim != config.hidden_size:
236 self.project_in = ReplicatedLinear(
237 config.word_embed_proj_dim,
238 config.hidden_size,
239 bias=False,
240 quant_config=quant_config,
241 prefix=f"{prefix}.project_in",
242 )
243 else:
244 self.project_in = None
245
246 # Note that the only purpose of `config._remove_final_layer_norm` is to
247 # keep backward compatibility with checkpoints that have been fine-tuned
248 # before transformers v4.20.1
249 # see https://github.com/facebookresearch/metaseq/pull/164
250 self.final_layer_norm: LayerNorm | None
251 if config.do_layer_norm_before and not config._remove_final_layer_norm:
252 self.final_layer_norm = LayerNorm(
253 config.hidden_size,
254 elementwise_affine=config.layer_norm_elementwise_affine,
255 )
256 else:
257 self.final_layer_norm = None
258
259 self.start_layer, self.end_layer, self.layers = make_layers(
260 config.num_hidden_layers,
261 lambda prefix: OPTDecoderLayer(
262 config, cache_config, quant_config, prefix=prefix
263 ),
264 prefix=f"{prefix}.layers",
265 )
266
267 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
268 return self.embed_tokens(input_ids)
269
270 def forward(
271 self,
272 input_ids: torch.Tensor | None,
273 positions: torch.Tensor,
274 intermediate_tensors: IntermediateTensors | None,
275 inputs_embeds: torch.Tensor | None = None,
276 ) -> torch.Tensor | IntermediateTensors:
277 if get_pp_group().is_first_rank:
278 if inputs_embeds is None:
279 inputs_embeds = self.embed_input_ids(input_ids)
280 pos_embeds = self.embed_positions(positions)
281 if self.project_in is not None:
282 inputs_embeds, _ = self.project_in(inputs_embeds)
283 hidden_states = inputs_embeds + pos_embeds
284 else:
285 assert intermediate_tensors is not None
286 hidden_states = intermediate_tensors["hidden_states"]
287
288 for layer in islice(self.layers, self.start_layer, self.end_layer):
289 hidden_states = layer(hidden_states)
290
291 if not get_pp_group().is_last_rank:
292 return IntermediateTensors({"hidden_states": hidden_states})
293 if self.final_layer_norm is not None:
294 hidden_states = self.final_layer_norm(hidden_states)
295 if self.project_out is not None:
296 hidden_states, _ = self.project_out(hidden_states)
297 return hidden_states
298
299
300 @support_torch_compile
301 class OPTModel(nn.Module):
302 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
303 super().__init__()
304
305 config = vllm_config.model_config.hf_config
306 cache_config = vllm_config.cache_config
307 quant_config = vllm_config.quant_config
308
309 self.decoder = OPTDecoder(
310 config, cache_config, quant_config, prefix=f"{prefix}.decoder"
311 )
312 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
313 ["hidden_states"], config.hidden_size
314 )
315
316 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
317 return self.decoder.embed_input_ids(input_ids)
318
319 def forward(
320 self,
321 input_ids: torch.Tensor | None,
322 positions: torch.Tensor,
323 intermediate_tensors: IntermediateTensors | None,
324 inputs_embeds: torch.Tensor | None = None,
325 ) -> torch.Tensor | IntermediateTensors:
326 return self.decoder(
327 input_ids, positions, intermediate_tensors, inputs_embeds=inputs_embeds
328 )
329
330
331 class OPTForCausalLM(nn.Module, SupportsPP, SupportsLoRA):
332 hf_to_vllm_mapper = WeightsMapper(
333 orig_to_new_stacked={
334 # weight_name: (param_name, shard_id)
335 ".q_proj": (".qkv_proj", "q"),
336 ".k_proj": (".qkv_proj", "k"),
337 ".v_proj": (".qkv_proj", "v"),
338 },
339 orig_to_new_prefix={
340 "decoder.": "model.decoder.",
341 },
342 )
343 packed_modules_mapping = {
344 "qkv_proj": ["q_proj", "k_proj", "v_proj"],
345 }
346
347 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
348 super().__init__()
349 config = vllm_config.model_config.hf_config
350 quant_config = vllm_config.quant_config
351 self.config = config
352 self.quant_config = quant_config
353 self.model = OPTModel(
354 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
355 )
356 self.lm_head = ParallelLMHead(
357 config.vocab_size,
358 config.word_embed_proj_dim,
359 prefix=maybe_prefix(prefix, "lm_head"),
360 )
361 if self.config.tie_word_embeddings:
362 self.lm_head = self.lm_head.tie_weights(self.model.decoder.embed_tokens)
363 self.logits_processor = LogitsProcessor(config.vocab_size)
364 self.make_empty_intermediate_tensors = (
365 self.model.make_empty_intermediate_tensors
366 )
367
368 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
369 return self.model.embed_input_ids(input_ids)
370
371 def forward(
372 self,
373 input_ids: torch.Tensor | None,
374 positions: torch.Tensor,
375 intermediate_tensors: IntermediateTensors | None = None,
376 inputs_embeds: torch.Tensor | None = None,
377 ) -> torch.Tensor | IntermediateTensors:
378 hidden_states = self.model(
379 input_ids, positions, intermediate_tensors, inputs_embeds
380 )
381 return hidden_states
382
383 def compute_logits(
384 self,
385 hidden_states: torch.Tensor,
386 ) -> torch.Tensor | None:
387 logits = self.logits_processor(self.lm_head, hidden_states)
388 return logits
389
390 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
391 loader = AutoWeightsLoader(self)
392 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)