main
py 648 lines 22.4 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Inference-only FalconH1 model."""
4
5 from collections.abc import Iterable
6 from itertools import islice
7
8 import torch
9 from torch import nn
10 from transformers import FalconH1Config
11
12 from vllm.compilation.decorators import support_torch_compile
13 from vllm.config import CacheConfig, ModelConfig, VllmConfig
14 from vllm.distributed import get_tensor_model_parallel_world_size
15 from vllm.distributed.parallel_state import get_pp_group
16 from vllm.model_executor.layers.activation import SiluAndMul
17 from vllm.model_executor.layers.attention import Attention
18 from vllm.model_executor.layers.layernorm import RMSNorm
19 from vllm.model_executor.layers.linear import (
20 MergedColumnParallelLinear,
21 QKVParallelLinear,
22 RowParallelLinear,
23 )
24 from vllm.model_executor.layers.logits_processor import LogitsProcessor
25 from vllm.model_executor.layers.mamba.mamba_mixer2 import MambaMixer2
26 from vllm.model_executor.layers.mamba.mamba_utils import (
27 MambaStateCopyFunc,
28 MambaStateCopyFuncCalculator,
29 MambaStateDtypeCalculator,
30 MambaStateShapeCalculator,
31 )
32 from vllm.model_executor.layers.quantization import QuantizationConfig
33 from vllm.model_executor.layers.rotary_embedding import get_rope
34 from vllm.model_executor.layers.vocab_parallel_embedding import (
35 ParallelLMHead,
36 VocabParallelEmbedding,
37 )
38 from vllm.sequence import IntermediateTensors
39 from vllm.transformers_utils.config import set_default_rope_theta
40
41 from .interfaces import (
42 HasInnerState,
43 IsHybrid,
44 SupportsLoRA,
45 SupportsMambaPrefixCaching,
46 SupportsPP,
47 )
48 from .utils import (
49 AutoWeightsLoader,
50 PPMissingLayer,
51 WeightsMapper,
52 make_empty_intermediate_tensors_factory,
53 make_layers,
54 maybe_prefix,
55 )
56
57
58 class FalconH1MLP(nn.Module):
59 def __init__(
60 self,
61 config: FalconH1Config,
62 quant_config: QuantizationConfig | None = None,
63 bias: bool = False,
64 prefix: str = "",
65 ) -> None:
66 super().__init__()
67 self.gate_up_proj = MergedColumnParallelLinear(
68 input_size=config.hidden_size,
69 output_sizes=[config.intermediate_size] * 2,
70 bias=bias,
71 quant_config=quant_config,
72 prefix=f"{prefix}.gate_up_proj",
73 )
74 self.down_proj = RowParallelLinear(
75 input_size=config.intermediate_size,
76 output_size=config.hidden_size,
77 bias=bias,
78 quant_config=quant_config,
79 prefix=f"{prefix}.down_proj",
80 )
81 self.tp_size = get_tensor_model_parallel_world_size()
82 self.intermediate_size = config.intermediate_size
83 self.gate_multiplier, self.down_multiplier = config.mlp_multipliers
84 if config.hidden_act != "silu":
85 raise ValueError(
86 f"Unsupported activation: {config.hidden_act}. "
87 "Only silu is supported for now."
88 )
89 self.act_fn = SiluAndMul()
90
91 def forward(self, x):
92 x, _ = self.gate_up_proj(x)
93 x[:, : self.intermediate_size // self.tp_size] *= self.gate_multiplier
94 x = self.act_fn(x)
95 x, _ = self.down_proj(x)
96 x = x * self.down_multiplier
97 return x
98
99
100 class FalconH1SSMDecoderLayer(nn.Module):
101 def __init__(
102 self,
103 config: FalconH1Config,
104 model_config: ModelConfig | None = None,
105 cache_config: CacheConfig | None = None,
106 quant_config: QuantizationConfig | None = None,
107 prefix: str = "",
108 ) -> None:
109 super().__init__()
110 self.config = config
111 self.tp_size = get_tensor_model_parallel_world_size()
112
113 self.d_ssm = (
114 int(config.mamba_expand * config.hidden_size)
115 if config.mamba_d_ssm is None
116 else config.mamba_d_ssm
117 )
118
119 self.mamba = MambaMixer2(
120 hidden_size=config.hidden_size,
121 ssm_state_size=config.mamba_d_state,
122 conv_kernel_size=config.mamba_d_conv,
123 intermediate_size=self.d_ssm,
124 use_conv_bias=config.mamba_conv_bias,
125 use_bias=config.mamba_proj_bias,
126 n_groups=config.mamba_n_groups,
127 num_heads=config.mamba_n_heads,
128 head_dim=config.mamba_d_head,
129 rms_norm_eps=config.rms_norm_eps,
130 activation=config.hidden_act,
131 model_config=model_config,
132 cache_config=cache_config,
133 quant_config=quant_config,
134 use_rms_norm=config.mamba_rms_norm,
135 prefix=f"{prefix}.mixer",
136 )
137 # n_groups is overridden later by `MambaMixer2`
138 self.groups_time_state_size = self.mamba.n_groups * config.mamba_d_state
139 self.zxbcdt_multipliers = config.ssm_multipliers
140 self._init_mup_vector()
141
142 def _init_mup_vector(self):
143 """Non learnable per-block scaling vector composed of element-wise
144 multipliersapplied to each separate contiguous block of the output
145 of the linear projection (in_proj) before further processing
146 (gating, convolution, SSM):
147
148 - Z block: [0 : d_ssm] → zxbcdt_multipliers[0]
149 - X block: [d_ssm : 2 * d_ssm] → zxbcdt_multipliers[1]
150 - B block: [2 * d_ssm : 2 * d_ssm + G * S] → zxbcdt_multipliers[2]
151 - C block: [2 * d_ssm + G * S : 2 * d_ssm + 2 * G * S]
152 → zxbcdt_multipliers[3]
153 - dt block: [2 * d_ssm + 2 * G * S : end] → zxbcdt_multipliers[4]
154
155 where:
156 - d_ssm: Dimension of state-space model latent
157 - G: Number of groups (n_groups)
158 - S: SSM state size per group
159 - All indices are divided by tp_size to support tensor parallelism
160 """
161 vector_shape = (
162 2 * self.d_ssm + 2 * self.groups_time_state_size + self.config.mamba_n_heads
163 ) // self.tp_size
164 mup_vector = torch.ones(1, vector_shape)
165 # Z vector 0 -> d_ssm
166 mup_vector[:, : self.d_ssm // self.tp_size] *= self.zxbcdt_multipliers[0]
167 # X vector d_ssm -> 2 * d_ssm
168 mup_vector[
169 :, (self.d_ssm // self.tp_size) : (2 * self.d_ssm // self.tp_size)
170 ] *= self.zxbcdt_multipliers[1]
171 # B vector 2 * d_ssm -> 2 * d_ssm + (n_group * d_state)
172 mup_vector[
173 :,
174 (2 * self.d_ssm) // self.tp_size : (
175 2 * self.d_ssm + self.groups_time_state_size
176 )
177 // self.tp_size,
178 ] *= self.zxbcdt_multipliers[2]
179 # C vector 2 * d_ssm + (n_group * d_state)
180 # -> 2 * d_ssm + 2 * (n_group * d_state)
181 mup_vector[
182 :,
183 (2 * self.d_ssm + self.groups_time_state_size) // self.tp_size : (
184 2 * self.d_ssm + 2 * self.groups_time_state_size
185 )
186 // self.tp_size,
187 ] *= self.zxbcdt_multipliers[3]
188 # dt vector 2 * d_ssm + 2 * (n_group * d_state)
189 # -> 2 * d_ssm + 2 * (n_group * d_state) + n_heads
190 mup_vector[
191 :,
192 (2 * self.d_ssm + 2 * self.groups_time_state_size) // self.tp_size :,
193 ] *= self.zxbcdt_multipliers[4]
194
195 self.register_buffer("mup_vector", mup_vector, persistent=False)
196
197 def forward(
198 self,
199 hidden_states: torch.Tensor,
200 residual: torch.Tensor | None,
201 **kwargs,
202 ):
203 output = self.mamba(
204 hidden_states,
205 mup_vector=self.mup_vector,
206 )
207 return output, residual
208
209
210 class FalconH1AttentionDecoderLayer(nn.Module):
211 def __init__(
212 self,
213 config: FalconH1Config,
214 cache_config: CacheConfig | None = None,
215 quant_config: QuantizationConfig | None = None,
216 prefix: str = "",
217 ) -> None:
218 super().__init__()
219 set_default_rope_theta(config, default_theta=1e11)
220 max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
221 self.hidden_size = config.hidden_size
222 tp_size = get_tensor_model_parallel_world_size()
223 self.total_num_heads = config.num_attention_heads
224 assert self.total_num_heads % tp_size == 0
225 self.num_heads = self.total_num_heads // tp_size
226 self.total_num_kv_heads = config.num_key_value_heads
227 if self.total_num_kv_heads >= tp_size:
228 # Number of KV heads is greater than TP size, so we partition
229 # the KV heads across multiple tensor parallel GPUs.
230 assert self.total_num_kv_heads % tp_size == 0
231 else:
232 # Number of KV heads is less than TP size, so we replicate
233 # the KV heads across multiple tensor parallel GPUs.
234 assert tp_size % self.total_num_kv_heads == 0
235 self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
236 self.head_dim = (
237 config.hidden_size // self.total_num_heads
238 if getattr(config, "head_dim", None) is None
239 else config.head_dim
240 )
241 self.q_size = self.num_heads * self.head_dim
242 self.kv_size = self.num_kv_heads * self.head_dim
243 self.scaling = self.head_dim**-0.5
244 self.max_position_embeddings = max_position_embeddings
245
246 rotary_dim = getattr(config, "attn_rotary_emb", self.head_dim)
247 config.rope_parameters["partial_rotary_factor"] = rotary_dim / self.head_dim
248
249 self.rotary_emb = get_rope(
250 head_size=self.head_dim,
251 max_position=max_position_embeddings,
252 rope_parameters=config.rope_parameters,
253 is_neox_style=True,
254 dtype=None, # see impl of get_rope
255 )
256
257 self.qkv_proj = QKVParallelLinear(
258 config.hidden_size,
259 self.head_dim,
260 self.total_num_heads,
261 self.total_num_kv_heads,
262 bias=False,
263 quant_config=quant_config,
264 prefix=f"{prefix}.qkv_proj",
265 )
266 self.o_proj = RowParallelLinear(
267 self.total_num_heads * self.head_dim,
268 config.hidden_size,
269 bias=False,
270 quant_config=quant_config,
271 prefix=f"{prefix}.o_proj",
272 )
273
274 self.attn = Attention(
275 self.num_heads,
276 self.head_dim,
277 self.scaling,
278 num_kv_heads=self.num_kv_heads,
279 cache_config=cache_config,
280 quant_config=quant_config,
281 prefix=f"{prefix}.attn",
282 )
283 self.key_multiplier = config.key_multiplier
284
285 def self_attention(
286 self,
287 positions: torch.Tensor,
288 hidden_states: torch.Tensor,
289 **kwargs,
290 ) -> torch.Tensor:
291 qkv, _ = self.qkv_proj(hidden_states)
292 q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
293 k = k * self.key_multiplier
294
295 q, k = self.rotary_emb(positions, q, k)
296 attn_output = self.attn(q, k, v)
297 output, _ = self.o_proj(attn_output)
298 return output
299
300 def forward(
301 self,
302 positions: torch.Tensor,
303 hidden_states: torch.Tensor,
304 residual: torch.Tensor | None,
305 **kwargs,
306 ):
307 hidden_states = self.self_attention(
308 positions=positions,
309 hidden_states=hidden_states,
310 )
311 return hidden_states, residual
312
313
314 class FalconH1ParallelHybrid(nn.Module):
315 """A hybrid decoder layer for FalconH1 where the input is processed
316 in parallel through both the self-attention branch and the SSM (Mamba)
317 branch. Their outputs are then summed to produce the final hidden state.
318
319 This layer uses:
320 - FalconH1AttentionDecoderLayer for the multi-head self-attention branch.
321 - FalconH1SSMDecoderLayer for the state-space (Mamba) branch.
322 """
323
324 def __init__(
325 self,
326 config: FalconH1Config,
327 layer_idx: int,
328 model_config: ModelConfig | None = None,
329 cache_config: CacheConfig | None = None,
330 quant_config: QuantizationConfig | None = None,
331 prefix: str = "",
332 ) -> None:
333 super().__init__()
334
335 # Instantiate the attention branch
336 self.self_attn = FalconH1AttentionDecoderLayer(
337 config=config,
338 cache_config=cache_config,
339 quant_config=quant_config,
340 prefix=prefix,
341 )
342
343 # In V1 all attention/ssm layers must have
344 # different index in prefix
345 ssm_layer_idx = config.num_hidden_layers + layer_idx
346 ssm_prefix = prefix.split(".")[0] + f".{ssm_layer_idx}"
347
348 # Instantiate the SSM branch
349 self.mamba = FalconH1SSMDecoderLayer(
350 config=config,
351 model_config=model_config,
352 cache_config=cache_config,
353 quant_config=quant_config,
354 prefix=ssm_prefix,
355 )
356 self.ssm_out_multiplier = config.ssm_out_multiplier
357 self.ssm_in_multiplier = config.ssm_in_multiplier
358
359 self.attention_in_multiplier = config.attention_in_multiplier
360 self.attn_out_multiplier = config.attention_out_multiplier
361
362 self.feed_forward = FalconH1MLP(
363 config, quant_config=quant_config, prefix=f"{prefix}.feed_forward"
364 )
365
366 self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
367 self.pre_ff_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
368
369 def forward(
370 self,
371 positions: torch.Tensor,
372 hidden_states: torch.Tensor,
373 **kwargs,
374 ):
375 residual = hidden_states
376 hidden_states = self.input_layernorm(hidden_states)
377 # Process input through the attention branch.
378 # FalconH1AttentionDecoderLayer expects positions, hidden_states,
379 # kv_cache, attn_metadata, and residual.
380 attn_hidden, _ = self.self_attn(
381 positions=positions,
382 hidden_states=hidden_states * self.attention_in_multiplier,
383 residual=residual,
384 **kwargs,
385 )
386
387 # Process input through the SSM branch.
388 # FalconH1SSMDecoderLayer expects hidden_states, attn_metadata,
389 # residual, and sequence_idx.
390 ssm_hidden, _ = self.mamba(
391 hidden_states=hidden_states * self.ssm_in_multiplier,
392 residual=residual,
393 **kwargs,
394 )
395 # Sum the outputs from both branches.
396 # We assume both branches produce outputs of the same
397 # dimensionality (config.hidden_size).
398 hidden_states = (attn_hidden * self.attn_out_multiplier) + (
399 ssm_hidden * self.ssm_out_multiplier
400 )
401 hidden_states = hidden_states + residual
402
403 # feed-forward
404 residual = hidden_states
405 hidden_states = self.pre_ff_layernorm(hidden_states)
406 hidden_states = self.feed_forward(hidden_states)
407 hidden_states = residual + hidden_states
408
409 return hidden_states
410
411
412 @support_torch_compile
413 class FalconH1Model(nn.Module):
414 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
415 super().__init__()
416 config: FalconH1Config = vllm_config.model_config.hf_config
417 model_config = vllm_config.model_config
418 cache_config = vllm_config.cache_config
419 quant_config = vllm_config.quant_config
420
421 self.config = config
422
423 self.vocab_size = config.vocab_size
424
425 if get_pp_group().is_first_rank:
426 self.embed_tokens = VocabParallelEmbedding(
427 self.vocab_size,
428 config.hidden_size,
429 )
430 self.embedding_multiplier = config.embedding_multiplier
431 else:
432 self.embed_tokens = PPMissingLayer()
433 self.embedding_multiplier = 1.0
434
435 def get_layer(prefix: str):
436 layer_idx = int(prefix.rsplit(".", 1)[1])
437 layer_class = FalconH1ParallelHybrid
438 return layer_class(
439 config,
440 layer_idx,
441 model_config,
442 cache_config,
443 quant_config=quant_config,
444 prefix=prefix,
445 )
446
447 self.start_layer, self.end_layer, self.layers = make_layers(
448 config.num_hidden_layers, get_layer, prefix=f"{prefix}.layers"
449 )
450 # FalconH1ParallelHybrid recomputes residual internally each layer,
451 # it is never threaded across the PP boundary.
452 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
453 ["hidden_states"], config.hidden_size
454 )
455 if get_pp_group().is_last_rank:
456 self.final_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
457 else:
458 self.final_layernorm = PPMissingLayer()
459
460 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
461 return self.embed_tokens(input_ids)
462
463 def forward(
464 self,
465 input_ids: torch.Tensor | None,
466 positions: torch.Tensor,
467 intermediate_tensors: IntermediateTensors | None = None,
468 inputs_embeds: torch.Tensor | None = None,
469 ) -> torch.Tensor:
470 if get_pp_group().is_first_rank:
471 if inputs_embeds is not None:
472 hidden_states = inputs_embeds * self.embedding_multiplier
473 else:
474 hidden_states = (
475 self.embed_input_ids(input_ids) * self.embedding_multiplier
476 )
477 else:
478 assert intermediate_tensors is not None
479 hidden_states = intermediate_tensors["hidden_states"]
480
481 for layer in islice(self.layers, self.start_layer, self.end_layer):
482 hidden_states = layer(
483 positions=positions,
484 hidden_states=hidden_states,
485 )
486 if not get_pp_group().is_last_rank:
487 return IntermediateTensors(
488 {
489 "hidden_states": hidden_states,
490 }
491 )
492 hidden_states = self.final_layernorm(hidden_states)
493 return hidden_states
494
495
496 class FalconH1ForCausalLM(
497 nn.Module,
498 HasInnerState,
499 SupportsLoRA,
500 SupportsPP,
501 IsHybrid,
502 SupportsMambaPrefixCaching,
503 ):
504 packed_modules_mapping = {
505 "qkv_proj": ["q_proj", "k_proj", "v_proj"],
506 "gate_up_proj": ["gate_proj", "up_proj"],
507 }
508
509 hf_to_vllm_mapper = WeightsMapper(
510 orig_to_new_substr={
511 "A_log": "A",
512 "mamba": "mamba.mamba",
513 },
514 orig_to_new_stacked={
515 ".q_proj": (".qkv_proj", "q"),
516 ".k_proj": (".qkv_proj", "k"),
517 ".v_proj": (".qkv_proj", "v"),
518 ".gate_proj": (".gate_up_proj", 0),
519 ".up_proj": (".gate_up_proj", 1),
520 },
521 )
522
523 embedding_modules = {
524 "embed_tokens": "input_embeddings",
525 "lm_head": "output_embeddings",
526 }
527
528 @classmethod
529 def get_mamba_state_dtype_from_config(
530 cls,
531 vllm_config: "VllmConfig",
532 ) -> tuple[torch.dtype, torch.dtype]:
533 return MambaStateDtypeCalculator.mamba2_state_dtype(
534 vllm_config.model_config.dtype,
535 vllm_config.cache_config.mamba_cache_dtype,
536 vllm_config.cache_config.mamba_ssm_cache_dtype,
537 )
538
539 @classmethod
540 def get_mamba_state_shape_from_config(
541 cls,
542 vllm_config: "VllmConfig",
543 ) -> tuple[tuple[int, int], tuple[int, int, int]]:
544 """Calculate shapes for Mamba's convolutional and state caches.
545
546 Args:
547 vllm_config: vLLM config
548
549 Returns:
550 Tuple containing:
551 - conv_state_shape: Shape for convolutional state cache
552 - temporal_state_shape: Shape for state space model cache
553
554 """
555 parallel_config = vllm_config.parallel_config
556 hf_config = vllm_config.model_config.hf_config
557
558 intermediate_size = (
559 int(hf_config.mamba_expand * hf_config.hidden_size)
560 if hf_config.mamba_d_ssm is None
561 else hf_config.mamba_d_ssm
562 )
563
564 return MambaStateShapeCalculator.mamba2_state_shape(
565 intermediate_size=intermediate_size,
566 tp_world_size=parallel_config.tensor_parallel_size,
567 n_groups=hf_config.mamba_n_groups,
568 num_heads=hf_config.mamba_n_heads,
569 head_dim=hf_config.mamba_d_head,
570 state_size=hf_config.mamba_d_state,
571 conv_kernel=hf_config.mamba_d_conv,
572 )
573
574 @classmethod
575 def get_mamba_state_copy_func(cls) -> tuple[MambaStateCopyFunc, MambaStateCopyFunc]:
576 return MambaStateCopyFuncCalculator.mamba2_state_copy_func()
577
578 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
579 config = vllm_config.model_config.hf_config
580 self.vllm_config = vllm_config
581 self.model_config = vllm_config.model_config
582
583 scheduler_config = vllm_config.scheduler_config
584
585 self.quant_config = vllm_config.quant_config
586
587 super().__init__()
588 self.config = config
589 self.scheduler_config = scheduler_config
590 self.model = FalconH1Model(
591 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
592 )
593 self.tie_word_embeddings = config.tie_word_embeddings
594
595 if get_pp_group().is_last_rank:
596 self.lm_head = ParallelLMHead(
597 config.vocab_size,
598 config.hidden_size,
599 prefix=maybe_prefix(prefix, "lm_head"),
600 )
601 self.lm_head_multiplier = config.lm_head_multiplier
602 if self.tie_word_embeddings:
603 self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
604 # Used to track and store by the Mamba cache between steps.
605
606 self.logits_processor = LogitsProcessor(
607 config.vocab_size,
608 config.vocab_size,
609 scale=config.lm_head_multiplier,
610 )
611 else:
612 self.lm_head = PPMissingLayer()
613
614 self.make_empty_intermediate_tensors = (
615 self.model.make_empty_intermediate_tensors
616 )
617
618 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
619 return self.model.embed_input_ids(input_ids)
620
621 def forward(
622 self,
623 input_ids: torch.Tensor | None,
624 positions: torch.Tensor,
625 intermediate_tensors: IntermediateTensors | None = None,
626 inputs_embeds: torch.Tensor | None = None,
627 **kwargs,
628 ):
629 hidden_states = self.model(
630 input_ids,
631 positions,
632 intermediate_tensors,
633 inputs_embeds,
634 )
635
636 return hidden_states
637
638 def compute_logits(
639 self,
640 hidden_states: torch.Tensor,
641 ) -> torch.Tensor | None:
642 logits = self.logits_processor(self.lm_head, hidden_states)
643
644 return logits
645
646 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
647 loader = AutoWeightsLoader(self)
648 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)