[Model] Migrate GPT-NeoX, Phi, Seed-OSS and Jais2 to the Transformers modeling backend (#59701)

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

Harry Mellor committed Oct 2, 2026 at 12:18 UTC 6e4efafc6edfee8be31c3c147164a1daa4650051
8 files changed +26 -1536
docs/models/supported_models.md
+6 -6
@@ -410,7 +410,6 @@ th {
410 | `GlmMoeDsaForCausalLM` | GLM-5, GLM-5.1, GLM-5.2 | `zai-org/GLM-5`, etc. | ✅︎ | ✅︎ |
411 | `GPT2LMHeadModel` | GPT-2 | `openai-community/gpt2`, `openai-community/gpt2-xl`, etc. | | ✅︎ |
412 | `GPTJForCausalLM` | GPT-J | `EleutherAI/gpt-j-6b`, `nomic-ai/gpt4all-j`, etc. | | ✅︎ |
413 -| `GPTNeoXForCausalLM` | GPT-NeoX, Pythia, OpenAssistant, Dolly V2, StableLM | `EleutherAI/gpt-neox-20b`, `EleutherAI/pythia-12b`, `OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5`, `databricks/dolly-v2-12b`, `stabilityai/stablelm-tuned-alpha-7b`, etc. | | ✅︎ |
413 | `GptOssForCausalLM` | GPT-OSS | `openai/gpt-oss-120b`, `openai/gpt-oss-20b` | ✅︎ | ✅︎ |
414 | `GraniteForCausalLM` | Granite 3.0, Granite 3.1, PowerLM | `ibm-granite/granite-3.0-2b-base`, `ibm-granite/granite-3.1-8b-instruct`, `ibm/PowerLM-3b`, etc. | ✅︎ | ✅︎ |
415 | `GraniteMoeForCausalLM` | Granite 3.0 MoE, PowerMoE | `ibm-granite/granite-3.0-1b-a400m-base`, `ibm-granite/granite-3.0-3b-a800m-instruct`, `ibm/PowerMoE-3b`, etc. | ✅︎ | ✅︎ |
@@ -426,7 +425,6 @@ th {
425 | `InternLM3ForCausalLM` | InternLM3 | `internlm/internlm3-8b-instruct`, etc. | ✅︎ | ✅︎ |
426 | `IQuestCoderForCausalLM` | IQuestCoderV1 | `IQuestLab/IQuest-Coder-V1-40B-Instruct`, etc. | | |
427 | `IQuestLoopCoderForCausalLM` | IQuestLoopCoderV1 | `IQuestLab/IQuest-Coder-V1-40B-Loop-Instruct`, etc. | | |
429 -| `Jais2ForCausalLM` | Jais2 | `inceptionai/Jais-2-8B-Chat`, `inceptionai/Jais-2-70B-Chat`, etc. | | ✅︎ |
428 | `JambaForCausalLM` | Jamba | `ai21labs/AI21-Jamba-1.5-Large`, `ai21labs/AI21-Jamba-1.5-Mini`, `ai21labs/Jamba-v0.1`, etc. | ✅︎ | ✅︎ |
429 | `K2HorizonForCausalLM` | K2-Horizon | `IFM/K2-Horizon-7B`, `IFM/K2-Horizon-375B` | | ✅︎ |
430 | `KimiLinearForCausalLM` | Kimi-Linear-48B-A3B-Base, Kimi-Linear-48B-A3B-Instruct | `moonshotai/Kimi-Linear-48B-A3B-Base`, `moonshotai/Kimi-Linear-48B-A3B-Instruct` | | ✅︎ |
@@ -456,7 +454,6 @@ th {
454 | `PanguProMoEV2ForCausalLM` | openpangu-pro-moe-v2 | | ✅︎ | ✅︎ |
455 | `PanguUltraMoEForCausalLM` | openpangu-ultra-moe-718b-model | `FreedomIntelligence/openPangu-Ultra-MoE-718B-V1.1` | ✅︎ | ✅︎ |
456 | `Param2MoEForCausalLM` | param2moe | `bharatgenai/Param2-17B-A2.4B-Thinking`, etc. | ✅︎ | ✅︎ |
459 -| `PhiForCausalLM` | Phi | `microsoft/phi-1_5`, `microsoft/phi-2`, etc. | ✅︎ | ✅︎ |
457 | `Phi3ForCausalLM` | Phi-4, Phi-3 | `microsoft/Phi-4-mini-instruct`, `microsoft/Phi-4`, `microsoft/Phi-3-mini-4k-instruct`, `microsoft/Phi-3-mini-128k-instruct`, `microsoft/Phi-3-medium-128k-instruct`, etc. | ✅︎ | ✅︎ |
458 | `PhiMoEForCausalLM` | Phi-3.5-MoE | `microsoft/Phi-3.5-MoE-instruct`, etc. | ✅︎ | ✅︎ |
459 | `Plamo3ForCausalLM` | PLaMo3 | `pfnet/plamo-3-nict-2b-base`, `pfnet/plamo-3-nict-8b-base`, etc. | ✅ | ✅︎ |
@@ -468,7 +465,6 @@ th {
465 | `Rnj1ForCausalLM` | Rnj1 | `EssentialAI/rnj-1-instruct`, etc. | | |
466 | `SarvamMoEForCausalLM` | Sarvam 2 | `sarvamai/sarvam2-30b-a3b`, etc. | ✅︎ | ✅︎ |
467 | `SarvamMLAForCausalLM` | Sarvam 2 | `sarvamai/sarvam2-105b-a9b`, etc. | | ✅︎ |
471 -| `SeedOssForCausalLM` | SeedOss | `ByteDance-Seed/Seed-OSS-36B-Instruct`, etc. | ✅︎ | ✅︎ |
468 | `SolarForCausalLM` | Solar Pro | `upstage/solar-pro-preview-instruct`, etc. | ✅︎ | ✅︎ |
469 | `StableLmForCausalLM` | StableLM | `stabilityai/stablelm-3b-4e1t`, `stabilityai/stablelm-base-alpha-7b-v2`, etc. | | |
470 | `Step1ForCausalLM` | Step-Audio | `stepfun-ai/Step-Audio-EditX`, etc. | ✅︎ | ✅︎ |
@@ -484,16 +480,20 @@ Some models are supported only via the [Transformers modeling backend](#transfor
480 | ------------ | ------ | ----------------- | -------------------- | ------------------------- |
481 | `ArceeForCausalLM` | Arcee (AFM) | `arcee-ai/AFM-4.5B-Base`, etc. | ✅︎ | ✅︎ |
482 | `CwmForCausalLM` | CWM | `facebook/cwm`, etc. | ✅︎ | ✅︎ |
487 -| `FlexOlmoForCausalLM` | FlexOlmo | `allenai/FlexOlmo-7x7B-1T`, `allenai/FlexOlmo-7x7B-1T-RT`, etc. | | ✅︎ |
483 +| `FlexOlmoForCausalLM` | FlexOlmo | `allenai/FlexOlmo-7x7B-1T`, `allenai/FlexOlmo-7x7B-1T-RT`, etc. | ✅︎ | ✅︎ |
484 | `GlmForCausalLM` | GLM-4 | `zai-org/glm-4-9b-chat-hf`, etc. | ✅︎ | ✅︎ |
485 | `GPTBigCodeForCausalLM` | StarCoder, SantaCoder, WizardCoder | `bigcode/starcoder`, `bigcode/gpt_bigcode-santacoder`, `WizardLM/WizardCoder-15B-V1.0`, etc. | ✅︎ | |
486 +| `GPTNeoXForCausalLM` | GPT-NeoX, Pythia, OpenAssistant, Dolly V2, StableLM | `EleutherAI/gpt-neox-20b`, `EleutherAI/pythia-12b`, `OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5`, `databricks/dolly-v2-12b`, `stabilityai/stablelm-tuned-alpha-7b`, etc. | | ✅︎ |
487 | `HunYuanDenseV1ForCausalLM` | Hunyuan Dense | `tencent/Hunyuan-7B-Instruct` | ✅︎ | ✅︎ |
488 | `HunYuanMoEV1ForCausalLM` | Hunyuan-A13B | `tencent/Hunyuan-A13B-Instruct`, `tencent/Hunyuan-A13B-Pretrain`, `tencent/Hunyuan-A13B-Instruct-FP8`, etc. | ✅︎ | ✅︎ |
492 -| `MellumForCausalLM` | Mellum 2 | `JetBrains/Mellum2-12B-A2.5B-Base`, etc. | | ✅︎ |
489 +| `Jais2ForCausalLM` | Jais2 | `inceptionai/Jais-2-8B-Chat`, `inceptionai/Jais-2-70B-Chat`, etc. | ✅︎ | ✅︎ |
490 +| `MellumForCausalLM` | Mellum 2 | `JetBrains/Mellum2-12B-A2.5B-Base`, etc. | ✅︎ | ✅︎ |
491 | `NanbeigeForCausalLM` | Nanbeige4.2 | `Nanbeige/Nanbeige4.2-3B`, etc. | ✅︎ | ✅︎ |
492 | `OlmoForCausalLM` | OLMo | `allenai/OLMo-1B-hf`, `allenai/OLMo-7B-hf`, etc. | ✅︎ | ✅︎ |
493 | `Olmo2ForCausalLM` | OLMo2 | `allenai/OLMo-2-0425-1B`, etc. | ✅︎ | ✅︎ |
494 | `Olmo3ForCausalLM` | OLMo3 | `allenai/Olmo-3-7B-Instruct`, `allenai/Olmo-3-32B-Think`, etc. | ✅︎ | ✅︎ |
495 +| `PhiForCausalLM` | Phi | `microsoft/phi-1_5`, `microsoft/phi-2`, etc. | ✅︎ | ✅︎ |
496 +| `SeedOssForCausalLM` | SeedOss | `ByteDance-Seed/Seed-OSS-36B-Instruct`, etc. | ✅︎ | ✅︎ |
497 | `SmolLM3ForCausalLM` | SmolLM3 | `HuggingFaceTB/SmolLM3-3B` | ✅︎ | ✅︎ |
498 | `Starcoder2ForCausalLM` | Starcoder2 | `bigcode/starcoder2-3b`, `bigcode/starcoder2-7b`, `bigcode/starcoder2-15b`, etc. | ✅︎ | ✅︎ |
499 | `VaultGemmaForCausalLM` | VaultGemma | `google/vaultgemma-1b` | ✅︎ | ✅︎ |
vllm/model_executor/models/gpt_neox.py deleted
-324
@@ -1,324 +0,0 @@
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/gpt_neox/modeling_gpt_neox.py
6 -# Copyright 2023 The vLLM team.
7 -# Copyright 2022 EleutherAI The HuggingFace Inc. team. All rights reserved.
8 -#
9 -# Licensed under the Apache License, Version 2.0 (the "License");
10 -# you may not use this file except in compliance with the License.
11 -# You may obtain a copy of the License at
12 -#
13 -# http://www.apache.org/licenses/LICENSE-2.0
14 -#
15 -# Unless required by applicable law or agreed to in writing, software
16 -# distributed under the License is distributed on an "AS IS" BASIS,
17 -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 -# See the License for the specific language governing permissions and
19 -# limitations under the License.
20 -"""Inference-only GPT-NeoX model compatible with HuggingFace weights."""
21 -
22 -from collections.abc import Iterable
23 -from itertools import islice
24 -
25 -import torch
26 -from torch import nn
27 -from transformers import GPTNeoXConfig
28 -
29 -from vllm.compilation.decorators import support_torch_compile
30 -from vllm.config import CacheConfig, VllmConfig
31 -from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
32 -from vllm.model_executor.layers.activation import get_act_fn
33 -from vllm.model_executor.layers.attention import Attention
34 -from vllm.model_executor.layers.linear import (
35 - ColumnParallelLinear,
36 - QKVParallelLinear,
37 - RowParallelLinear,
38 -)
39 -from vllm.model_executor.layers.logits_processor import LogitsProcessor
40 -from vllm.model_executor.layers.quantization import QuantizationConfig
41 -from vllm.model_executor.layers.rotary_embedding import get_rope
42 -from vllm.model_executor.layers.vocab_parallel_embedding import (
43 - ParallelLMHead,
44 - VocabParallelEmbedding,
45 -)
46 -from vllm.sequence import IntermediateTensors
47 -
48 -from .interfaces import SupportsPP
49 -from .utils import (
50 - AutoWeightsLoader,
51 - WeightsMapper,
52 - make_empty_intermediate_tensors_factory,
53 - make_layers,
54 - maybe_prefix,
55 -)
56 -
57 -
58 -class GPTNeoXAttention(nn.Module):
59 - def __init__(
60 - self,
61 - config: GPTNeoXConfig,
62 - cache_config: CacheConfig | None = None,
63 - quant_config: QuantizationConfig | None = None,
64 - prefix: str = "",
65 - ):
66 - super().__init__()
67 - self.total_num_heads = config.num_attention_heads
68 - self.hidden_size = config.hidden_size
69 - self.head_size = self.hidden_size // self.total_num_heads
70 - self.bias = getattr(config, "attention_bias", True)
71 -
72 - tensor_model_parallel_world_size = get_tensor_model_parallel_world_size()
73 - assert self.total_num_heads % tensor_model_parallel_world_size == 0
74 - self.num_heads = self.total_num_heads // tensor_model_parallel_world_size
75 -
76 - self.query_key_value = QKVParallelLinear(
77 - config.hidden_size,
78 - self.head_size,
79 - self.total_num_heads,
80 - bias=self.bias,
81 - quant_config=quant_config,
82 - prefix=f"{prefix}.query_key_value",
83 - )
84 - self.dense = RowParallelLinear(
85 - config.hidden_size,
86 - config.hidden_size,
87 - bias=self.bias,
88 - quant_config=quant_config,
89 - prefix=f"{prefix}.dense",
90 - )
91 - max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
92 - self.rotary_emb = get_rope(
93 - self.head_size,
94 - max_position=max_position_embeddings,
95 - rope_parameters=config.rope_parameters,
96 - )
97 - scaling = self.head_size**-0.5
98 - self.attn = Attention(
99 - self.num_heads,
100 - self.head_size,
101 - scaling,
102 - cache_config=cache_config,
103 - quant_config=quant_config,
104 - prefix=f"{prefix}.attn",
105 - )
106 -
107 - def forward(
108 - self,
109 - position_ids: torch.Tensor,
110 - hidden_states: torch.Tensor,
111 - ) -> torch.Tensor:
112 - qkv, _ = self.query_key_value(hidden_states)
113 - q, k, v = qkv.chunk(chunks=3, dim=-1)
114 - q, k = self.rotary_emb(position_ids, q, k)
115 - attn_output = self.attn(q, k, v)
116 - output, _ = self.dense(attn_output)
117 - return output
118 -
119 -
120 -class GPTNeoXMLP(nn.Module):
121 - def __init__(
122 - self,
123 - config: GPTNeoXConfig,
124 - quant_config: QuantizationConfig | None = None,
125 - prefix: str = "",
126 - ):
127 - super().__init__()
128 - self.dense_h_to_4h = ColumnParallelLinear(
129 - config.hidden_size,
130 - config.intermediate_size,
131 - quant_config=quant_config,
132 - prefix=f"{prefix}.dense_h_to_4h",
133 - )
134 - self.dense_4h_to_h = RowParallelLinear(
135 - config.intermediate_size,
136 - config.hidden_size,
137 - quant_config=quant_config,
138 - prefix=f"{prefix}.dense_4h_to_h",
139 - )
140 - self.act = get_act_fn(config.hidden_act)
141 -
142 - def forward(self, hidden_states):
143 - hidden_states, _ = self.dense_h_to_4h(hidden_states)
144 - hidden_states = self.act(hidden_states)
145 - hidden_states, _ = self.dense_4h_to_h(hidden_states)
146 - return hidden_states
147 -
148 -
149 -class GPTNeoXLayer(nn.Module):
150 - def __init__(
151 - self,
152 - config: GPTNeoXConfig,
153 - cache_config: CacheConfig | None = None,
154 - quant_config: QuantizationConfig | None = None,
155 - prefix: str = "",
156 - ):
157 - super().__init__()
158 - self.use_parallel_residual = config.use_parallel_residual
159 - self.input_layernorm = nn.LayerNorm(
160 - config.hidden_size, eps=config.layer_norm_eps
161 - )
162 - self.post_attention_layernorm = nn.LayerNorm(
163 - config.hidden_size, eps=config.layer_norm_eps
164 - )
165 - self.attention = GPTNeoXAttention(
166 - config, cache_config, quant_config, prefix=f"{prefix}.attention"
167 - )
168 - self.mlp = GPTNeoXMLP(config, quant_config, prefix=f"{prefix}.mlp")
169 -
170 - def forward(
171 - self,
172 - position_ids: torch.Tensor,
173 - hidden_states: torch.Tensor,
174 - ) -> torch.Tensor:
175 - attn_input = self.input_layernorm(hidden_states)
176 - attn_output = self.attention(
177 - position_ids=position_ids,
178 - hidden_states=attn_input,
179 - )
180 -
181 - if self.use_parallel_residual:
182 - # pseudocode:
183 - # x = x + attn(ln1(x)) + mlp(ln2(x))
184 - mlp_input = self.post_attention_layernorm(hidden_states)
185 - mlp_output = self.mlp(mlp_input)
186 - hidden_states = mlp_output + attn_output + hidden_states
187 - else:
188 - # pseudocode:
189 - # x = x + attn(ln1(x))
190 - # x = x + mlp(ln2(x))
191 - attn_output = attn_output + hidden_states
192 - mlp_input = self.post_attention_layernorm(attn_output)
193 - mlp_output = self.mlp(mlp_input)
194 - hidden_states = mlp_output + attn_output
195 - return hidden_states
196 -
197 -
198 -@support_torch_compile
199 -class GPTNeoXModel(nn.Module):
200 - hf_to_vllm_mapper = WeightsMapper(
201 - orig_to_new_substr={"attention.bias": None, "attention.masked_bias": None}
202 - )
203 -
204 - def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
205 - super().__init__()
206 -
207 - config = vllm_config.model_config.hf_config
208 - cache_config = vllm_config.cache_config
209 - quant_config = vllm_config.quant_config
210 -
211 - self.config = config
212 -
213 - self.embed_in = VocabParallelEmbedding(
214 - config.vocab_size,
215 - config.hidden_size,
216 - )
217 - self.start_layer, self.end_layer, self.layers = make_layers(
218 - config.num_hidden_layers,
219 - lambda prefix: GPTNeoXLayer(
220 - config, cache_config, quant_config, prefix=prefix
221 - ),
222 - prefix=f"{prefix}.layers",
223 - )
224 - self.final_layer_norm = nn.LayerNorm(
225 - config.hidden_size, eps=config.layer_norm_eps
226 - )
227 - self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
228 - ["hidden_states"], config.hidden_size
229 - )
230 -
231 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
232 - return self.embed_in(input_ids)
233 -
234 - def forward(
235 - self,
236 - input_ids: torch.Tensor | None,
237 - position_ids: torch.Tensor,
238 - intermediate_tensors: IntermediateTensors | None,
239 - inputs_embeds: torch.Tensor | None = None,
240 - ) -> torch.Tensor | IntermediateTensors:
241 - if get_pp_group().is_first_rank:
242 - if inputs_embeds is not None:
243 - hidden_states = inputs_embeds
244 - else:
245 - hidden_states = self.embed_input_ids(input_ids)
246 - else:
247 - assert intermediate_tensors is not None
248 - hidden_states = intermediate_tensors["hidden_states"]
249 - for layer in islice(self.layers, self.start_layer, self.end_layer):
250 - hidden_states = layer(position_ids, hidden_states)
251 - if not get_pp_group().is_last_rank:
252 - return IntermediateTensors({"hidden_states": hidden_states})
253 - hidden_states = self.final_layer_norm(hidden_states)
254 - return hidden_states
255 -
256 - def _repack_qkv(
257 - self, weights: Iterable[tuple[str, torch.Tensor]]
258 - ) -> Iterable[tuple[str, torch.Tensor]]:
259 - # GPT-NeoX's fused QKV is laid out as (num_heads * 3 * head_size) on
260 - # its output dim (0), while vLLM expects (3 * num_heads * head_size).
261 - num_heads = self.config.num_attention_heads
262 - for name, loaded_weight in weights:
263 - if "query_key_value" in name:
264 - shape = loaded_weight.shape
265 - loaded_weight = loaded_weight.view((num_heads, 3, -1) + shape[1:])
266 - loaded_weight = loaded_weight.transpose(0, 1)
267 - loaded_weight = loaded_weight.reshape(shape)
268 - yield name, loaded_weight
269 -
270 - def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
271 - loader = AutoWeightsLoader(self)
272 - return loader.load_weights(
273 - self._repack_qkv(weights), mapper=self.hf_to_vllm_mapper
274 - )
275 -
276 -
277 -class GPTNeoXForCausalLM(nn.Module, SupportsPP):
278 - def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
279 - super().__init__()
280 - config = vllm_config.model_config.hf_config
281 - quant_config = vllm_config.quant_config
282 - self.config = config
283 - self.quant_config = quant_config
284 - self.gpt_neox = GPTNeoXModel(
285 - vllm_config=vllm_config, prefix=maybe_prefix(prefix, "gpt_neox")
286 - )
287 - self.embed_out = ParallelLMHead(
288 - config.vocab_size,
289 - config.hidden_size,
290 - quant_config=quant_config,
291 - prefix=maybe_prefix(prefix, "embed_out"),
292 - )
293 - if self.config.tie_word_embeddings:
294 - self.embed_out = self.embed_out.tie_weights(self.gpt_neox.embed_in)
295 - self.logits_processor = LogitsProcessor(config.vocab_size)
296 - self.make_empty_intermediate_tensors = (
297 - self.gpt_neox.make_empty_intermediate_tensors
298 - )
299 -
300 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
301 - return self.gpt_neox.embed_input_ids(input_ids)
302 -
303 - def forward(
304 - self,
305 - input_ids: torch.Tensor | None,
306 - positions: torch.Tensor,
307 - intermediate_tensors: IntermediateTensors | None = None,
308 - inputs_embeds: torch.Tensor | None = None,
309 - ) -> torch.Tensor | IntermediateTensors:
310 - hidden_states = self.gpt_neox(
311 - input_ids, positions, intermediate_tensors, inputs_embeds
312 - )
313 - return hidden_states
314 -
315 - def compute_logits(
316 - self,
317 - hidden_states: torch.Tensor,
318 - ) -> torch.Tensor | None:
319 - logits = self.logits_processor(self.embed_out, hidden_states)
320 - return logits
321 -
322 - def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
323 - loader = AutoWeightsLoader(self)
324 - return loader.load_weights(weights)
vllm/model_executor/models/jais2.py deleted
-441
@@ -1,441 +0,0 @@
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 -
26 -"""Inference-only Jais2 model compatible with HuggingFace weights."""
27 -
28 -from collections.abc import Iterable
29 -
30 -import torch
31 -from torch import nn
32 -from transformers import Jais2Config
33 -
34 -from vllm.compilation.decorators import support_torch_compile
35 -from vllm.config import CacheConfig, VllmConfig
36 -from vllm.distributed import (
37 - get_pp_group,
38 - get_tensor_model_parallel_world_size,
39 -)
40 -from vllm.model_executor.layers.activation import ReLUSquaredActivation
41 -from vllm.model_executor.layers.attention import Attention
42 -from vllm.model_executor.layers.linear import (
43 - ColumnParallelLinear,
44 - QKVParallelLinear,
45 - RowParallelLinear,
46 -)
47 -from vllm.model_executor.layers.logits_processor import LogitsProcessor
48 -from vllm.model_executor.layers.quantization import QuantizationConfig
49 -from vllm.model_executor.layers.rotary_embedding import get_rope
50 -from vllm.model_executor.layers.vocab_parallel_embedding import (
51 - ParallelLMHead,
52 - VocabParallelEmbedding,
53 -)
54 -from vllm.sequence import IntermediateTensors
55 -
56 -from .interfaces import SupportsLoRA, SupportsPP
57 -from .utils import (
58 - AutoWeightsLoader,
59 - PPMissingLayer,
60 - WeightsMapper,
61 - extract_layer_index,
62 - make_empty_intermediate_tensors_factory,
63 - make_layers,
64 - maybe_prefix,
65 -)
66 -
67 -
68 -class Jais2MLP(nn.Module):
69 - def __init__(
70 - self,
71 - hidden_size: int,
72 - intermediate_size: int,
73 - hidden_act: str,
74 - quant_config: QuantizationConfig | None = None,
75 - bias: bool = False,
76 - prefix: str = "",
77 - ) -> None:
78 - super().__init__()
79 - self.up_proj = ColumnParallelLinear(
80 - input_size=hidden_size,
81 - output_size=intermediate_size,
82 - bias=bias,
83 - quant_config=quant_config,
84 - prefix=f"{prefix}.up_proj",
85 - )
86 - self.down_proj = RowParallelLinear(
87 - input_size=intermediate_size,
88 - output_size=hidden_size,
89 - bias=bias,
90 - quant_config=quant_config,
91 - prefix=f"{prefix}.down_proj",
92 - )
93 - self.act_fn = ReLUSquaredActivation()
94 -
95 - def forward(self, x):
96 - x, _ = self.up_proj(x)
97 - x = self.act_fn(x)
98 - x, _ = self.down_proj(x)
99 - return x
100 -
101 -
102 -class Jais2Attention(nn.Module):
103 - def __init__(
104 - self,
105 - config: Jais2Config,
106 - hidden_size: int,
107 - num_heads: int,
108 - num_kv_heads: int,
109 - max_position_embeddings: int = 8192,
110 - quant_config: QuantizationConfig | None = None,
111 - bias: bool = False,
112 - cache_config: CacheConfig | None = None,
113 - prefix: str = "",
114 - ) -> None:
115 - super().__init__()
116 - layer_idx = extract_layer_index(prefix)
117 - self.hidden_size = hidden_size
118 - tp_size = get_tensor_model_parallel_world_size()
119 - self.total_num_heads = num_heads
120 - assert self.total_num_heads % tp_size == 0
121 - self.num_heads = self.total_num_heads // tp_size
122 - self.total_num_kv_heads = num_kv_heads
123 - if self.total_num_kv_heads >= tp_size:
124 - # Number of KV heads is greater than TP size, so we partition
125 - # the KV heads across multiple tensor parallel GPUs.
126 - assert self.total_num_kv_heads % tp_size == 0
127 - else:
128 - # Number of KV heads is less than TP size, so we replicate
129 - # the KV heads across multiple tensor parallel GPUs.
130 - assert tp_size % self.total_num_kv_heads == 0
131 - self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
132 - # MistralConfig has an optional head_dim introduced by Mistral-Nemo
133 - self.head_dim = getattr(
134 - config, "head_dim", self.hidden_size // self.total_num_heads
135 - )
136 - self.q_size = self.num_heads * self.head_dim
137 - self.kv_size = self.num_kv_heads * self.head_dim
138 - self.scaling = self.head_dim**-0.5
139 - self.max_position_embeddings = max_position_embeddings
140 -
141 - self.qkv_proj = QKVParallelLinear(
142 - hidden_size=hidden_size,
143 - head_size=self.head_dim,
144 - total_num_heads=self.total_num_heads,
145 - total_num_kv_heads=self.total_num_kv_heads,
146 - bias=bias,
147 - quant_config=quant_config,
148 - prefix=f"{prefix}.qkv_proj",
149 - )
150 -
151 - self.o_proj = RowParallelLinear(
152 - input_size=self.total_num_heads * self.head_dim,
153 - output_size=hidden_size,
154 - bias=bias,
155 - quant_config=quant_config,
156 - prefix=f"{prefix}.o_proj",
157 - )
158 -
159 - is_neox_style = True
160 - self.rotary_emb = get_rope(
161 - self.head_dim,
162 - max_position=max_position_embeddings,
163 - rope_parameters=getattr(config, "rope_parameters", None),
164 - is_neox_style=is_neox_style,
165 - )
166 -
167 - if hasattr(config, "interleaved_sliding_window"):
168 - interleaved_sliding_window = config.interleaved_sliding_window
169 - if isinstance(interleaved_sliding_window, int):
170 - sliding_window = interleaved_sliding_window
171 - elif isinstance(interleaved_sliding_window, list):
172 - sw_idx = layer_idx % len(interleaved_sliding_window)
173 - sliding_window = interleaved_sliding_window[sw_idx]
174 - else:
175 - raise ValueError(
176 - f"{type(interleaved_sliding_window)} is not supported."
177 - )
178 - else:
179 - sliding_window = None
180 -
181 - self.attn = Attention(
182 - self.num_heads,
183 - self.head_dim,
184 - self.scaling,
185 - num_kv_heads=self.num_kv_heads,
186 - cache_config=cache_config,
187 - quant_config=quant_config,
188 - per_layer_sliding_window=sliding_window,
189 - prefix=f"{prefix}.attn",
190 - )
191 -
192 - def forward(
193 - self,
194 - positions: torch.Tensor,
195 - hidden_states: torch.Tensor,
196 - ) -> torch.Tensor:
197 - qkv, _ = self.qkv_proj(hidden_states)
198 - q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
199 - q, k = self.rotary_emb(positions, q, k)
200 - attn_output = self.attn(q, k, v)
201 - output, _ = self.o_proj(attn_output)
202 - return output
203 -
204 -
205 -class Jais2DecoderLayer(nn.Module):
206 - def __init__(
207 - self,
208 - vllm_config: VllmConfig,
209 - config: Jais2Config,
210 - prefix: str = "",
211 - ) -> None:
212 - super().__init__()
213 -
214 - config = config or vllm_config.model_config.hf_config
215 - cache_config = vllm_config.cache_config
216 - quant_config = self.get_quant_config(vllm_config)
217 -
218 - self.hidden_size = config.hidden_size
219 - max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
220 - # Support abacusai/Smaug-72B-v0.1 with attention_bias
221 - attention_bias = getattr(config, "attention_bias", False) or getattr(
222 - config, "bias", False
223 - )
224 - self.self_attn = Jais2Attention(
225 - config=config,
226 - hidden_size=self.hidden_size,
227 - num_heads=config.num_attention_heads,
228 - num_kv_heads=getattr(
229 - config, "num_key_value_heads", config.num_attention_heads
230 - ),
231 - max_position_embeddings=max_position_embeddings,
232 - quant_config=quant_config,
233 - bias=attention_bias,
234 - cache_config=cache_config,
235 - prefix=f"{prefix}.self_attn",
236 - )
237 - self.mlp = Jais2MLP(
238 - hidden_size=self.hidden_size,
239 - intermediate_size=config.intermediate_size,
240 - hidden_act=config.hidden_act,
241 - quant_config=quant_config,
242 - bias=getattr(config, "mlp_bias", False),
243 - prefix=f"{prefix}.mlp",
244 - )
245 - self.input_layernorm = nn.LayerNorm(
246 - config.hidden_size, eps=config.layer_norm_eps
247 - )
248 - self.post_attention_layernorm = nn.LayerNorm(
249 - config.hidden_size, eps=config.layer_norm_eps
250 - )
251 -
252 - def forward(
253 - self,
254 - positions: torch.Tensor,
255 - hidden_states: torch.Tensor,
256 - residual: torch.Tensor | None,
257 - ) -> tuple[torch.Tensor, torch.Tensor]:
258 - # Self Attention
259 - if residual is None:
260 - residual = hidden_states
261 - hidden_states = self.input_layernorm(hidden_states)
262 - else:
263 - hidden_states, residual = (
264 - self.input_layernorm(hidden_states + residual),
265 - hidden_states + residual,
266 - )
267 - hidden_states = self.self_attn(
268 - positions=positions,
269 - hidden_states=hidden_states,
270 - )
271 -
272 - # Fully Connected
273 - hidden_states, residual = (
274 - self.post_attention_layernorm(hidden_states + residual),
275 - hidden_states + residual,
276 - )
277 - hidden_states = self.mlp(hidden_states)
278 - return hidden_states, residual
279 -
280 - def get_quant_config(self, vllm_config: VllmConfig) -> QuantizationConfig | None:
281 - """Get quantization config for this layer. Override in subclasses."""
282 - return vllm_config.quant_config
283 -
284 -
285 -@support_torch_compile
286 -class Jais2Model(nn.Module):
287 - def __init__(
288 - self,
289 - vllm_config: VllmConfig,
290 - prefix: str = "",
291 - layer_type: type[nn.Module] = Jais2DecoderLayer,
292 - ):
293 - super().__init__()
294 -
295 - config = vllm_config.model_config.hf_config
296 - quant_config = vllm_config.quant_config
297 -
298 - self.config = config
299 - self.quant_config = quant_config
300 -
301 - self.vocab_size = config.vocab_size
302 - self.org_vocab_size = config.vocab_size
303 - if get_pp_group().is_first_rank or (
304 - config.tie_word_embeddings and get_pp_group().is_last_rank
305 - ):
306 - self.embed_tokens = VocabParallelEmbedding(
307 - self.vocab_size,
308 - config.hidden_size,
309 - org_num_embeddings=config.vocab_size,
310 - quant_config=quant_config,
311 - )
312 - else:
313 - self.embed_tokens = PPMissingLayer()
314 - self.start_layer, self.end_layer, self.layers = make_layers(
315 - config.num_hidden_layers,
316 - lambda prefix: layer_type(
317 - config=config,
318 - vllm_config=vllm_config,
319 - prefix=prefix,
320 - ),
321 - prefix=f"{prefix}.layers",
322 - )
323 - if get_pp_group().is_last_rank:
324 - self.norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
325 - else:
326 - self.norm = PPMissingLayer()
327 -
328 - self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
329 - ["hidden_states", "residual"], config.hidden_size
330 - )
331 -
332 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
333 - return self.embed_tokens(input_ids)
334 -
335 - def forward(
336 - self,
337 - input_ids: torch.Tensor | None,
338 - positions: torch.Tensor,
339 - intermediate_tensors: IntermediateTensors | None,
340 - inputs_embeds: torch.Tensor | None = None,
341 - ) -> torch.Tensor | IntermediateTensors | tuple[torch.Tensor, list[torch.Tensor]]:
342 - if get_pp_group().is_first_rank:
343 - if inputs_embeds is not None:
344 - hidden_states = inputs_embeds
345 - else:
346 - hidden_states = self.embed_input_ids(input_ids)
347 - residual = None
348 - else:
349 - assert intermediate_tensors is not None
350 - hidden_states = intermediate_tensors["hidden_states"]
351 - residual = intermediate_tensors["residual"]
352 -
353 - for i in range(self.start_layer, self.end_layer):
354 - layer = self.layers[i]
355 - hidden_states, residual = layer(positions, hidden_states, residual)
356 -
357 - if not get_pp_group().is_last_rank:
358 - return IntermediateTensors(
359 - {"hidden_states": hidden_states, "residual": residual}
360 - )
361 -
362 - hidden_states, _ = self.norm(hidden_states + residual), residual
363 - return hidden_states
364 -
365 -
366 -class Jais2ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
367 - hf_to_vllm_mapper = WeightsMapper(
368 - orig_to_new_stacked={
369 - # weight_name: (param_name, shard_id)
370 - ".q_proj": (".qkv_proj", "q"),
371 - ".k_proj": (".qkv_proj", "k"),
372 - ".v_proj": (".qkv_proj", "v"),
373 - }
374 - )
375 - packed_modules_mapping = {
376 - "qkv_proj": ["q_proj", "k_proj", "v_proj"],
377 - }
378 -
379 - embedding_modules = {
380 - "embed_tokens": "input_embeddings",
381 - "lm_head": "output_embeddings",
382 - }
383 -
384 - def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
385 - super().__init__()
386 - config = vllm_config.model_config.hf_config
387 - quant_config = vllm_config.quant_config
388 - self.config = config
389 - self.model = self._init_model(
390 - vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
391 - )
392 -
393 - if get_pp_group().is_last_rank:
394 - self.lm_head = ParallelLMHead(
395 - config.vocab_size,
396 - config.hidden_size,
397 - quant_config=quant_config,
398 - prefix=maybe_prefix(prefix, "lm_head"),
399 - )
400 - if config.tie_word_embeddings:
401 - self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
402 -
403 - logit_scale = getattr(config, "logit_scale", 1.0)
404 - self.logits_processor = LogitsProcessor(
405 - config.vocab_size, scale=logit_scale
406 - )
407 - else:
408 - self.lm_head = PPMissingLayer()
409 -
410 - self.make_empty_intermediate_tensors = (
411 - self.model.make_empty_intermediate_tensors
412 - )
413 -
414 - def _init_model(self, vllm_config: VllmConfig, prefix: str = ""):
415 - return Jais2Model(vllm_config=vllm_config, prefix=prefix)
416 -
417 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
418 - return self.model.embed_input_ids(input_ids)
419 -
420 - def forward(
421 - self,
422 - input_ids: torch.Tensor | None,
423 - positions: torch.Tensor,
424 - intermediate_tensors: IntermediateTensors | None = None,
425 - inputs_embeds: torch.Tensor | None = None,
426 - ) -> torch.Tensor | IntermediateTensors:
427 - model_output = self.model(
428 - input_ids, positions, intermediate_tensors, inputs_embeds
429 - )
430 - return model_output
431 -
432 - def compute_logits(
433 - self,
434 - hidden_states: torch.Tensor,
435 - ) -> torch.Tensor | None:
436 - logits = self.logits_processor(self.lm_head, hidden_states)
437 - return logits
438 -
439 - def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
440 - loader = AutoWeightsLoader(self)
441 - return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/phi.py deleted
-325
@@ -1,325 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -
4 -# Adapted from
5 -# https://huggingface.co/microsoft/phi-1_5/blob/main/modeling_phi.py
6 -# Copyright 2023 The vLLM team.
7 -# Copyright (c) Microsoft Corporation.
8 -# Licensed under the MIT license.
9 -#
10 -# BSD 3-Clause License
11 -#
12 -# Copyright (c) 2022, Tri Dao, trid@cs.stanford.edu.
13 -# All rights reserved.
14 -#
15 -# Redistribution and use in source and binary forms, with or without
16 -# modification, are permitted provided that the following conditions are met:
17 -#
18 -# * Redistributions of source code must retain the above copyright notice, this
19 -# list of conditions and the following disclaimer.
20 -#
21 -# * Redistributions in binary form must reproduce the above copyright notice,
22 -# this list of conditions and the following disclaimer in the documentation
23 -# and/or other materials provided with the distribution.
24 -#
25 -# * Neither the name of the copyright holder nor the names of its
26 -# contributors may be used to endorse or promote products derived from
27 -# this software without specific prior written permission.
28 -#
29 -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
33 -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
37 -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 -"""Inference-only Phi-1.5 model compatible with HuggingFace weights."""
40 -
41 -from collections.abc import Iterable
42 -from itertools import islice
43 -
44 -import torch
45 -from torch import nn
46 -from transformers import PhiConfig
47 -
48 -from vllm.compilation.decorators import support_torch_compile
49 -from vllm.config import CacheConfig, VllmConfig
50 -from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
51 -from vllm.model_executor.layers.activation import get_act_fn
52 -from vllm.model_executor.layers.attention import Attention
53 -from vllm.model_executor.layers.linear import (
54 - ColumnParallelLinear,
55 - QKVParallelLinear,
56 - RowParallelLinear,
57 -)
58 -from vllm.model_executor.layers.logits_processor import LogitsProcessor
59 -from vllm.model_executor.layers.quantization import QuantizationConfig
60 -from vllm.model_executor.layers.rotary_embedding import get_rope
61 -from vllm.model_executor.layers.vocab_parallel_embedding import (
62 - ParallelLMHead,
63 - VocabParallelEmbedding,
64 -)
65 -from vllm.sequence import IntermediateTensors
66 -
67 -from .interfaces import SupportsLoRA, SupportsPP
68 -from .utils import (
69 - AutoWeightsLoader,
70 - WeightsMapper,
71 - make_empty_intermediate_tensors_factory,
72 - make_layers,
73 - maybe_prefix,
74 -)
75 -
76 -
77 -class PhiAttention(nn.Module):
78 - def __init__(
79 - self,
80 - config: PhiConfig,
81 - cache_config: CacheConfig | None = None,
82 - quant_config: QuantizationConfig | None = None,
83 - prefix: str = "",
84 - ):
85 - super().__init__()
86 - self.hidden_size = config.hidden_size
87 - self.head_size = self.hidden_size // config.num_attention_heads
88 -
89 - tensor_model_parallel_world_size = get_tensor_model_parallel_world_size()
90 - assert config.num_attention_heads % tensor_model_parallel_world_size == 0
91 - self.num_heads = config.num_attention_heads // tensor_model_parallel_world_size
92 -
93 - # pylint: disable=C0103
94 - self.qkv_proj = QKVParallelLinear(
95 - self.hidden_size,
96 - self.head_size,
97 - config.num_attention_heads,
98 - bias=True,
99 - quant_config=quant_config,
100 - prefix=f"{prefix}.qkv_proj",
101 - )
102 - self.dense = RowParallelLinear(
103 - self.hidden_size,
104 - self.hidden_size,
105 - quant_config=quant_config,
106 - prefix=f"{prefix}.dense",
107 - )
108 -
109 - scaling = self.head_size**-0.5
110 -
111 - max_position_embeddings = getattr(config, "max_position_embeddings", 2048)
112 - self.rotary_emb = get_rope(
113 - self.head_size,
114 - max_position=max_position_embeddings,
115 - rope_parameters=config.rope_parameters,
116 - )
117 - self.attn = Attention(
118 - self.num_heads,
119 - self.head_size,
120 - scaling,
121 - cache_config=cache_config,
122 - quant_config=quant_config,
123 - prefix=f"{prefix}.attn",
124 - )
125 -
126 - def forward(
127 - self,
128 - position_ids: torch.Tensor,
129 - hidden_states: torch.Tensor,
130 - ) -> torch.Tensor:
131 - qkv, _ = self.qkv_proj(hidden_states)
132 - q, k, v = qkv.chunk(chunks=3, dim=-1)
133 - q, k = self.rotary_emb(position_ids, q, k)
134 - attn_output = self.attn(q, k, v)
135 - output, _ = self.dense(attn_output)
136 - return output
137 -
138 -
139 -class PhiMLP(nn.Module):
140 - def __init__(
141 - self,
142 - config: PhiConfig,
143 - quant_config: QuantizationConfig | None = None,
144 - prefix: str = "",
145 - ):
146 - super().__init__()
147 -
148 - n_inner = getattr(config, "n_inner", None)
149 - n_inner = n_inner if n_inner is not None else 4 * config.hidden_size
150 -
151 - self.fc1 = ColumnParallelLinear(
152 - config.hidden_size,
153 - n_inner,
154 - quant_config=quant_config,
155 - prefix=f"{prefix}.fc1",
156 - )
157 - self.fc2 = RowParallelLinear(
158 - n_inner,
159 - config.hidden_size,
160 - quant_config=quant_config,
161 - prefix=f"{prefix}.fc2",
162 - )
163 - self.act = get_act_fn(config.hidden_act)
164 -
165 - def forward(self, hidden_states):
166 - hidden_states, _ = self.fc1(hidden_states)
167 - hidden_states = self.act(hidden_states)
168 - hidden_states, _ = self.fc2(hidden_states)
169 - return hidden_states
170 -
171 -
172 -class PhiLayer(nn.Module):
173 - def __init__(
174 - self,
175 - config: PhiConfig,
176 - cache_config: CacheConfig | None = None,
177 - quant_config: QuantizationConfig | None = None,
178 - prefix: str = "",
179 - ):
180 - super().__init__()
181 - self.input_layernorm = nn.LayerNorm(
182 - config.hidden_size, eps=config.layer_norm_eps
183 - )
184 - self.self_attn = PhiAttention(
185 - config, cache_config, quant_config, prefix=f"{prefix}.self_attn"
186 - )
187 - self.mlp = PhiMLP(config, quant_config, prefix=f"{prefix}.mlp")
188 -
189 - def forward(
190 - self,
191 - position_ids: torch.Tensor,
192 - hidden_states: torch.Tensor,
193 - ) -> torch.Tensor:
194 - residual = hidden_states
195 - hidden_states = self.input_layernorm(hidden_states)
196 - attn_outputs = self.self_attn(
197 - position_ids=position_ids,
198 - hidden_states=hidden_states,
199 - )
200 - feed_forward_hidden_states = self.mlp(hidden_states)
201 - hidden_states = attn_outputs + feed_forward_hidden_states + residual
202 - return hidden_states
203 -
204 -
205 -@support_torch_compile
206 -class PhiModel(nn.Module):
207 - def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
208 - super().__init__()
209 -
210 - config = vllm_config.model_config.hf_config
211 - cache_config = vllm_config.cache_config
212 - quant_config = vllm_config.quant_config
213 -
214 - self.config = config
215 - self.quant_config = quant_config
216 - self.embed_tokens = VocabParallelEmbedding(
217 - config.vocab_size, config.hidden_size
218 - )
219 - self.start_layer, self.end_layer, self.layers = make_layers(
220 - config.num_hidden_layers,
221 - lambda prefix: PhiLayer(config, cache_config, quant_config, prefix=prefix),
222 - prefix=f"{prefix}.layers",
223 - )
224 - self.final_layernorm = nn.LayerNorm(
225 - config.hidden_size, eps=config.layer_norm_eps
226 - )
227 - self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
228 - ["hidden_states"], config.hidden_size
229 - )
230 -
231 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
232 - return self.embed_tokens(input_ids)
233 -
234 - def forward(
235 - self,
236 - input_ids: torch.Tensor | None,
237 - positions: torch.Tensor,
238 - intermediate_tensors: IntermediateTensors | None,
239 - inputs_embeds: torch.Tensor | None = None,
240 - ) -> torch.Tensor | IntermediateTensors:
241 - if get_pp_group().is_first_rank:
242 - if inputs_embeds is not None:
243 - hidden_states = inputs_embeds
244 - else:
245 - hidden_states = self.embed_input_ids(input_ids)
246 - else:
247 - assert intermediate_tensors is not None
248 - hidden_states = intermediate_tensors["hidden_states"]
249 - for layer in islice(self.layers, self.start_layer, self.end_layer):
250 - hidden_states = layer(positions, hidden_states)
251 -
252 - if not get_pp_group().is_last_rank:
253 - return IntermediateTensors({"hidden_states": hidden_states})
254 -
255 - hidden_states = self.final_layernorm(hidden_states)
256 -
257 - return hidden_states
258 -
259 -
260 -class PhiForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
261 - hf_to_vllm_mapper = WeightsMapper(
262 - orig_to_new_stacked={
263 - # weight_name: (param_name, shard_id)
264 - ".q_proj": (".qkv_proj", "q"),
265 - ".k_proj": (".qkv_proj", "k"),
266 - ".v_proj": (".qkv_proj", "v"),
267 - }
268 - )
269 - packed_modules_mapping = {
270 - "qkv_proj": ["q_proj", "k_proj", "v_proj"],
271 - }
272 -
273 - def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
274 - super().__init__()
275 - config = vllm_config.model_config.hf_config
276 - quant_config = vllm_config.quant_config
277 -
278 - self.config = config
279 - # lm_head use bias, cannot share word embeddings
280 - assert not config.tie_word_embeddings
281 -
282 - self.quant_config = quant_config
283 -
284 - self.model = PhiModel(
285 - vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
286 - )
287 -
288 - self.lm_head = ParallelLMHead(
289 - config.vocab_size,
290 - config.hidden_size,
291 - bias=True,
292 - quant_config=quant_config,
293 - prefix=maybe_prefix(prefix, "lm_head"),
294 - )
295 - self.logits_processor = LogitsProcessor(config.vocab_size)
296 - self.make_empty_intermediate_tensors = (
297 - self.model.make_empty_intermediate_tensors
298 - )
299 -
300 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
301 - return self.model.embed_input_ids(input_ids)
302 -
303 - def forward(
304 - self,
305 - input_ids: torch.Tensor | None,
306 - positions: torch.Tensor,
307 - intermediate_tensors: IntermediateTensors | None = None,
308 - inputs_embeds: torch.Tensor | None = None,
309 - ) -> torch.Tensor | IntermediateTensors:
310 - hidden_states = self.model(
311 - input_ids, positions, intermediate_tensors, inputs_embeds
312 - )
313 -
314 - return hidden_states
315 -
316 - def compute_logits(
317 - self,
318 - hidden_states: torch.Tensor,
319 - ) -> torch.Tensor | None:
320 - logits = self.logits_processor(self.lm_head, hidden_states, self.lm_head.bias)
321 - return logits
322 -
323 - def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
324 - loader = AutoWeightsLoader(self)
325 - return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/registry.py
+4 -4
@@ -120,7 +120,6 @@ _TEXT_GENERATION_MODELS = {
120 "GptOssForCausalLM": ("gpt_oss", "GptOssForCausalLM"),
121 "GPT2LMHeadModel": ("gpt2", "GPT2LMHeadModel"),
122 "GPTJForCausalLM": ("gpt_j", "GPTJForCausalLM"),
123 - "GPTNeoXForCausalLM": ("gpt_neox", "GPTNeoXForCausalLM"),
123 "GraniteForCausalLM": ("granite", "GraniteForCausalLM"),
124 "GraniteMoeForCausalLM": ("granitemoe", "GraniteMoeForCausalLM"),
125 "GraniteMoeHybridForCausalLM": ("granitemoehybrid", "GraniteMoeHybridForCausalLM"),
@@ -136,7 +135,6 @@ _TEXT_GENERATION_MODELS = {
135 "InternLM3ForCausalLM": ("llama", "LlamaForCausalLM"),
136 "IQuestCoderForCausalLM": ("llama", "LlamaForCausalLM"),
137 "IQuestLoopCoderForCausalLM": ("iquest_loopcoder", "IQuestLoopCoderForCausalLM"),
139 - "Jais2ForCausalLM": ("jais2", "Jais2ForCausalLM"),
138 "JambaForCausalLM": ("jamba", "JambaForCausalLM"),
139 "K2HorizonForCausalLM": ("k2_horizon", "K2HorizonForCausalLM"),
140 "KimiLinearForCausalLM": (
@@ -188,7 +186,6 @@ _TEXT_GENERATION_MODELS = {
186 "PanguProMoEV2ForCausalLM": ("openpangu", "PanguProMoEV2ForCausalLM"),
187 "PanguUltraMoEForCausalLM": ("openpangu", "PanguUltraMoEForCausalLM"),
188 "Param2MoEForCausalLM": ("param2moe", "Param2MoEForCausalLM"),
191 - "PhiForCausalLM": ("phi", "PhiForCausalLM"),
189 "Phi3ForCausalLM": ("phi3", "Phi3ForCausalLM"),
190 "PhiMoEForCausalLM": ("phimoe", "PhiMoEForCausalLM"),
191 "Plamo3ForCausalLM": ("plamo3", "Plamo3ForCausalLM"),
@@ -200,7 +197,6 @@ _TEXT_GENERATION_MODELS = {
197 "Qwen3_5MoeForCausalLM": ("qwen3_5", "Qwen3_5MoeForCausalLM"),
198 "SarvamMoEForCausalLM": ("sarvam", "SarvamMoEForCausalLM"),
199 "SarvamMLAForCausalLM": ("sarvam", "SarvamMLAForCausalLM"),
203 - "SeedOssForCausalLM": ("seed_oss", "SeedOssForCausalLM"),
200 "Step1ForCausalLM": ("step1", "Step1ForCausalLM"),
201 "Step3TextForCausalLM": ("step3_text", "Step3TextForCausalLM"),
202 "Step3p5ForCausalLM": ("step3p5", "Step3p5ForCausalLM"),
@@ -709,13 +705,17 @@ _TRANSFORMERS_SUPPORTED_MODELS = {
705 "FlexOlmoForCausalLM": ("transformers", "TransformersMoEForCausalLM"),
706 "GlmForCausalLM": ("transformers", "TransformersForCausalLM"),
707 "GPTBigCodeForCausalLM": ("transformers", "TransformersForCausalLM"),
708 + "GPTNeoXForCausalLM": ("transformers", "TransformersForCausalLM"),
709 "HunYuanDenseV1ForCausalLM": ("transformers", "TransformersForCausalLM"),
710 "HunYuanMoEV1ForCausalLM": ("transformers", "TransformersMoEForCausalLM"),
711 + "Jais2ForCausalLM": ("transformers", "TransformersForCausalLM"),
712 "MellumForCausalLM": ("transformers", "TransformersMoEForCausalLM"),
713 "NanbeigeForCausalLM": ("transformers", "TransformersForCausalLM"),
714 "OlmoForCausalLM": ("transformers", "TransformersForCausalLM"),
715 "Olmo2ForCausalLM": ("transformers", "TransformersForCausalLM"),
716 "Olmo3ForCausalLM": ("transformers", "TransformersForCausalLM"),
717 + "PhiForCausalLM": ("transformers", "TransformersForCausalLM"),
718 + "SeedOssForCausalLM": ("transformers", "TransformersForCausalLM"),
719 "SmolLM3ForCausalLM": ("transformers", "TransformersForCausalLM"),
720 "Starcoder2ForCausalLM": ("transformers", "TransformersForCausalLM"),
721 "VaultGemmaForCausalLM": ("transformers", "TransformersForCausalLM"),
vllm/model_executor/models/seed_oss.py deleted
-432
@@ -1,432 +0,0 @@
1 -# SPDX-License-Identifier: Apache-2.0
2 -# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 -
4 -# Copyright 2025 The Seed team.
5 -# Copyright 2023 The vLLM team.
6 -# Copyright 2022 EleutherAI and the HuggingFace Inc. team. All rights reserved.
7 -#
8 -# This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
9 -# and OPT implementations in this library. It has been modified from its
10 -# original forms to accommodate minor architectural differences compared
11 -# to GPT-NeoX and OPT used by the Meta AI team that trained the model.
12 -#
13 -# Licensed under the Apache License, Version 2.0 (the "License");
14 -# you may not use this file except in compliance with the License.
15 -# You may obtain a copy of the License at
16 -#
17 -# http://www.apache.org/licenses/LICENSE-2.0
18 -#
19 -# Unless required by applicable law or agreed to in writing, software
20 -# distributed under the License is distributed on an "AS IS" BASIS,
21 -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 -# See the License for the specific language governing permissions and
23 -# limitations under the License.
24 -"""Inference-only SeedOss model compatible with HuggingFace weights."""
25 -
26 -from collections.abc import Iterable
27 -from itertools import islice
28 -
29 -import torch
30 -from torch import nn
31 -from transformers import PreTrainedConfig as SeedOssConfig
32 -
33 -from vllm.compilation.decorators import support_torch_compile
34 -from vllm.config import CacheConfig, VllmConfig
35 -from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
36 -from vllm.logger import init_logger
37 -from vllm.model_executor.layers.activation import SiluAndMul
38 -from vllm.model_executor.layers.attention import Attention
39 -from vllm.model_executor.layers.layernorm import RMSNorm
40 -from vllm.model_executor.layers.linear import (
41 - MergedColumnParallelLinear,
42 - QKVParallelLinear,
43 - RowParallelLinear,
44 -)
45 -from vllm.model_executor.layers.logits_processor import LogitsProcessor
46 -from vllm.model_executor.layers.quantization import QuantizationConfig
47 -from vllm.model_executor.layers.rotary_embedding import get_rope
48 -from vllm.model_executor.layers.vocab_parallel_embedding import (
49 - ParallelLMHead,
50 - VocabParallelEmbedding,
51 -)
52 -from vllm.sequence import IntermediateTensors
53 -from vllm.transformers_utils.config import set_default_rope_theta
54 -from vllm.v1.attention.backend import AttentionType
55 -
56 -from .interfaces import SupportsLoRA, SupportsPP
57 -from .utils import (
58 - AutoWeightsLoader,
59 - PPMissingLayer,
60 - WeightsMapper,
61 - make_empty_intermediate_tensors_factory,
62 - make_layers,
63 - maybe_prefix,
64 -)
65 -
66 -logger = init_logger(__name__)
67 -
68 -
69 -class SeedOssMLP(nn.Module):
70 - def __init__(
71 - self,
72 - hidden_size: int,
73 - intermediate_size: int,
74 - hidden_act: str,
75 - quant_config: QuantizationConfig | None = None,
76 - prefix: str = "",
77 - ) -> None:
78 - super().__init__()
79 - self.gate_up_proj = MergedColumnParallelLinear(
80 - hidden_size,
81 - [intermediate_size] * 2,
82 - bias=False,
83 - quant_config=quant_config,
84 - prefix=f"{prefix}.gate_up_proj",
85 - )
86 - self.down_proj = RowParallelLinear(
87 - intermediate_size,
88 - hidden_size,
89 - bias=False,
90 - quant_config=quant_config,
91 - prefix=f"{prefix}.down_proj",
92 - )
93 - if hidden_act != "silu":
94 - raise ValueError(
95 - f"Unsupported activation: {hidden_act}. Only silu is supported for now."
96 - )
97 - self.act_fn = SiluAndMul()
98 -
99 - def forward(self, x):
100 - gate_up, _ = self.gate_up_proj(x)
101 - x = self.act_fn(gate_up)
102 - x, _ = self.down_proj(x)
103 - return x
104 -
105 -
106 -class SeedOssAttention(nn.Module):
107 - def __init__(
108 - self,
109 - hidden_size: int,
110 - num_heads: int,
111 - num_kv_heads: int,
112 - head_dim: int,
113 - rope_parameters: dict,
114 - max_position: int = 4096 * 32,
115 - cache_config: CacheConfig | None = None,
116 - quant_config: QuantizationConfig | None = None,
117 - prefix: str = "",
118 - attn_type: str = AttentionType.DECODER,
119 - ) -> None:
120 - super().__init__()
121 - self.hidden_size = hidden_size
122 - tp_size = get_tensor_model_parallel_world_size()
123 - self.total_num_heads = num_heads
124 - assert self.total_num_heads % tp_size == 0
125 - self.num_heads = self.total_num_heads // tp_size
126 - self.total_num_kv_heads = num_kv_heads
127 - self.head_dim = head_dim
128 - if self.total_num_kv_heads >= tp_size:
129 - # Number of KV heads is greater than TP size, so we partition
130 - # the KV heads across multiple tensor parallel GPUs.
131 - assert self.total_num_kv_heads % tp_size == 0
132 - else:
133 - # Number of KV heads is less than TP size, so we replicate
134 - # the KV heads across multiple tensor parallel GPUs.
135 - assert tp_size % self.total_num_kv_heads == 0
136 - self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
137 - self.q_size = self.num_heads * self.head_dim
138 - self.kv_size = self.num_kv_heads * self.head_dim
139 - self.scaling = self.head_dim**-0.5
140 -
141 - self.qkv_proj = QKVParallelLinear(
142 - hidden_size,
143 - self.head_dim,
144 - self.total_num_heads,
145 - self.total_num_kv_heads,
146 - bias=True,
147 - quant_config=quant_config,
148 - prefix=f"{prefix}.qkv_proj",
149 - )
150 - self.o_proj = RowParallelLinear(
151 - self.total_num_heads * self.head_dim,
152 - hidden_size,
153 - bias=False,
154 - quant_config=quant_config,
155 - prefix=f"{prefix}.o_proj",
156 - )
157 -
158 - self.rotary_emb = get_rope(
159 - self.head_dim,
160 - max_position=max_position,
161 - rope_parameters=rope_parameters,
162 - )
163 - self.attn = Attention(
164 - self.num_heads,
165 - self.head_dim,
166 - self.scaling,
167 - num_kv_heads=self.num_kv_heads,
168 - cache_config=cache_config,
169 - quant_config=quant_config,
170 - attn_type=attn_type,
171 - prefix=f"{prefix}.attn",
172 - )
173 -
174 - def forward(
175 - self,
176 - positions: torch.Tensor,
177 - hidden_states: torch.Tensor,
178 - ) -> torch.Tensor:
179 - qkv, _ = self.qkv_proj(hidden_states)
180 - q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
181 - q, k = self.rotary_emb(positions, q, k)
182 - attn_output = self.attn(q, k, v)
183 - output, _ = self.o_proj(attn_output)
184 - return output
185 -
186 -
187 -class SeedOssDecoderLayer(nn.Module):
188 - def __init__(
189 - self,
190 - config: SeedOssConfig,
191 - cache_config: CacheConfig | None = None,
192 - quant_config: QuantizationConfig | None = None,
193 - prefix: str = "",
194 - ) -> None:
195 - super().__init__()
196 - self.hidden_size = config.hidden_size
197 - set_default_rope_theta(config, default_theta=1000000)
198 -
199 - # By default, SeedOss uses causal attention as it is a
200 - # decoder-only model.
201 - # You can override the HF config with `is_causal=False` to enable
202 - # bidirectional attention, which is used in some embedding models
203 - if getattr(config, "is_causal", True):
204 - attn_type = AttentionType.DECODER
205 - else:
206 - attn_type = AttentionType.ENCODER_ONLY
207 -
208 - self.self_attn = SeedOssAttention(
209 - hidden_size=self.hidden_size,
210 - num_heads=config.num_attention_heads,
211 - max_position=config.max_position_embeddings,
212 - num_kv_heads=config.num_key_value_heads,
213 - head_dim=config.head_dim,
214 - cache_config=cache_config,
215 - quant_config=quant_config,
216 - rope_parameters=config.rope_parameters,
217 - prefix=f"{prefix}.self_attn",
218 - attn_type=attn_type,
219 - )
220 - self.mlp = SeedOssMLP(
221 - hidden_size=self.hidden_size,
222 - intermediate_size=config.intermediate_size,
223 - hidden_act=config.hidden_act,
224 - quant_config=quant_config,
225 - prefix=f"{prefix}.mlp",
226 - )
227 - self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
228 - self.post_attention_layernorm = RMSNorm(
229 - config.hidden_size, eps=config.rms_norm_eps
230 - )
231 -
232 - def forward(
233 - self,
234 - positions: torch.Tensor,
235 - hidden_states: torch.Tensor,
236 - residual: torch.Tensor | None,
237 - ) -> tuple[torch.Tensor, torch.Tensor]:
238 - # Self Attention
239 - if residual is None:
240 - residual = hidden_states
241 - hidden_states = self.input_layernorm(hidden_states)
242 - else:
243 - hidden_states, residual = self.input_layernorm(hidden_states, residual)
244 - hidden_states = self.self_attn(
245 - positions=positions,
246 - hidden_states=hidden_states,
247 - )
248 -
249 - # Fully Connected
250 - hidden_states, residual = self.post_attention_layernorm(hidden_states, residual)
251 - hidden_states = self.mlp(hidden_states)
252 - return hidden_states, residual
253 -
254 -
255 -@support_torch_compile(
256 - dynamic_arg_dims={
257 - "input_ids": 0,
258 - "positions": -1,
259 - "intermediate_tensors": 0,
260 - "inputs_embeds": 0,
261 - }
262 -)
263 -class SeedOssModel(nn.Module):
264 - def __init__(
265 - self,
266 - *,
267 - vllm_config: VllmConfig,
268 - prefix: str = "",
269 - decoder_layer_type: type[nn.Module] = SeedOssDecoderLayer,
270 - ):
271 - super().__init__()
272 -
273 - config = vllm_config.model_config.hf_config
274 - cache_config = vllm_config.cache_config
275 - quant_config = vllm_config.quant_config
276 -
277 - # TODO (@robertgshaw2): see if this can be moved out
278 - if cache_config.sliding_window is not None and hasattr(
279 - config, "max_window_layers"
280 - ):
281 - assert config.max_window_layers == config.num_hidden_layers, (
282 - "Sliding window for some but all layers is not supported. "
283 - "This model uses sliding window but `max_window_layers` = {} "
284 - "is less than `num_hidden_layers` = {}. Please open an issue "
285 - "to discuss this feature.".format(
286 - config.max_window_layers,
287 - config.num_hidden_layers,
288 - )
289 - )
290 -
291 - self.config = config
292 - self.quant_config = quant_config
293 - self.vocab_size = config.vocab_size
294 -
295 - if get_pp_group().is_first_rank or (
296 - config.tie_word_embeddings and get_pp_group().is_last_rank
297 - ):
298 - self.embed_tokens = VocabParallelEmbedding(
299 - config.vocab_size,
300 - config.hidden_size,
301 - quant_config=quant_config,
302 - prefix=f"{prefix}.embed_tokens",
303 - )
304 - else:
305 - self.embed_tokens = PPMissingLayer()
306 -
307 - # Use the provided decoder layer type or default to SeedDecoderLayer
308 - decoder_layer_type = decoder_layer_type or SeedOssDecoderLayer
309 - self.start_layer, self.end_layer, self.layers = make_layers(
310 - config.num_hidden_layers,
311 - lambda prefix: decoder_layer_type(
312 - config=config,
313 - cache_config=cache_config,
314 - quant_config=quant_config,
315 - prefix=prefix,
316 - ),
317 - prefix=f"{prefix}.layers",
318 - )
319 -
320 - self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
321 - ["hidden_states", "residual"], config.hidden_size
322 - )
323 - if get_pp_group().is_last_rank:
324 - self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
325 - else:
326 - self.norm = PPMissingLayer()
327 -
328 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
329 - return self.embed_tokens(input_ids)
330 -
331 - def forward(
332 - self,
333 - input_ids: torch.Tensor | None,
334 - positions: torch.Tensor,
335 - intermediate_tensors: IntermediateTensors | None = None,
336 - inputs_embeds: torch.Tensor | None = None,
337 - ) -> torch.Tensor | IntermediateTensors:
338 - if get_pp_group().is_first_rank:
339 - if inputs_embeds is not None:
340 - hidden_states = inputs_embeds
341 - else:
342 - hidden_states = self.embed_input_ids(input_ids)
343 - residual = None
344 - else:
345 - assert intermediate_tensors is not None
346 - hidden_states = intermediate_tensors["hidden_states"]
347 - residual = intermediate_tensors["residual"]
348 - for layer in islice(self.layers, self.start_layer, self.end_layer):
349 - hidden_states, residual = layer(
350 - positions,
351 - hidden_states,
352 - residual,
353 - )
354 - if not get_pp_group().is_last_rank:
355 - return IntermediateTensors(
356 - {"hidden_states": hidden_states, "residual": residual}
357 - )
358 - hidden_states, _ = self.norm(hidden_states, residual)
359 - return hidden_states
360 -
361 -
362 -class SeedOssForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
363 - hf_to_vllm_mapper = WeightsMapper(
364 - orig_to_new_stacked={
365 - # weight_name: (param_name, shard_id)
366 - ".q_proj": (".qkv_proj", "q"),
367 - ".k_proj": (".qkv_proj", "k"),
368 - ".v_proj": (".qkv_proj", "v"),
369 - ".gate_proj": (".gate_up_proj", 0),
370 - ".up_proj": (".gate_up_proj", 1),
371 - }
372 - )
373 - packed_modules_mapping = {
374 - "qkv_proj": ["q_proj", "k_proj", "v_proj"],
375 - "gate_up_proj": ["gate_proj", "up_proj"],
376 - }
377 -
378 - def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
379 - super().__init__()
380 - config = vllm_config.model_config.hf_config
381 - quant_config = vllm_config.quant_config
382 -
383 - self.config = config
384 -
385 - self.quant_config = quant_config
386 - self.model = SeedOssModel(
387 - vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
388 - )
389 -
390 - if get_pp_group().is_last_rank:
391 - self.lm_head = ParallelLMHead(
392 - config.vocab_size,
393 - config.hidden_size,
394 - quant_config=quant_config,
395 - prefix=maybe_prefix(prefix, "lm_head"),
396 - )
397 - if config.tie_word_embeddings:
398 - self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
399 - else:
400 - self.lm_head = PPMissingLayer()
401 -
402 - self.logits_processor = LogitsProcessor(config.vocab_size)
403 -
404 - self.make_empty_intermediate_tensors = (
405 - self.model.make_empty_intermediate_tensors
406 - )
407 -
408 - def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
409 - return self.model.embed_input_ids(input_ids)
410 -
411 - def forward(
412 - self,
413 - input_ids: torch.Tensor | None,
414 - positions: torch.Tensor,
415 - intermediate_tensors: IntermediateTensors | None = None,
416 - inputs_embeds: torch.Tensor | None = None,
417 - ) -> torch.Tensor | IntermediateTensors:
418 - hidden_states = self.model(
419 - input_ids, positions, intermediate_tensors, inputs_embeds
420 - )
421 - return hidden_states
422 -
423 - def compute_logits(
424 - self,
425 - hidden_states: torch.Tensor,
426 - ) -> torch.Tensor | None:
427 - logits = self.logits_processor(self.lm_head, hidden_states)
428 - return logits
429 -
430 - def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
431 - loader = AutoWeightsLoader(self)
432 - return loader.load_weights(weights, mapper=self.hf_to_vllm_mapper)
vllm/model_executor/models/transformers/base.py
+9 -1
@@ -32,6 +32,7 @@ from torch import nn
32 from transformers import AutoModel, PreTrainedConfig
33 from transformers.conversion_mapping import (
34 WeightRenaming,
35 + get_checkpoint_conversion_mapping,
36 get_model_conversion_mapping,
37 )
38
@@ -311,7 +312,14 @@ class Base(
312 orig_to_new_renaming: list[WeightRenaming] = []
313 orig_to_new_regex: dict[re.Pattern, str | None] = {}
314
314 - for mapping in get_model_conversion_mapping(self.model):
315 + mappings = get_model_conversion_mapping(self.model)
316 + # Ensure layers that are part of the model, but not AutoModel, get their mapping
317 + instantiated = {type(m).__name__ for m in self.model.modules()}
318 + for arch in self.config.architectures or []:
319 + if arch not in instantiated:
320 + mappings.extend(get_checkpoint_conversion_mapping(arch) or [])
321 +
322 + for mapping in mappings:
323 # Handle weights which have been renamed in Transformers
324 if isinstance(mapping, WeightRenaming):
325 orig_to_new_renaming.append(mapping)
vllm/model_executor/models/transformers/causal.py
+7 -3
@@ -19,6 +19,8 @@
19 from collections.abc import Iterable
20 from typing import TYPE_CHECKING
21
22 +import torch
23 +
24 from vllm.model_executor.layers.logits_processor import LogitsProcessor
25 from vllm.model_executor.layers.vocab_parallel_embedding import (
26 ParallelLMHead,
@@ -30,8 +32,6 @@ from vllm.model_executor.models.utils import PPMissingLayer, maybe_prefix
32 from .base import Base
33
34 if TYPE_CHECKING:
33 - import torch
34 -
35 from vllm.config import VllmConfig
36
37
@@ -68,11 +68,15 @@ class CausalMixin(VllmModelForTextGeneration, Base):
68 def load_weights(self, weights: Iterable[tuple[str, "torch.Tensor"]]) -> set[str]:
69 """A thin wrapper around `Base.load_weights` to handle the lm_head bias."""
70 lm_head_bias = set()
71 + load_device = self.vllm_config.load_config.device or self.device_config.device
72
73 def auto_load_lm_head_bias(weights):
74 for name, weight in weights:
75 if name.endswith("lm_head.bias") and self.pp_group.is_last_rank:
75 - self.lm_head._register_bias()
76 + # load_weights is called outside vLLM's device context,
77 + # so we must enter it again when registering the bias.
78 + with torch.device(load_device):
79 + self.lm_head._register_bias()
80 self.lm_head.bias.weight_loader(self.lm_head.bias, weight)
81 lm_head_bias.add(name)
82 else: