main
py 416 lines 14.1 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/llama/modeling_llama.py
6 # Copyright 2023 The vLLM team.
7 # Copyright 2022 EleutherAI and the HuggingFace Inc. team. All rights reserved.
8 #
9 # This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
10 # and OPT implementations in this library. It has been modified from its
11 # original forms to accommodate minor architectural differences compared
12 # to GPT-NeoX and OPT used by the Meta AI team that trained the model.
13 #
14 # Licensed under the Apache License, Version 2.0 (the "License");
15 # you may not use this file except in compliance with the License.
16 # You may obtain a copy of the License at
17 #
18 # http://www.apache.org/licenses/LICENSE-2.0
19 #
20 # Unless required by applicable law or agreed to in writing, software
21 # distributed under the License is distributed on an "AS IS" BASIS,
22 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 # See the License for the specific language governing permissions and
24 # limitations under the License.
25 """Inference-only deci model compatible with HuggingFace weights."""
26
27 from collections.abc import Iterable
28 from itertools import islice
29
30 import torch
31 from torch import nn
32 from transformers import LlamaConfig
33
34 from vllm.compilation.decorators import support_torch_compile
35 from vllm.config import CacheConfig, VllmConfig
36 from vllm.distributed import get_pp_group
37 from vllm.model_executor.layers.layernorm import RMSNorm
38 from vllm.model_executor.layers.logits_processor import LogitsProcessor
39 from vllm.model_executor.layers.quantization import QuantizationConfig
40 from vllm.model_executor.layers.rotary_embedding import get_rope
41 from vllm.model_executor.layers.vocab_parallel_embedding import (
42 ParallelLMHead,
43 VocabParallelEmbedding,
44 )
45 from vllm.model_executor.models.llama import LlamaAttention, LlamaMLP
46 from vllm.sequence import IntermediateTensors
47 from vllm.v1.attention.backend import AttentionType
48
49 from .interfaces import HasNoOps, SupportsLoRA, SupportsPP
50 from .utils import (
51 AutoWeightsLoader,
52 PPMissingLayer,
53 WeightsMapper,
54 make_empty_intermediate_tensors_factory,
55 make_layers,
56 maybe_prefix,
57 )
58
59
60 def _ffn_mult_to_intermediate_size(ffn_mult: float, n_embd: int) -> int:
61 # DeciLM-specific code
62 intermediate_size = int(2 * ffn_mult * n_embd / 3)
63 return _find_multiple(intermediate_size, 256)
64
65
66 def _find_multiple(n: int, k: int) -> int:
67 # DeciLM-specific code
68 if n % k == 0:
69 return n
70 return n + k - (n % k)
71
72
73 class DeciLMAttention(LlamaAttention):
74 def __init__(
75 self,
76 config: LlamaConfig,
77 hidden_size: int,
78 num_heads: int,
79 num_kv_heads: int,
80 max_position_embeddings: int = 8192,
81 quant_config: QuantizationConfig | None = None,
82 bias: bool = False,
83 bias_o_proj: bool = False,
84 cache_config: CacheConfig | None = None,
85 prefix: str = "",
86 attn_type: str = AttentionType.DECODER,
87 ) -> None:
88 super().__init__(
89 config,
90 hidden_size,
91 num_heads,
92 num_kv_heads,
93 max_position_embeddings,
94 quant_config,
95 bias,
96 bias_o_proj,
97 cache_config,
98 prefix,
99 attn_type,
100 )
101
102 def _init_rotary_emb(
103 self,
104 config,
105 quant_config: QuantizationConfig | None,
106 ) -> None:
107 # Enables YARN for Mistral and LLaMA4 derivatives.
108 is_neox_style = True
109 if hasattr(config, "position_embedding_type"):
110 is_neox_style = config.position_embedding_type not in [
111 "mistral_yarn",
112 "rope_llama4",
113 ]
114
115 self.rotary_emb = get_rope(
116 self.head_dim,
117 max_position=self.max_position_embeddings,
118 rope_parameters=config.rope_parameters,
119 is_neox_style=is_neox_style,
120 )
121
122
123 class DeciLMDecoderLayer(nn.Module):
124 def __init__(
125 self,
126 config: LlamaConfig,
127 layer_idx: int,
128 cache_config: CacheConfig | None = None,
129 quant_config: QuantizationConfig | None = None,
130 prefix: str = "",
131 ) -> None:
132 super().__init__()
133 block_config = config.block_configs[layer_idx]
134 self._is_no_op_attention = block_config.attention.no_op
135 self._is_no_op_ffn = block_config.ffn.no_op
136
137 self.hidden_size = config.hidden_size
138 max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
139 # Support abacusai/Smaug-72B-v0.1 with attention_bias
140 attention_bias = getattr(config, "attention_bias", False) or getattr(
141 config, "bias", False
142 )
143 bias_o_proj = attention_bias
144 # support internlm/internlm3-8b with qkv_bias
145 if hasattr(config, "qkv_bias"):
146 attention_bias = config.qkv_bias
147
148 if not self._is_no_op_attention:
149 num_kv_heads = (
150 config.num_attention_heads // block_config.attention.n_heads_in_group
151 )
152 self.self_attn = DeciLMAttention(
153 config=config,
154 hidden_size=self.hidden_size,
155 num_heads=config.num_attention_heads,
156 num_kv_heads=num_kv_heads,
157 max_position_embeddings=max_position_embeddings,
158 quant_config=quant_config,
159 bias=attention_bias,
160 bias_o_proj=bias_o_proj,
161 cache_config=cache_config,
162 prefix=f"{prefix}.self_attn",
163 )
164 self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
165
166 if not self._is_no_op_ffn:
167 if hasattr(block_config.ffn, "ffn_mult"):
168 ffn_mult = block_config.ffn.ffn_mult
169 intermediate_size = _ffn_mult_to_intermediate_size(
170 ffn_mult, config.hidden_size
171 )
172 else:
173 intermediate_size = block_config.ffn.intermediate_size
174
175 if hasattr(block_config.ffn, "hidden_act"):
176 hidden_act = block_config.ffn.hidden_act
177 else:
178 hidden_act = config.hidden_act
179
180 self.mlp = LlamaMLP(
181 hidden_size=self.hidden_size,
182 intermediate_size=intermediate_size,
183 hidden_act=hidden_act,
184 quant_config=quant_config,
185 bias=getattr(config, "mlp_bias", False),
186 prefix=f"{prefix}.mlp",
187 )
188 self.post_attention_layernorm = RMSNorm(
189 config.hidden_size, eps=config.rms_norm_eps
190 )
191
192 def forward(
193 self,
194 positions: torch.Tensor,
195 hidden_states: torch.Tensor,
196 residual: torch.Tensor | None,
197 ) -> tuple[torch.Tensor, torch.Tensor]:
198 # Self Attention
199
200 if self._is_no_op_attention:
201 pass
202 else:
203 if residual is None:
204 residual = hidden_states
205 hidden_states = self.input_layernorm(hidden_states)
206 else:
207 hidden_states, residual = self.input_layernorm(hidden_states, residual)
208 hidden_states = self.self_attn(
209 positions=positions,
210 hidden_states=hidden_states,
211 )
212
213 # Fully Connected
214 if not self._is_no_op_ffn:
215 hidden_states, residual = self.post_attention_layernorm(
216 hidden_states, residual
217 )
218 hidden_states = self.mlp(hidden_states)
219 return hidden_states, residual
220
221
222 @support_torch_compile
223 class DeciModel(nn.Module):
224 def __init__(
225 self,
226 *,
227 vllm_config: VllmConfig,
228 prefix: str = "",
229 layer_type: type[DeciLMDecoderLayer] = DeciLMDecoderLayer,
230 ):
231 super().__init__()
232
233 config = vllm_config.model_config.hf_config
234 cache_config = vllm_config.cache_config
235 quant_config = vllm_config.quant_config
236
237 self.config = config
238 self.quant_config = quant_config
239
240 self.vocab_size = config.vocab_size
241
242 if get_pp_group().is_first_rank or (
243 config.tie_word_embeddings and get_pp_group().is_last_rank
244 ):
245 self.embed_tokens = VocabParallelEmbedding(
246 self.vocab_size,
247 config.hidden_size,
248 quant_config=quant_config,
249 )
250 else:
251 self.embed_tokens = PPMissingLayer()
252
253 def get_layer(prefix: str):
254 layer_idx = int(prefix.rsplit(".", 1)[1])
255 return layer_type(
256 config,
257 layer_idx,
258 cache_config,
259 quant_config=quant_config,
260 prefix=prefix,
261 )
262
263 self.start_layer, self.end_layer, self.layers = make_layers(
264 config.num_hidden_layers,
265 get_layer,
266 prefix=f"{prefix}.layers",
267 )
268 if get_pp_group().is_last_rank:
269 self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
270 else:
271 self.norm = PPMissingLayer()
272
273 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
274 ["hidden_states", "residual"], config.hidden_size
275 )
276
277 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
278 return self.embed_tokens(input_ids)
279
280 def forward(
281 self,
282 input_ids: torch.Tensor | None,
283 positions: torch.Tensor,
284 intermediate_tensors: IntermediateTensors | None,
285 inputs_embeds: torch.Tensor | None = None,
286 ) -> torch.Tensor | IntermediateTensors:
287 if get_pp_group().is_first_rank:
288 if inputs_embeds is not None:
289 hidden_states = inputs_embeds
290 else:
291 hidden_states = self.embed_input_ids(input_ids)
292 residual = None
293 else:
294 assert intermediate_tensors is not None
295 hidden_states = intermediate_tensors["hidden_states"]
296 residual = intermediate_tensors["residual"]
297
298 kv_cache_index = 0
299 for layer in islice(self.layers, self.start_layer, self.end_layer):
300 if not layer._is_no_op_attention:
301 hidden_states, residual = layer(positions, hidden_states, residual)
302 kv_cache_index += 1
303 else:
304 hidden_states, residual = layer(positions, hidden_states, residual)
305
306 if not get_pp_group().is_last_rank:
307 return IntermediateTensors(
308 {"hidden_states": hidden_states, "residual": residual}
309 )
310
311 hidden_states, _ = self.norm(hidden_states, residual)
312 return hidden_states
313
314
315 class DeciLMForCausalLM(nn.Module, SupportsLoRA, SupportsPP, HasNoOps):
316 hf_to_vllm_mapper = WeightsMapper(
317 orig_to_new_stacked={
318 # weight_name: (param_name, shard_id)
319 ".q_proj": (".qkv_proj", "q"),
320 ".k_proj": (".qkv_proj", "k"),
321 ".v_proj": (".qkv_proj", "v"),
322 ".gate_proj": (".gate_up_proj", 0),
323 ".up_proj": (".gate_up_proj", 1),
324 }
325 )
326 packed_modules_mapping = {
327 "qkv_proj": ["q_proj", "k_proj", "v_proj"],
328 "gate_up_proj": ["gate_proj", "up_proj"],
329 }
330
331 # LoRA specific attributes
332 embedding_modules = {
333 "embed_tokens": "input_embeddings",
334 "lm_head": "output_embeddings",
335 }
336
337 # Mistral/Llama models can also be loaded with --load-format mistral
338 # from consolidated.safetensors checkpoints
339 mistral_mapping = {
340 "layers": "model.layers",
341 "attention": "self_attn",
342 "wq": "q_proj",
343 "wk": "k_proj",
344 "wv": "v_proj",
345 "wo": "o_proj",
346 "attention_norm": "input_layernorm",
347 "feed_forward": "mlp",
348 "w1": "gate_proj",
349 "w2": "down_proj",
350 "w3": "up_proj",
351 "ffn_norm": "post_attention_layernorm",
352 "tok_embeddings": "model.embed_tokens",
353 "output": "lm_head",
354 "norm": "model.norm",
355 }
356
357 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
358 super().__init__()
359 config = vllm_config.model_config.hf_config
360 quant_config = vllm_config.quant_config
361
362 self.config = config
363
364 self.model = self._init_model(
365 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
366 )
367
368 if get_pp_group().is_last_rank:
369 self.lm_head = ParallelLMHead(
370 config.vocab_size,
371 config.hidden_size,
372 quant_config=quant_config,
373 prefix=maybe_prefix(prefix, "lm_head"),
374 )
375 if config.tie_word_embeddings:
376 self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
377
378 logit_scale = getattr(config, "logit_scale", 1.0)
379 self.logits_processor = LogitsProcessor(
380 config.vocab_size, scale=logit_scale
381 )
382 else:
383 self.lm_head = PPMissingLayer()
384
385 self.make_empty_intermediate_tensors = (
386 self.model.make_empty_intermediate_tensors
387 )
388
389 def _init_model(self, vllm_config: VllmConfig, prefix: str = ""):
390 return DeciModel(vllm_config=vllm_config, prefix=prefix)
391
392 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
393 return self.model.embed_input_ids(input_ids)
394
395 def forward(
396 self,
397 input_ids: torch.Tensor | None,
398 positions: torch.Tensor,
399 intermediate_tensors: IntermediateTensors | None = None,
400 inputs_embeds: torch.Tensor | None = None,
401 ) -> torch.Tensor | IntermediateTensors:
402 model_output = self.model(
403 input_ids, positions, intermediate_tensors, inputs_embeds
404 )
405 return model_output
406
407 def compute_logits(
408 self,
409 hidden_states: torch.Tensor,
410 ) -> torch.Tensor | None:
411 logits = self.logits_processor(self.lm_head, hidden_states)
412 return logits
413
414 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
415 loader = AutoWeightsLoader(self)
416 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)