main
py 329 lines 12 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # Copyright 2023 Stability AI, EleutherAI, and The HuggingFace Inc. team.
5 # All rights reserved.
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18 #
19 # This code is based off the following work:
20 # https://huggingface.co/stabilityai/stablelm-3b-4e1t/blob/main/modeling_stablelm_epoch.py
21 # https://huggingface.co/stabilityai/stablelm-3b-4e1t/blob/main/config.json
22 """Inference-only StableLM (https://github.com/Stability-AI/StableLM)
23 model compatible with HuggingFace weights."""
24
25 from collections.abc import Iterable
26 from itertools import islice
27
28 import torch
29 from torch import nn
30 from transformers import StableLmConfig
31
32 from vllm.compilation.decorators import support_torch_compile
33 from vllm.config import CacheConfig, VllmConfig
34 from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
35 from vllm.model_executor.layers.activation import SiluAndMul
36 from vllm.model_executor.layers.attention import Attention
37 from vllm.model_executor.layers.linear import (
38 MergedColumnParallelLinear,
39 QKVParallelLinear,
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.rotary_embedding import get_rope
45 from vllm.model_executor.layers.vocab_parallel_embedding import (
46 ParallelLMHead,
47 VocabParallelEmbedding,
48 )
49 from vllm.sequence import IntermediateTensors
50
51 from .interfaces import SupportsPP
52 from .utils import (
53 AutoWeightsLoader,
54 WeightsMapper,
55 make_empty_intermediate_tensors_factory,
56 make_layers,
57 maybe_prefix,
58 )
59
60
61 class StablelmMLP(nn.Module):
62 def __init__(
63 self,
64 config: StableLmConfig,
65 quant_config: QuantizationConfig | None = None,
66 prefix: str = "",
67 ) -> None:
68 super().__init__()
69 self.config = config
70 self.hidden_size = config.hidden_size
71 self.intermediate_size = config.intermediate_size
72 self.gate_up_proj = MergedColumnParallelLinear(
73 config.hidden_size,
74 [config.intermediate_size] * 2,
75 bias=False,
76 quant_config=quant_config,
77 prefix=f"{prefix}.gate_up_proj",
78 )
79 self.down_proj = RowParallelLinear(
80 config.intermediate_size,
81 config.hidden_size,
82 bias=False,
83 quant_config=quant_config,
84 prefix=f"{prefix}.down_proj",
85 )
86 self.act_fn = SiluAndMul()
87
88 def forward(self, x: torch.Tensor) -> torch.Tensor:
89 gate_up, _ = self.gate_up_proj(x)
90 x = self.act_fn(gate_up)
91 x, _ = self.down_proj(x)
92 return x
93
94
95 class StablelmAttention(nn.Module):
96 def __init__(
97 self,
98 config: StableLmConfig,
99 cache_config: CacheConfig | None = None,
100 quant_config: QuantizationConfig | None = None,
101 prefix: str = "",
102 ) -> None:
103 super().__init__()
104 self.config = config
105 self.hidden_size = config.hidden_size
106 tp_size = get_tensor_model_parallel_world_size()
107 self.total_num_heads = config.num_attention_heads
108 self.num_heads = self.total_num_heads // tp_size
109
110 self.total_num_key_value_heads = config.num_key_value_heads
111 if self.total_num_key_value_heads >= tp_size:
112 # Number of KV heads is greater than TP size, so we partition
113 # the KV heads across multiple tensor parallel GPUs.
114 assert self.total_num_key_value_heads % tp_size == 0
115 else:
116 # Number of KV heads is less than TP size, so we replicate
117 # the KV heads across multiple tensor parallel GPUs.
118 assert tp_size % self.total_num_key_value_heads == 0
119 self.num_key_value_heads = max(1, self.total_num_key_value_heads // tp_size)
120 self.head_dim = self.hidden_size // self.total_num_heads
121 self.max_position_embeddings = config.max_position_embeddings
122 self.scaling = self.head_dim**-0.5
123 self.q_size = self.num_heads * self.head_dim
124 self.kv_size = self.num_key_value_heads * self.head_dim
125 self.qkv_bias = getattr(config, "use_qkv_bias", False)
126 if (self.head_dim * self.num_heads * tp_size) != self.hidden_size:
127 raise ValueError(
128 f"hidden_size must be divisible by num_heads "
129 f"(got `hidden_size`: {self.hidden_size}"
130 f" and `num_heads`: {self.num_heads})."
131 )
132
133 self.qkv_proj = QKVParallelLinear(
134 self.hidden_size,
135 self.head_dim,
136 self.total_num_heads,
137 self.total_num_key_value_heads,
138 self.qkv_bias,
139 quant_config=quant_config,
140 prefix=f"{prefix}.qkv_proj",
141 )
142 self.o_proj = RowParallelLinear(
143 self.total_num_heads * self.head_dim,
144 self.hidden_size,
145 bias=False,
146 quant_config=quant_config,
147 prefix=f"{prefix}.o_proj",
148 )
149 self.rotary_emb = get_rope(
150 self.head_dim,
151 max_position=self.config.max_position_embeddings,
152 rope_parameters=self.config.rope_parameters,
153 )
154 self.attn = Attention(
155 self.num_heads,
156 self.head_dim,
157 self.scaling,
158 num_kv_heads=self.num_key_value_heads,
159 cache_config=cache_config,
160 quant_config=quant_config,
161 prefix=f"{prefix}.attn",
162 )
163
164 def forward(
165 self,
166 positions: torch.Tensor,
167 hidden_states: torch.Tensor,
168 ) -> torch.Tensor:
169 qkv, _ = self.qkv_proj(hidden_states)
170 q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
171 q, k = self.rotary_emb(positions, q, k)
172 attn_output = self.attn(q, k, v)
173 output, _ = self.o_proj(attn_output)
174 return output
175
176
177 class StablelmDecoderLayer(nn.Module):
178 def __init__(
179 self,
180 config: StableLmConfig,
181 cache_config: CacheConfig | None = None,
182 quant_config: QuantizationConfig | None = None,
183 prefix: str = "",
184 ) -> None:
185 super().__init__()
186 self.self_attn = StablelmAttention(
187 config, cache_config, quant_config, prefix=f"{prefix}.self_attn"
188 )
189 self.mlp = StablelmMLP(config, quant_config, prefix=f"{prefix}.mlp")
190 norm_eps = getattr(config, "norm_eps", getattr(config, "layer_norm_eps", 1e-05))
191 self.input_layernorm = nn.LayerNorm(config.hidden_size, eps=norm_eps)
192 self.post_attention_layernorm = nn.LayerNorm(config.hidden_size, eps=norm_eps)
193
194 def forward(
195 self,
196 positions: torch.Tensor,
197 hidden_states: torch.Tensor,
198 ) -> tuple[torch.Tensor, torch.Tensor]:
199 # Self Attention
200 residual = hidden_states
201 hidden_states = self.input_layernorm(hidden_states)
202 hidden_states = self.self_attn(
203 positions=positions,
204 hidden_states=hidden_states,
205 )
206 hidden_states = residual + hidden_states
207
208 # Fully Connected
209 residual = hidden_states
210 hidden_states = self.post_attention_layernorm(hidden_states)
211 hidden_states = self.mlp(hidden_states)
212 hidden_states = residual + hidden_states
213
214 return hidden_states, residual
215
216
217 @support_torch_compile
218 class StableLMEpochModel(nn.Module):
219 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
220 super().__init__()
221
222 config = vllm_config.model_config.hf_config
223 cache_config = vllm_config.cache_config
224 quant_config = vllm_config.quant_config
225
226 self.embed_tokens = VocabParallelEmbedding(
227 config.vocab_size,
228 config.hidden_size,
229 quant_config=quant_config,
230 prefix=f"{prefix}.embed_tokens",
231 )
232 self.start_layer, self.end_layer, self.layers = make_layers(
233 config.num_hidden_layers,
234 lambda prefix: StablelmDecoderLayer(
235 config, cache_config, quant_config, prefix=prefix
236 ),
237 prefix=f"{prefix}.layers",
238 )
239 norm_eps = getattr(config, "norm_eps", getattr(config, "layer_norm_eps", 1e-05))
240 self.norm = nn.LayerNorm(config.hidden_size, eps=norm_eps)
241 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
242 ["hidden_states"], config.hidden_size
243 )
244
245 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
246 return self.embed_tokens(input_ids)
247
248 def forward(
249 self,
250 input_ids: torch.Tensor | None,
251 positions: torch.Tensor,
252 intermediate_tensors: IntermediateTensors | None,
253 inputs_embeds: torch.Tensor | None = None,
254 ) -> torch.Tensor | IntermediateTensors:
255 if get_pp_group().is_first_rank:
256 if inputs_embeds is not None:
257 hidden_states = inputs_embeds
258 else:
259 hidden_states = self.embed_input_ids(input_ids)
260 else:
261 assert intermediate_tensors is not None
262 hidden_states = intermediate_tensors["hidden_states"]
263 for layer in islice(self.layers, self.start_layer, self.end_layer):
264 hidden_states, residual = layer(positions, hidden_states)
265 if not get_pp_group().is_last_rank:
266 return IntermediateTensors({"hidden_states": hidden_states})
267 hidden_states = self.norm(hidden_states)
268 return hidden_states
269
270
271 class StablelmForCausalLM(nn.Module, SupportsPP):
272 hf_to_vllm_mapper = WeightsMapper(
273 orig_to_new_stacked={
274 # weight_name: (param_name, shard_id)
275 ".q_proj": (".qkv_proj", "q"),
276 ".k_proj": (".qkv_proj", "k"),
277 ".v_proj": (".qkv_proj", "v"),
278 ".gate_proj": (".gate_up_proj", 0),
279 ".up_proj": (".gate_up_proj", 1),
280 }
281 )
282
283 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
284 super().__init__()
285 config = vllm_config.model_config.hf_config
286 quant_config = vllm_config.quant_config
287 self.config = config
288 self.quant_config = quant_config
289 self.model = StableLMEpochModel(
290 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
291 )
292 self.lm_head = ParallelLMHead(
293 config.vocab_size,
294 config.hidden_size,
295 quant_config=quant_config,
296 prefix=f"{prefix}.lm_head",
297 )
298 if self.config.tie_word_embeddings:
299 self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
300 self.logits_processor = LogitsProcessor(config.vocab_size)
301 self.make_empty_intermediate_tensors = (
302 self.model.make_empty_intermediate_tensors
303 )
304
305 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
306 return self.model.embed_input_ids(input_ids)
307
308 def forward(
309 self,
310 input_ids: torch.Tensor | None,
311 positions: torch.Tensor,
312 intermediate_tensors: IntermediateTensors | None = None,
313 inputs_embeds: torch.Tensor | None = None,
314 ) -> torch.Tensor | IntermediateTensors:
315 hidden_states = self.model(
316 input_ids, positions, intermediate_tensors, inputs_embeds
317 )
318 return hidden_states
319
320 def compute_logits(
321 self,
322 hidden_states: torch.Tensor,
323 ) -> torch.Tensor | None:
324 logits = self.logits_processor(self.lm_head, hidden_states)
325 return logits
326
327 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
328 loader = AutoWeightsLoader(self)
329 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)