main
py 338 lines 11.6 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # Adapted from
5 # https://huggingface.co/OrionStarAI/Orion-14B-Base/blob/main/modeling_orion.py
6 # Copyright (c) OrionStar Inc.
7 # LICENSE: https://huggingface.co/OrionStarAI/Orion-14B-Base/blob/main/LICENSE
8 """Inference-only Orion-14B model compatible with HuggingFace weights."""
9
10 from collections.abc import Iterable
11 from itertools import islice
12 from typing import Any
13
14 import torch
15 from torch import nn
16 from transformers import PreTrainedConfig
17
18 from vllm.compilation.decorators import support_torch_compile
19 from vllm.config import CacheConfig, VllmConfig
20 from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
21 from vllm.model_executor.layers.activation import SiluAndMul
22 from vllm.model_executor.layers.attention import Attention
23 from vllm.model_executor.layers.linear import (
24 MergedColumnParallelLinear,
25 QKVParallelLinear,
26 RowParallelLinear,
27 )
28 from vllm.model_executor.layers.logits_processor import LogitsProcessor
29 from vllm.model_executor.layers.quantization import QuantizationConfig
30 from vllm.model_executor.layers.rotary_embedding import get_rope
31 from vllm.model_executor.layers.vocab_parallel_embedding import (
32 ParallelLMHead,
33 VocabParallelEmbedding,
34 )
35 from vllm.sequence import IntermediateTensors
36
37 from .interfaces import SupportsPP
38 from .utils import (
39 AutoWeightsLoader,
40 WeightsMapper,
41 make_empty_intermediate_tensors_factory,
42 make_layers,
43 maybe_prefix,
44 )
45
46
47 class OrionMLP(nn.Module):
48 def __init__(
49 self,
50 hidden_size: int,
51 intermediate_size: int,
52 hidden_act: str,
53 quant_config: QuantizationConfig | None = None,
54 prefix: str = "",
55 ) -> None:
56 super().__init__()
57 self.gate_up_proj = MergedColumnParallelLinear(
58 hidden_size,
59 [intermediate_size] * 2,
60 bias=False,
61 quant_config=quant_config,
62 prefix=f"{prefix}.gate_up_proj",
63 )
64 self.down_proj = RowParallelLinear(
65 intermediate_size,
66 hidden_size,
67 bias=False,
68 quant_config=quant_config,
69 prefix=f"{prefix}.down_proj",
70 )
71 if hidden_act != "silu":
72 raise ValueError(
73 f"Unsupported activation: {hidden_act}. Only silu is supported for now."
74 )
75 self.act_fn = SiluAndMul()
76
77 def forward(self, x):
78 gate_up, _ = self.gate_up_proj(x)
79 x = self.act_fn(gate_up)
80 x, _ = self.down_proj(x)
81 return x
82
83
84 class OrionAttention(nn.Module):
85 def __init__(
86 self,
87 hidden_size: int,
88 num_heads: int,
89 num_kv_heads: int,
90 rope_parameters: dict[str, Any] | None = None,
91 max_position_embeddings: int = 8192,
92 cache_config: CacheConfig | None = None,
93 quant_config: QuantizationConfig | None = None,
94 prefix: str = "",
95 ) -> None:
96 super().__init__()
97 self.hidden_size = hidden_size
98 tp_size = get_tensor_model_parallel_world_size()
99 self.total_num_heads = num_heads
100 assert self.total_num_heads % tp_size == 0
101 self.num_heads = self.total_num_heads // tp_size
102 self.total_num_kv_heads = num_kv_heads
103 if self.total_num_kv_heads >= tp_size:
104 # Number of KV heads is greater than TP size, so we partition
105 # the KV heads across multiple tensor parallel GPUs.
106 assert self.total_num_kv_heads % tp_size == 0
107 else:
108 # Number of KV heads is less than TP size, so we replicate
109 # the KV heads across multiple tensor parallel GPUs.
110 assert tp_size % self.total_num_kv_heads == 0
111 self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
112 self.head_dim = hidden_size // self.total_num_heads
113 self.q_size = self.num_heads * self.head_dim
114 self.kv_size = self.num_kv_heads * self.head_dim
115 self.scaling = self.head_dim**-0.5
116 self.max_position_embeddings = max_position_embeddings
117
118 self.qkv_proj = QKVParallelLinear(
119 hidden_size,
120 self.head_dim,
121 self.total_num_heads,
122 self.total_num_kv_heads,
123 bias=False,
124 quant_config=quant_config,
125 prefix=f"{prefix}.qkv_proj",
126 )
127 self.o_proj = RowParallelLinear(
128 self.total_num_heads * self.head_dim,
129 hidden_size,
130 bias=False,
131 quant_config=quant_config,
132 prefix=f"{prefix}.o_proj",
133 )
134
135 self.rotary_emb = get_rope(
136 self.head_dim,
137 max_position=max_position_embeddings,
138 rope_parameters=rope_parameters,
139 )
140 self.attn = Attention(
141 self.num_heads,
142 self.head_dim,
143 self.scaling,
144 num_kv_heads=self.num_kv_heads,
145 cache_config=cache_config,
146 quant_config=quant_config,
147 prefix=f"{prefix}.attn",
148 )
149
150 def forward(
151 self,
152 positions: torch.Tensor,
153 hidden_states: torch.Tensor,
154 ) -> torch.Tensor:
155 qkv, _ = self.qkv_proj(hidden_states)
156 q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
157 q, k = self.rotary_emb(positions, q, k)
158 attn_output = self.attn(q, k, v)
159 output, _ = self.o_proj(attn_output)
160 return output
161
162
163 class OrionDecoderLayer(nn.Module):
164 def __init__(
165 self,
166 config: PreTrainedConfig,
167 cache_config: CacheConfig | None = None,
168 quant_config: QuantizationConfig | None = None,
169 prefix: str = "",
170 ) -> None:
171 super().__init__()
172 self.hidden_size = config.hidden_size
173 max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
174 self.self_attn = OrionAttention(
175 hidden_size=self.hidden_size,
176 num_heads=config.num_attention_heads,
177 num_kv_heads=config.num_key_value_heads,
178 rope_parameters=config.rope_parameters,
179 max_position_embeddings=max_position_embeddings,
180 cache_config=cache_config,
181 quant_config=quant_config,
182 prefix=f"{prefix}.self_attn",
183 )
184 self.mlp = OrionMLP(
185 hidden_size=self.hidden_size,
186 intermediate_size=config.intermediate_size,
187 hidden_act=config.hidden_act,
188 quant_config=quant_config,
189 prefix=f"{prefix}.mlp",
190 )
191
192 self.input_layernorm = nn.LayerNorm(config.hidden_size, eps=config.rms_norm_eps)
193 self.post_attention_layernorm = nn.LayerNorm(
194 config.hidden_size, eps=config.rms_norm_eps
195 )
196
197 def forward(
198 self,
199 positions: torch.Tensor,
200 hidden_states: torch.Tensor,
201 ) -> tuple[torch.Tensor, torch.Tensor]:
202 # Self Attention
203 residual = hidden_states
204 hidden_states = self.input_layernorm(hidden_states)
205 hidden_states = self.self_attn(
206 positions=positions,
207 hidden_states=hidden_states,
208 )
209
210 hidden_states = residual + hidden_states
211
212 # Fully Connected
213 residual = hidden_states
214 hidden_states = self.post_attention_layernorm(hidden_states)
215 hidden_states = self.mlp(hidden_states)
216 hidden_states = residual + hidden_states
217 return hidden_states
218
219
220 @support_torch_compile
221 class OrionModel(nn.Module):
222 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
223 super().__init__()
224
225 config = vllm_config.model_config.hf_config
226 cache_config = vllm_config.cache_config
227 quant_config = vllm_config.quant_config
228
229 self.config = config
230 self.vocab_size = config.vocab_size
231 self.embed_tokens = VocabParallelEmbedding(
232 config.vocab_size,
233 config.hidden_size,
234 )
235 self.start_layer, self.end_layer, self.layers = make_layers(
236 config.num_hidden_layers,
237 lambda prefix: OrionDecoderLayer(
238 config, cache_config, quant_config, prefix=prefix
239 ),
240 prefix=f"{prefix}.layers",
241 )
242 self.norm = nn.LayerNorm(config.hidden_size, eps=config.rms_norm_eps)
243 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
244 [
245 "hidden_states",
246 ],
247 config.hidden_size,
248 )
249
250 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
251 return self.embed_tokens(input_ids)
252
253 def forward(
254 self,
255 input_ids: torch.Tensor | None,
256 positions: torch.Tensor,
257 intermediate_tensors: IntermediateTensors | None,
258 inputs_embeds: torch.Tensor | None = None,
259 ) -> torch.Tensor | IntermediateTensors:
260 if get_pp_group().is_first_rank:
261 if inputs_embeds is not None:
262 hidden_states = inputs_embeds
263 else:
264 hidden_states = self.embed_input_ids(input_ids)
265 else:
266 assert intermediate_tensors is not None
267 hidden_states = intermediate_tensors["hidden_states"]
268 for layer in islice(self.layers, self.start_layer, self.end_layer):
269 hidden_states = layer(positions, hidden_states)
270 if not get_pp_group().is_last_rank:
271 return IntermediateTensors(
272 {
273 "hidden_states": hidden_states,
274 }
275 )
276 hidden_states = self.norm(hidden_states)
277 return hidden_states
278
279
280 class OrionForCausalLM(nn.Module, SupportsPP):
281 hf_to_vllm_mapper = WeightsMapper(
282 orig_to_new_stacked={
283 # weight_name: (param_name, shard_id)
284 ".q_proj": (".qkv_proj", "q"),
285 ".k_proj": (".qkv_proj", "k"),
286 ".v_proj": (".qkv_proj", "v"),
287 ".gate_proj": (".gate_up_proj", 0),
288 ".up_proj": (".gate_up_proj", 1),
289 }
290 )
291
292 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
293 super().__init__()
294 config = vllm_config.model_config.hf_config
295 quant_config = vllm_config.quant_config
296 self.config = config
297 self.quant_config = quant_config
298 self.model = OrionModel(
299 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
300 )
301 self.lm_head = ParallelLMHead(
302 config.vocab_size,
303 config.hidden_size,
304 quant_config=quant_config,
305 prefix=maybe_prefix(prefix, "lm_head"),
306 )
307 if self.config.tie_word_embeddings:
308 self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
309 self.logits_processor = LogitsProcessor(config.vocab_size)
310 self.make_empty_intermediate_tensors = (
311 self.model.make_empty_intermediate_tensors
312 )
313
314 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
315 return self.model.embed_input_ids(input_ids)
316
317 def forward(
318 self,
319 input_ids: torch.Tensor | None,
320 positions: torch.Tensor,
321 intermediate_tensors: IntermediateTensors | None = None,
322 inputs_embeds: torch.Tensor | None = None,
323 ) -> torch.Tensor | IntermediateTensors:
324 hidden_states = self.model(
325 input_ids, positions, intermediate_tensors, inputs_embeds
326 )
327 return hidden_states
328
329 def compute_logits(
330 self,
331 hidden_states: torch.Tensor,
332 ) -> torch.Tensor | None:
333 logits = self.logits_processor(self.lm_head, hidden_states)
334 return logits
335
336 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
337 loader = AutoWeightsLoader(self)
338 return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)