main
py 264 lines 9.06 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """PyTorch MAMBA 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 MambaConfig
11
12 from vllm.compilation.decorators import support_torch_compile
13 from vllm.config import CacheConfig, ModelConfig, VllmConfig
14 from vllm.distributed.parallel_state import get_pp_group
15 from vllm.model_executor.layers.layernorm import RMSNorm
16 from vllm.model_executor.layers.logits_processor import LogitsProcessor
17 from vllm.model_executor.layers.mamba.mamba_mixer import MambaMixer
18 from vllm.model_executor.layers.mamba.mamba_utils import (
19 MambaStateCopyFunc,
20 MambaStateCopyFuncCalculator,
21 MambaStateDtypeCalculator,
22 MambaStateShapeCalculator,
23 )
24 from vllm.model_executor.layers.quantization import QuantizationConfig
25 from vllm.model_executor.layers.vocab_parallel_embedding import (
26 ParallelLMHead,
27 VocabParallelEmbedding,
28 )
29 from vllm.model_executor.models.interfaces import (
30 HasInnerState,
31 IsAttentionFree,
32 SupportsMambaPrefixCaching,
33 SupportsPP,
34 )
35 from vllm.sequence import IntermediateTensors
36
37 from .utils import (
38 AutoWeightsLoader,
39 WeightsMapper,
40 make_empty_intermediate_tensors_factory,
41 make_layers,
42 maybe_prefix,
43 )
44
45 KVCache = tuple[torch.Tensor, torch.Tensor]
46
47
48 class MambaDecoderLayer(nn.Module):
49 def __init__(
50 self,
51 config: MambaConfig,
52 model_config: ModelConfig | None = None,
53 cache_config: CacheConfig | None = None,
54 quant_config: QuantizationConfig | None = None,
55 is_lora_enabled: bool = False,
56 prefix: str = "",
57 ) -> None:
58 super().__init__()
59 self.config = config
60 self.is_falcon_mamba = config.model_type == "falcon_mamba"
61 self.is_lora_enabled = is_lora_enabled
62 mixer_rms_eps = config.mixer_rms_eps if self.is_falcon_mamba else 1e-5
63 self.mixer = MambaMixer(
64 hidden_size=config.hidden_size,
65 ssm_state_size=config.state_size,
66 conv_kernel_size=config.conv_kernel,
67 intermediate_size=config.intermediate_size,
68 time_step_rank=config.time_step_rank,
69 use_conv_bias=config.use_conv_bias,
70 use_bias=config.use_bias,
71 use_rms_norm=self.is_falcon_mamba,
72 rms_norm_has_weight=not self.is_falcon_mamba,
73 rms_norm_eps=mixer_rms_eps,
74 activation=config.hidden_act,
75 is_lora_enabled=self.is_lora_enabled,
76 model_config=model_config,
77 cache_config=cache_config,
78 prefix=f"{prefix}.mixer",
79 )
80
81 self.norm = RMSNorm(config.hidden_size, eps=config.layer_norm_epsilon)
82
83 def forward(
84 self,
85 hidden_states: torch.Tensor,
86 residual: torch.Tensor | None,
87 **kwargs,
88 ):
89 if residual is None:
90 residual = hidden_states
91 hidden_states = self.norm(hidden_states)
92 else:
93 hidden_states, residual = self.norm(hidden_states, residual)
94
95 output = torch.empty_like(hidden_states)
96 self.mixer(hidden_states, output)
97 return output, residual
98
99
100 @support_torch_compile
101 class MambaModel(nn.Module):
102 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
103 super().__init__()
104
105 config = vllm_config.model_config.hf_config
106 model_config = vllm_config.model_config
107 cache_config = vllm_config.cache_config
108 quant_config = vllm_config.quant_config
109 lora_config = vllm_config.lora_config
110 is_lora_enabled = bool(lora_config)
111
112 self.config = config
113
114 self.vocab_size = config.vocab_size
115
116 self.embeddings = VocabParallelEmbedding(
117 self.vocab_size,
118 config.hidden_size,
119 )
120
121 self.start_layer, self.end_layer, self.layers = make_layers(
122 config.num_hidden_layers,
123 lambda prefix: MambaDecoderLayer(
124 config,
125 model_config=model_config,
126 cache_config=cache_config,
127 quant_config=quant_config,
128 is_lora_enabled=is_lora_enabled,
129 prefix=prefix,
130 ),
131 prefix=f"{prefix}.layers",
132 )
133
134 self.norm_f = RMSNorm(config.hidden_size, eps=config.layer_norm_epsilon)
135 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
136 ["hidden_states", "residual"], config.hidden_size
137 )
138
139 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
140 return self.embeddings(input_ids)
141
142 def forward(
143 self,
144 input_ids: torch.Tensor | None,
145 positions: torch.Tensor,
146 intermediate_tensors: IntermediateTensors | None = None,
147 inputs_embeds: torch.Tensor | None = None,
148 ) -> torch.Tensor:
149 if get_pp_group().is_first_rank:
150 if inputs_embeds is not None:
151 hidden_states = inputs_embeds
152 else:
153 hidden_states = self.embed_input_ids(input_ids)
154 residual = None
155 else:
156 assert intermediate_tensors is not None
157 hidden_states = intermediate_tensors["hidden_states"]
158 residual = intermediate_tensors["residual"]
159
160 for layer in islice(self.layers, self.start_layer, self.end_layer):
161 hidden_states, residual = layer(
162 positions=positions, hidden_states=hidden_states, residual=residual
163 )
164 if not get_pp_group().is_last_rank:
165 return IntermediateTensors(
166 {"hidden_states": hidden_states, "residual": residual}
167 )
168 hidden_states, _ = self.norm_f(hidden_states, residual)
169
170 return hidden_states
171
172
173 class MambaForCausalLM(
174 nn.Module, HasInnerState, IsAttentionFree, SupportsPP, SupportsMambaPrefixCaching
175 ):
176 hf_to_vllm_mapper = WeightsMapper(orig_to_new_substr={".A_log": ".A"})
177
178 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
179 config = vllm_config.model_config.hf_config
180
181 self.scheduler_config = vllm_config.scheduler_config
182
183 super().__init__()
184 self.config = config
185 self.vllm_config = vllm_config
186 self.model_config = vllm_config.model_config
187 self.backbone = MambaModel(
188 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "backbone")
189 )
190
191 self.lm_head = ParallelLMHead(
192 config.vocab_size,
193 config.hidden_size,
194 prefix=maybe_prefix(prefix, "lm_head"),
195 )
196 if config.tie_word_embeddings:
197 self.lm_head = self.lm_head.tie_weights(self.backbone.embeddings)
198
199 self.logits_processor = LogitsProcessor(config.vocab_size)
200
201 self.make_empty_intermediate_tensors = (
202 self.backbone.make_empty_intermediate_tensors
203 )
204
205 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
206 return self.backbone.embed_input_ids(input_ids)
207
208 def forward(
209 self,
210 input_ids: torch.Tensor | None,
211 positions: torch.Tensor,
212 intermediate_tensors: IntermediateTensors | None = None,
213 inputs_embeds: torch.Tensor | None = None,
214 **kwargs,
215 ):
216 hidden_states = self.backbone(
217 input_ids, positions, intermediate_tensors, inputs_embeds
218 )
219
220 return hidden_states
221
222 @classmethod
223 def get_mamba_state_dtype_from_config(
224 cls,
225 vllm_config: "VllmConfig",
226 ) -> tuple[torch.dtype, torch.dtype]:
227 return MambaStateDtypeCalculator.mamba1_state_dtype(
228 vllm_config.model_config.dtype,
229 vllm_config.cache_config.mamba_cache_dtype,
230 vllm_config.cache_config.mamba_ssm_cache_dtype,
231 )
232
233 @classmethod
234 def get_mamba_state_shape_from_config(
235 cls,
236 vllm_config: "VllmConfig",
237 ) -> tuple[tuple[int, int], tuple[int, int]]:
238 parallel_config = vllm_config.parallel_config
239 hf_config = vllm_config.model_config.hf_config
240
241 return MambaStateShapeCalculator.mamba1_state_shape(
242 tp_world_size=parallel_config.tensor_parallel_size,
243 intermediate_size=hf_config.intermediate_size,
244 state_size=hf_config.state_size,
245 conv_kernel=hf_config.conv_kernel,
246 )
247
248 @classmethod
249 def get_mamba_state_copy_func(cls) -> tuple[MambaStateCopyFunc, MambaStateCopyFunc]:
250 return MambaStateCopyFuncCalculator.mamba1_state_copy_func()
251
252 def copy_inputs_before_cuda_graphs(self, input_buffers, **kwargs):
253 return self.mamba_cache.copy_inputs_before_cuda_graphs(input_buffers, **kwargs)
254
255 def get_seqlen_agnostic_capture_inputs(self, batch_size: int):
256 return self.mamba_cache.get_seqlen_agnostic_capture_inputs(batch_size)
257
258 def compute_logits(self, hidden_states: torch.Tensor) -> torch.Tensor:
259 logits = self.logits_processor(self.lm_head, hidden_states)
260 return logits
261
262 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
263 loader = AutoWeightsLoader(self)
264 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)