main
py 585 lines 20.2 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 LLaMA model compatible with HuggingFace weights."""
26
27 from collections.abc import Iterable
28 from itertools import islice
29 from typing import TYPE_CHECKING
30
31 import torch
32 from torch import nn
33 from transformers import LlamaConfig
34
35 from vllm.compilation.decorators import support_torch_compile
36 from vllm.config import CacheConfig, VllmConfig
37 from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
38 from vllm.model_executor.layers.activation import SiluAndMul
39 from vllm.model_executor.layers.attention import (
40 Attention,
41 EncoderOnlyAttention,
42 )
43 from vllm.model_executor.layers.fusion.fused_act_quant import maybe_fused_act_quant
44 from vllm.model_executor.layers.layernorm import RMSNorm
45 from vllm.model_executor.layers.linear import (
46 MergedColumnParallelLinear,
47 QKVParallelLinear,
48 RowParallelLinear,
49 )
50 from vllm.model_executor.layers.logits_processor import LogitsProcessor
51 from vllm.model_executor.layers.quantization import QuantizationConfig
52 from vllm.model_executor.layers.rotary_embedding import get_rope
53 from vllm.model_executor.layers.vocab_parallel_embedding import (
54 ParallelLMHead,
55 VocabParallelEmbedding,
56 )
57 from vllm.sequence import IntermediateTensors
58 from vllm.v1.attention.backend import AttentionType
59
60 from .adapters import as_embedding_model, as_seq_cls_model
61 from .interfaces import (
62 EagleModelMixin,
63 LocalArgmaxMixin,
64 SupportsEagle,
65 SupportsEagle3,
66 SupportsLoRA,
67 SupportsPP,
68 SupportsQuant,
69 )
70 from .utils import (
71 AutoWeightsLoader,
72 PPMissingLayer,
73 WeightsMapper,
74 extract_layer_index,
75 make_empty_intermediate_tensors_factory,
76 make_layers,
77 maybe_prefix,
78 spec_decode_needs_target_embed,
79 )
80
81
82 class LlamaMLP(nn.Module):
83 def __init__(
84 self,
85 hidden_size: int,
86 intermediate_size: int,
87 hidden_act: str,
88 quant_config: QuantizationConfig | None = None,
89 bias: bool = False,
90 prefix: str = "",
91 reduce_results: bool = True,
92 disable_tp: bool = False,
93 ) -> None:
94 super().__init__()
95 self.gate_up_proj = MergedColumnParallelLinear(
96 input_size=hidden_size,
97 output_sizes=[intermediate_size] * 2,
98 bias=bias,
99 quant_config=quant_config,
100 disable_tp=disable_tp,
101 prefix=f"{prefix}.gate_up_proj",
102 )
103 self.down_proj = RowParallelLinear(
104 input_size=intermediate_size,
105 output_size=hidden_size,
106 bias=bias,
107 quant_config=quant_config,
108 reduce_results=reduce_results,
109 disable_tp=disable_tp,
110 prefix=f"{prefix}.down_proj",
111 )
112 if hidden_act != "silu":
113 raise ValueError(
114 f"Unsupported activation: {hidden_act}. Only silu is supported for now."
115 )
116 self.act_fn = SiluAndMul()
117
118 def forward(self, x):
119 x, _ = self.gate_up_proj(x)
120 x = maybe_fused_act_quant(self.act_fn, x, self.down_proj)
121 x, _ = self.down_proj(x)
122 return x
123
124
125 class LlamaAttention(nn.Module):
126 def __init__(
127 self,
128 config: LlamaConfig,
129 hidden_size: int,
130 num_heads: int,
131 num_kv_heads: int,
132 max_position_embeddings: int = 8192,
133 quant_config: QuantizationConfig | None = None,
134 bias: bool = False,
135 bias_o_proj: bool = False,
136 cache_config: CacheConfig | None = None,
137 prefix: str = "",
138 attn_type: str = AttentionType.DECODER,
139 ) -> None:
140 super().__init__()
141 layer_idx = extract_layer_index(prefix)
142 self.hidden_size = hidden_size
143 tp_size = get_tensor_model_parallel_world_size()
144 self.total_num_heads = num_heads
145 assert self.total_num_heads % tp_size == 0
146 self.num_heads = self.total_num_heads // tp_size
147 self.total_num_kv_heads = num_kv_heads
148 if self.total_num_kv_heads >= tp_size:
149 # Number of KV heads is greater than TP size, so we partition
150 # the KV heads across multiple tensor parallel GPUs.
151 assert self.total_num_kv_heads % tp_size == 0
152 else:
153 # Number of KV heads is less than TP size, so we replicate
154 # the KV heads across multiple tensor parallel GPUs.
155 assert tp_size % self.total_num_kv_heads == 0
156 self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
157
158 head_dim = getattr(config, "head_dim", None)
159 self.head_dim = head_dim or self.hidden_size // self.total_num_heads
160 self.q_size = self.num_heads * self.head_dim
161 self.kv_size = self.num_kv_heads * self.head_dim
162 self.scaling = self.head_dim**-0.5
163 self.max_position_embeddings = max_position_embeddings
164
165 self.qkv_proj = QKVParallelLinear(
166 hidden_size=hidden_size,
167 head_size=self.head_dim,
168 total_num_heads=self.total_num_heads,
169 total_num_kv_heads=self.total_num_kv_heads,
170 bias=bias,
171 quant_config=quant_config,
172 prefix=f"{prefix}.qkv_proj",
173 )
174
175 self.o_proj = RowParallelLinear(
176 input_size=self.total_num_heads * self.head_dim,
177 output_size=hidden_size,
178 bias=bias_o_proj,
179 quant_config=quant_config,
180 prefix=f"{prefix}.o_proj",
181 )
182
183 self._init_rotary_emb(config, quant_config=quant_config)
184
185 sliding_window = None
186 if layer_types := getattr(config, "layer_types", None):
187 # Fix for Eagle3 compatibility:
188 # for draft models, subtract target layer count
189 # to get draft-relative layer index starting from 0
190 if hasattr(config, "target_layer_count"):
191 # This is a draft model,
192 # adjust layer_idx to be relative to draft layers
193 effective_layer_idx = layer_idx - config.target_layer_count
194 else:
195 # This is a target model, use layer_idx directly
196 effective_layer_idx = layer_idx
197 assert effective_layer_idx < len(layer_types), (
198 f"effective_layer_idx: {effective_layer_idx} "
199 f"is out of bounds for layer_types: {layer_types}"
200 )
201
202 is_sliding = layer_types[effective_layer_idx] == "sliding_attention"
203 if is_sliding:
204 sliding_window = config.sliding_window
205
206 attn_cls = (
207 EncoderOnlyAttention
208 if attn_type == AttentionType.ENCODER_ONLY
209 else Attention
210 )
211
212 self.attn = attn_cls(
213 self.num_heads,
214 self.head_dim,
215 self.scaling,
216 num_kv_heads=self.num_kv_heads,
217 cache_config=cache_config,
218 quant_config=quant_config,
219 per_layer_sliding_window=sliding_window,
220 attn_type=attn_type,
221 prefix=f"{prefix}.attn",
222 )
223
224 def forward(
225 self,
226 positions: torch.Tensor,
227 hidden_states: torch.Tensor,
228 ) -> torch.Tensor:
229 qkv, _ = self.qkv_proj(hidden_states)
230 q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
231 q, k = self.rotary_emb(positions, q, k)
232 attn_output = self.attn(q, k, v)
233 output, _ = self.o_proj(attn_output)
234 return output
235
236 def _init_rotary_emb(
237 self,
238 config: LlamaConfig,
239 quant_config: QuantizationConfig | None,
240 ) -> None:
241 is_neox_style = True
242
243 self.rotary_emb = get_rope(
244 self.head_dim,
245 max_position=self.max_position_embeddings,
246 rope_parameters=getattr(config, "rope_parameters", None),
247 is_neox_style=is_neox_style,
248 )
249
250
251 class LlamaDecoderLayer(nn.Module):
252 def __init__(
253 self,
254 vllm_config: VllmConfig,
255 prefix: str = "",
256 config: LlamaConfig | None = None,
257 attn_layer_type: type[nn.Module] = LlamaAttention,
258 ) -> None:
259 super().__init__()
260
261 config = config or vllm_config.model_config.hf_config
262 cache_config = vllm_config.cache_config
263 quant_config = self.get_quant_config(vllm_config)
264
265 self.hidden_size = config.hidden_size
266 max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
267 # Support abacusai/Smaug-72B-v0.1 with attention_bias
268 attention_bias = getattr(config, "attention_bias", False) or getattr(
269 config, "bias", False
270 )
271 bias_o_proj = attention_bias
272 # support internlm/internlm3-8b with qkv_bias
273 if hasattr(config, "qkv_bias"):
274 attention_bias = config.qkv_bias
275
276 # By default, Llama uses causal attention as it is a decoder-only model.
277 # You can override the HF config with `is_causal=False` to enable
278 # bidirectional attention, which is used in some embedding models
279 # (e.g. nvidia/llama-nemotron-embed-1b-v2)
280 if getattr(config, "is_causal", True):
281 attn_type = AttentionType.DECODER
282 else:
283 attn_type = AttentionType.ENCODER_ONLY
284
285 self.self_attn = attn_layer_type(
286 config=config,
287 hidden_size=self.hidden_size,
288 num_heads=config.num_attention_heads,
289 num_kv_heads=getattr(
290 config, "num_key_value_heads", config.num_attention_heads
291 ),
292 max_position_embeddings=max_position_embeddings,
293 quant_config=quant_config,
294 bias=attention_bias,
295 bias_o_proj=bias_o_proj,
296 cache_config=cache_config,
297 prefix=f"{prefix}.self_attn",
298 attn_type=attn_type,
299 )
300 self.mlp = LlamaMLP(
301 hidden_size=self.hidden_size,
302 intermediate_size=config.intermediate_size,
303 hidden_act=config.hidden_act,
304 quant_config=quant_config,
305 bias=getattr(config, "mlp_bias", False),
306 prefix=f"{prefix}.mlp",
307 )
308 self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
309 self.post_attention_layernorm = RMSNorm(
310 config.hidden_size, eps=config.rms_norm_eps
311 )
312
313 def forward(
314 self,
315 positions: torch.Tensor,
316 hidden_states: torch.Tensor,
317 residual: torch.Tensor | None,
318 ) -> tuple[torch.Tensor, torch.Tensor]:
319 # Self Attention
320 if residual is None:
321 residual = hidden_states
322 hidden_states = self.input_layernorm(hidden_states)
323 else:
324 hidden_states, residual = self.input_layernorm(hidden_states, residual)
325 hidden_states = self.self_attn(positions=positions, hidden_states=hidden_states)
326
327 # Fully Connected
328 hidden_states, residual = self.post_attention_layernorm(hidden_states, residual)
329 hidden_states = self.mlp(hidden_states)
330 return hidden_states, residual
331
332 def get_quant_config(self, vllm_config: VllmConfig) -> QuantizationConfig | None:
333 """Get quantization config for this layer. Override in subclasses."""
334 return vllm_config.quant_config
335
336
337 @support_torch_compile(
338 # TODO[#32068]: Investigate recompilation
339 # mark_unbacked_dims={"input_ids": 0},
340 dynamic_arg_dims={
341 "input_ids": {0: "b"},
342 "positions": {0: "b"},
343 "intermediate_tensors": {0: "b"},
344 "inputs_embeds": {0: "b"},
345 },
346 )
347 class LlamaModel(nn.Module, EagleModelMixin):
348 hf_to_vllm_mapper = WeightsMapper(
349 orig_to_new_stacked={
350 # weight_name: (param_name, shard_id)
351 ".q_proj": (".qkv_proj", "q"),
352 ".k_proj": (".qkv_proj", "k"),
353 ".v_proj": (".qkv_proj", "v"),
354 ".gate_proj": (".gate_up_proj", 0),
355 ".up_proj": (".gate_up_proj", 1),
356 }
357 )
358 supports_aux_hidden_states_over_pp = True
359
360 def __init__(
361 self,
362 *,
363 vllm_config: VllmConfig,
364 prefix: str = "",
365 layer_type: type[nn.Module] = LlamaDecoderLayer,
366 ):
367 super().__init__()
368
369 config = vllm_config.model_config.hf_config
370 quant_config = vllm_config.quant_config
371
372 self.config = config
373 self.quant_config = quant_config
374
375 self.vocab_size = config.vocab_size
376
377 if (
378 get_pp_group().is_first_rank
379 or (config.tie_word_embeddings and get_pp_group().is_last_rank)
380 or spec_decode_needs_target_embed(vllm_config)
381 ):
382 self.embed_tokens = VocabParallelEmbedding(
383 self.vocab_size,
384 config.hidden_size,
385 quant_config=quant_config,
386 )
387 else:
388 self.embed_tokens = PPMissingLayer()
389 self.start_layer, self.end_layer, self.layers = make_layers(
390 config.num_hidden_layers,
391 lambda prefix: layer_type(vllm_config=vllm_config, prefix=prefix),
392 prefix=f"{prefix}.layers",
393 )
394 if get_pp_group().is_last_rank:
395 self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
396 else:
397 self.norm = PPMissingLayer()
398
399 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
400 ["hidden_states", "residual"], config.hidden_size
401 )
402
403 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
404 return self.embed_tokens(input_ids)
405
406 def forward(
407 self,
408 input_ids: torch.Tensor | None,
409 positions: torch.Tensor,
410 intermediate_tensors: IntermediateTensors | None,
411 inputs_embeds: torch.Tensor | None = None,
412 **extra_layer_kwargs,
413 ) -> torch.Tensor | IntermediateTensors | tuple[torch.Tensor, list[torch.Tensor]]:
414 if get_pp_group().is_first_rank:
415 if inputs_embeds is not None:
416 hidden_states = inputs_embeds
417 else:
418 hidden_states = self.embed_input_ids(input_ids)
419 residual = None
420 else:
421 assert intermediate_tensors is not None
422 hidden_states = intermediate_tensors["hidden_states"]
423 residual = intermediate_tensors["residual"]
424
425 remote_aux = self.collect_remote_aux_hidden_states(intermediate_tensors)
426
427 aux_hidden_states: list[torch.Tensor] = []
428 if get_pp_group().is_first_rank:
429 self._maybe_add_hidden_state(
430 aux_hidden_states, self.start_layer, hidden_states, residual
431 )
432 for idx, layer in enumerate(
433 islice(self.layers, self.start_layer, self.end_layer),
434 start=self.start_layer,
435 ):
436 hidden_states, residual = layer(
437 positions, hidden_states, residual, **extra_layer_kwargs
438 )
439 self._maybe_add_hidden_state(
440 aux_hidden_states, idx + 1, hidden_states, residual
441 )
442
443 if not get_pp_group().is_last_rank:
444 return IntermediateTensors(
445 {
446 "hidden_states": hidden_states,
447 "residual": residual,
448 **self.pack_local_aux_hidden_states(aux_hidden_states),
449 }
450 )
451
452 hidden_states, _ = self.norm(hidden_states, residual)
453
454 aux_hidden_states = remote_aux + aux_hidden_states
455 if len(aux_hidden_states) > 0:
456 return hidden_states, aux_hidden_states
457 return hidden_states
458
459 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
460 loader = AutoWeightsLoader(self)
461 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
462
463
464 class LlamaForCausalLM(
465 LocalArgmaxMixin,
466 nn.Module,
467 SupportsLoRA,
468 SupportsPP,
469 SupportsEagle,
470 SupportsEagle3,
471 SupportsQuant,
472 ):
473 hf_to_vllm_mapper = LlamaModel.hf_to_vllm_mapper
474 # LoRA specific attributes
475 packed_modules_mapping = {
476 "qkv_proj": ["q_proj", "k_proj", "v_proj"],
477 "gate_up_proj": ["gate_proj", "up_proj"],
478 }
479 embedding_modules = {
480 "embed_tokens": "input_embeddings",
481 "lm_head": "output_embeddings",
482 }
483
484 def __init__(
485 self,
486 *,
487 vllm_config: VllmConfig,
488 prefix: str = "",
489 layer_type: type[nn.Module] = LlamaDecoderLayer,
490 ):
491 super().__init__()
492 config = vllm_config.model_config.hf_config
493 quant_config = vllm_config.quant_config
494 self.config = config
495
496 self.model = self._init_model(
497 vllm_config=vllm_config,
498 prefix=maybe_prefix(prefix, "model"),
499 layer_type=layer_type,
500 )
501
502 if get_pp_group().is_last_rank:
503 self.lm_head = ParallelLMHead(
504 config.vocab_size,
505 config.hidden_size,
506 quant_config=quant_config,
507 prefix=maybe_prefix(prefix, "lm_head"),
508 )
509 if config.tie_word_embeddings:
510 self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
511
512 logit_scale = getattr(config, "logit_scale", 1.0)
513 self.logits_processor = LogitsProcessor(
514 config.vocab_size, scale=logit_scale
515 )
516 else:
517 self.lm_head = PPMissingLayer()
518
519 self.make_empty_intermediate_tensors = (
520 self.model.make_empty_intermediate_tensors
521 )
522
523 def _init_model(
524 self,
525 vllm_config: VllmConfig,
526 prefix: str = "",
527 layer_type: type[nn.Module] = LlamaDecoderLayer,
528 ):
529 return LlamaModel(vllm_config=vllm_config, prefix=prefix, layer_type=layer_type)
530
531 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
532 return self.model.embed_input_ids(input_ids)
533
534 def forward(
535 self,
536 input_ids: torch.Tensor | None,
537 positions: torch.Tensor,
538 intermediate_tensors: IntermediateTensors | None = None,
539 inputs_embeds: torch.Tensor | None = None,
540 ) -> torch.Tensor | IntermediateTensors:
541 model_output = self.model(
542 input_ids, positions, intermediate_tensors, inputs_embeds
543 )
544 return model_output
545
546 def compute_logits(
547 self,
548 hidden_states: torch.Tensor,
549 ) -> torch.Tensor | None:
550 logits = self.logits_processor(self.lm_head, hidden_states)
551 return logits
552
553 def compute_logits_local(
554 self,
555 hidden_states: torch.Tensor,
556 ) -> torch.Tensor:
557 return self.logits_processor(self.lm_head, hidden_states, skip_gather=True)
558
559 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
560 loader = AutoWeightsLoader(self)
561 return loader.load_weights(weights)
562
563
564 if TYPE_CHECKING:
565 _LlamaBidirectionalForSequenceClassificationBase = LlamaForCausalLM
566 _LlamaBidirectionalModelBase = LlamaForCausalLM
567 else:
568 _LlamaBidirectionalForSequenceClassificationBase = as_seq_cls_model(
569 LlamaForCausalLM
570 )
571 _LlamaBidirectionalModelBase = as_embedding_model(LlamaForCausalLM)
572
573
574 class LlamaBidirectionalForSequenceClassification(
575 _LlamaBidirectionalForSequenceClassificationBase
576 ):
577 # This class sets the correct attention type and pooling type
578 # through LlamaBidirectionalConfig.
579 pass
580
581
582 class LlamaBidirectionalModel(_LlamaBidirectionalModelBase):
583 # This class sets the correct attention type and pooling type
584 # through LlamaBidirectionalConfig.
585 pass