nhorlava commited on
Commit
bb3eab5
·
verified ·
1 Parent(s): 3d67087

Upload TinyLlamaV2

Browse files
Files changed (4) hide show
  1. README.md +199 -0
  2. config.json +23 -0
  3. model.safetensors +3 -0
  4. tiny_llama.py +315 -0
README.md ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ tags: []
4
+ ---
5
+
6
+ # Model Card for Model ID
7
+
8
+ <!-- Provide a quick summary of what the model is/does. -->
9
+
10
+
11
+
12
+ ## Model Details
13
+
14
+ ### Model Description
15
+
16
+ <!-- Provide a longer summary of what this model is. -->
17
+
18
+ This is the model card of a 🤗 transformers model that has been pushed on the Hub. This model card has been automatically generated.
19
+
20
+ - **Developed by:** [More Information Needed]
21
+ - **Funded by [optional]:** [More Information Needed]
22
+ - **Shared by [optional]:** [More Information Needed]
23
+ - **Model type:** [More Information Needed]
24
+ - **Language(s) (NLP):** [More Information Needed]
25
+ - **License:** [More Information Needed]
26
+ - **Finetuned from model [optional]:** [More Information Needed]
27
+
28
+ ### Model Sources [optional]
29
+
30
+ <!-- Provide the basic links for the model. -->
31
+
32
+ - **Repository:** [More Information Needed]
33
+ - **Paper [optional]:** [More Information Needed]
34
+ - **Demo [optional]:** [More Information Needed]
35
+
36
+ ## Uses
37
+
38
+ <!-- Address questions around how the model is intended to be used, including the foreseeable users of the model and those affected by the model. -->
39
+
40
+ ### Direct Use
41
+
42
+ <!-- This section is for the model use without fine-tuning or plugging into a larger ecosystem/app. -->
43
+
44
+ [More Information Needed]
45
+
46
+ ### Downstream Use [optional]
47
+
48
+ <!-- This section is for the model use when fine-tuned for a task, or when plugged into a larger ecosystem/app -->
49
+
50
+ [More Information Needed]
51
+
52
+ ### Out-of-Scope Use
53
+
54
+ <!-- This section addresses misuse, malicious use, and uses that the model will not work well for. -->
55
+
56
+ [More Information Needed]
57
+
58
+ ## Bias, Risks, and Limitations
59
+
60
+ <!-- This section is meant to convey both technical and sociotechnical limitations. -->
61
+
62
+ [More Information Needed]
63
+
64
+ ### Recommendations
65
+
66
+ <!-- This section is meant to convey recommendations with respect to the bias, risk, and technical limitations. -->
67
+
68
+ Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.
69
+
70
+ ## How to Get Started with the Model
71
+
72
+ Use the code below to get started with the model.
73
+
74
+ [More Information Needed]
75
+
76
+ ## Training Details
77
+
78
+ ### Training Data
79
+
80
+ <!-- This should link to a Dataset Card, perhaps with a short stub of information on what the training data is all about as well as documentation related to data pre-processing or additional filtering. -->
81
+
82
+ [More Information Needed]
83
+
84
+ ### Training Procedure
85
+
86
+ <!-- This relates heavily to the Technical Specifications. Content here should link to that section when it is relevant to the training procedure. -->
87
+
88
+ #### Preprocessing [optional]
89
+
90
+ [More Information Needed]
91
+
92
+
93
+ #### Training Hyperparameters
94
+
95
+ - **Training regime:** [More Information Needed] <!--fp32, fp16 mixed precision, bf16 mixed precision, bf16 non-mixed precision, fp16 non-mixed precision, fp8 mixed precision -->
96
+
97
+ #### Speeds, Sizes, Times [optional]
98
+
99
+ <!-- This section provides information about throughput, start/end time, checkpoint size if relevant, etc. -->
100
+
101
+ [More Information Needed]
102
+
103
+ ## Evaluation
104
+
105
+ <!-- This section describes the evaluation protocols and provides the results. -->
106
+
107
+ ### Testing Data, Factors & Metrics
108
+
109
+ #### Testing Data
110
+
111
+ <!-- This should link to a Dataset Card if possible. -->
112
+
113
+ [More Information Needed]
114
+
115
+ #### Factors
116
+
117
+ <!-- These are the things the evaluation is disaggregating by, e.g., subpopulations or domains. -->
118
+
119
+ [More Information Needed]
120
+
121
+ #### Metrics
122
+
123
+ <!-- These are the evaluation metrics being used, ideally with a description of why. -->
124
+
125
+ [More Information Needed]
126
+
127
+ ### Results
128
+
129
+ [More Information Needed]
130
+
131
+ #### Summary
132
+
133
+
134
+
135
+ ## Model Examination [optional]
136
+
137
+ <!-- Relevant interpretability work for the model goes here -->
138
+
139
+ [More Information Needed]
140
+
141
+ ## Environmental Impact
142
+
143
+ <!-- Total emissions (in grams of CO2eq) and additional considerations, such as electricity usage, go here. Edit the suggested text below accordingly -->
144
+
145
+ Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700).
146
+
147
+ - **Hardware Type:** [More Information Needed]
148
+ - **Hours used:** [More Information Needed]
149
+ - **Cloud Provider:** [More Information Needed]
150
+ - **Compute Region:** [More Information Needed]
151
+ - **Carbon Emitted:** [More Information Needed]
152
+
153
+ ## Technical Specifications [optional]
154
+
155
+ ### Model Architecture and Objective
156
+
157
+ [More Information Needed]
158
+
159
+ ### Compute Infrastructure
160
+
161
+ [More Information Needed]
162
+
163
+ #### Hardware
164
+
165
+ [More Information Needed]
166
+
167
+ #### Software
168
+
169
+ [More Information Needed]
170
+
171
+ ## Citation [optional]
172
+
173
+ <!-- If there is a paper or blog post introducing the model, the APA and Bibtex information for that should go in this section. -->
174
+
175
+ **BibTeX:**
176
+
177
+ [More Information Needed]
178
+
179
+ **APA:**
180
+
181
+ [More Information Needed]
182
+
183
+ ## Glossary [optional]
184
+
185
+ <!-- If relevant, include terms and calculations in this section that can help readers understand the model or model card. -->
186
+
187
+ [More Information Needed]
188
+
189
+ ## More Information [optional]
190
+
191
+ [More Information Needed]
192
+
193
+ ## Model Card Authors [optional]
194
+
195
+ [More Information Needed]
196
+
197
+ ## Model Card Contact
198
+
199
+ [More Information Needed]
config.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "TinyLlamaV2"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "tiny_llama.TinyLlamaConfig",
7
+ "AutoModel": "tiny_llama.TinyLlamaV2"
8
+ },
9
+ "dropout": 0.1,
10
+ "dtype": "float32",
11
+ "hidden_dim": 768,
12
+ "intermediate_dim": 3072,
13
+ "max_seq_len": 1024,
14
+ "model_type": "tiny_llama_v2",
15
+ "n_heads": 12,
16
+ "n_kv_heads": 4,
17
+ "n_layers": 12,
18
+ "norm_eps": 1e-06,
19
+ "rope_theta": 10000.0,
20
+ "tie_word_embeddings": true,
21
+ "transformers_version": "5.17.0",
22
+ "vocab_size": 50257
23
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4f0b9f8aa1df246c8f50bdeab7e59e5a35c7e5db89dc1a9aba6291a573409000
3
+ size 569710104
tiny_llama.py ADDED
@@ -0,0 +1,315 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """TinyTransformer v2 as a Transformers custom model, servable by vLLM's Transformers modeling backend.
2
+
3
+ A copy of `MLExamples/TinyTransformer/version2_pytorch_fused/tiny_llama_v2.py`'s model from the https://github.com/amd/HPCTrainingExamples — except where v2's code
4
+ can't work when served. Every such change is marked `# SERVING CHANGE N:` below; there are three:
5
+ 1. Attention goes through `ALL_ATTENTION_FUNCTIONS` (keyed by `layer_idx`) instead of calling SDPA
6
+ directly, so vLLM can plug in its own attention kernel and KV cache —
7
+ https://docs.vllm.ai/en/latest/models/supported_models/#writing-custom-models. GQA's K/V head
8
+ repeat moves into that interface too (transformers' `repeat_kv` gives the same head order as
9
+ v2's `repeat_interleave`): vLLM sizes its KV cache by `n_kv_heads`.
10
+ 2. RoPE angles come from explicit `position_ids` instead of `start_pos + arange(seq_len)`, which
11
+ assumes every call starts at position `start_pos` — wrong for vLLM's decoding steps and packed
12
+ batches. vLLM may also hand in precomputed `inputs_embeds` instead of `input_ids`.
13
+ 3. transformers plumbing, so transformers/vLLM can load it: `PretrainedConfig`/`PreTrainedModel`
14
+ base classes, and `TinyLlamaV2.forward` stops after the final norm and returns the hidden
15
+ states. vLLM builds this class via `auto_map.AutoModel` and puts its own lm_head on top, tied to
16
+ `get_input_embeddings()` (`tie_word_embeddings`) — which is exactly v2's `output_proj`, itself
17
+ tied to `token_embedding`.
18
+
19
+ Also left out, without affecting outputs:
20
+ - `record_function` profiler ranges and dropout (inactive at inference).
21
+ - The unfused Q/K/V and gate/up projection branches, and the manual-attention/explicit-mask branch:
22
+ the workshop checkpoint uses the fused layout and the SDPA path (`convert_and_push.py` refuses
23
+ any other checkpoint), so `FusionConfig` is gone too.
24
+ - `output_proj` and the loss (see 3), `get_fusion_statistics`, and `_init_weights`: random
25
+ initialization, which loading the checkpoint overwrites.
26
+ """
27
+
28
+ from typing import ClassVar
29
+
30
+ import torch
31
+ import torch.nn.functional as F
32
+ from torch import nn
33
+ from transformers import PretrainedConfig, PreTrainedModel
34
+ from transformers.integrations.sdpa_attention import sdpa_attention_forward
35
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
36
+
37
+
38
+ class TinyLlamaConfig(PretrainedConfig):
39
+ """v2's TinyLlamaConfig: same name, fields and defaults. SERVING CHANGE 3: a PretrainedConfig
40
+ subclass instead of a dataclass, so transformers/vLLM can read it from config.json."""
41
+
42
+ model_type = "tiny_llama_v2"
43
+ # SERVING CHANGE 3: transformers/vLLM read the standard names; alias them to v2's fields.
44
+ attribute_map: ClassVar[dict[str, str]] = {
45
+ "hidden_size": "hidden_dim",
46
+ "num_hidden_layers": "n_layers",
47
+ "num_attention_heads": "n_heads",
48
+ "num_key_value_heads": "n_kv_heads",
49
+ "intermediate_size": "intermediate_dim",
50
+ "rms_norm_eps": "norm_eps",
51
+ "max_position_embeddings": "max_seq_len",
52
+ }
53
+
54
+ def __init__(
55
+ self,
56
+ vocab_size: int = 1000,
57
+ hidden_dim: int = 256,
58
+ n_layers: int = 4,
59
+ n_heads: int = 8,
60
+ n_kv_heads: int = 4,
61
+ intermediate_dim: int = 512,
62
+ max_seq_len: int = 128,
63
+ rope_theta: float = 10000.0,
64
+ norm_eps: float = 1e-6,
65
+ dropout: float = 0.0,
66
+ **kwargs,
67
+ ):
68
+ self.vocab_size = vocab_size
69
+ self.hidden_dim = hidden_dim
70
+ self.n_layers = n_layers
71
+ self.n_heads = n_heads
72
+ self.n_kv_heads = n_kv_heads
73
+ self.intermediate_dim = intermediate_dim
74
+ self.max_seq_len = max_seq_len
75
+ self.rope_theta = rope_theta
76
+ self.norm_eps = norm_eps
77
+ self.dropout = (
78
+ dropout # kept for fidelity with v2's config; unused at inference
79
+ )
80
+ # v2 always ties output_proj to token_embedding; vLLM reads this flag to tie its lm_head.
81
+ kwargs["tie_word_embeddings"] = True
82
+ super().__init__(**kwargs)
83
+
84
+
85
+ class RMSNorm(nn.Module):
86
+ """Root Mean Square Layer Normalization - optimized for fusion."""
87
+
88
+ def __init__(self, dim: int, eps: float = 1e-6):
89
+ super().__init__()
90
+ self.eps = eps
91
+ self.weight = nn.Parameter(torch.ones(dim))
92
+
93
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
94
+ rms = torch.sqrt(torch.mean(x * x, dim=-1, keepdim=True) + self.eps)
95
+ x = x / rms
96
+ return x * self.weight
97
+
98
+
99
+ class RotaryPositionEmbedding(nn.Module):
100
+ """Rotary Position Embeddings, v2's interleaved-pair formula.
101
+
102
+ SERVING CHANGE 2: angles are computed for the given `position_ids` rather than cached for
103
+ `start_pos .. start_pos + seq_len`. v2 builds positions and frequencies in the activations'
104
+ dtype (float32 for this checkpoint); so does this.
105
+ """
106
+
107
+ def __init__(self, dim: int, theta: float = 10000.0):
108
+ super().__init__()
109
+ self.dim = dim
110
+ self.theta = theta
111
+
112
+ def cos_sin(self, position_ids: torch.Tensor, dtype: torch.dtype):
113
+ # position_ids: [batch, seq_len] -> cos/sin: [batch, seq_len, 1, dim // 2]
114
+ t = position_ids.to(dtype)
115
+ inv_freq = 1.0 / (
116
+ self.theta
117
+ ** (torch.arange(0, self.dim, 2, device=t.device, dtype=dtype) / self.dim)
118
+ )
119
+ freqs = t[..., None] * inv_freq
120
+ return torch.cos(freqs).to(dtype).unsqueeze(2), torch.sin(freqs).to(
121
+ dtype
122
+ ).unsqueeze(2)
123
+
124
+ @staticmethod
125
+ def apply_rotary_embedding(
126
+ q: torch.Tensor, k: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor
127
+ ):
128
+ batch_size, seq_len, n_heads_q, head_dim = q.shape
129
+ _, _, n_heads_k, _ = k.shape
130
+
131
+ # Reshape for rotary embedding
132
+ q = q.reshape(batch_size, seq_len, n_heads_q, head_dim // 2, 2)
133
+ k = k.reshape(batch_size, seq_len, n_heads_k, head_dim // 2, 2)
134
+
135
+ q_rot = torch.stack(
136
+ [q[..., 0] * cos - q[..., 1] * sin, q[..., 0] * sin + q[..., 1] * cos],
137
+ dim=-1,
138
+ )
139
+
140
+ k_rot = torch.stack(
141
+ [k[..., 0] * cos - k[..., 1] * sin, k[..., 0] * sin + k[..., 1] * cos],
142
+ dim=-1,
143
+ )
144
+
145
+ # Reshape back
146
+ q_rot = q_rot.reshape(batch_size, seq_len, n_heads_q, head_dim)
147
+ k_rot = k_rot.reshape(batch_size, seq_len, n_heads_k, head_dim)
148
+
149
+ return q_rot, k_rot
150
+
151
+
152
+ class FusedAttention(nn.Module):
153
+ """Optimized attention with QKV fusion."""
154
+
155
+ def __init__(self, config: TinyLlamaConfig, layer_idx: int):
156
+ super().__init__()
157
+ self.n_heads = config.n_heads
158
+ self.n_kv_heads = config.n_kv_heads
159
+ self.head_dim = config.hidden_dim // config.n_heads
160
+ self.scale = self.head_dim**-0.5
161
+ # SERVING CHANGE 1: what the attention interface reads off the module.
162
+ self.config = config
163
+ self.layer_idx = layer_idx
164
+ self.num_key_value_groups = self.n_heads // self.n_kv_heads
165
+ self.is_causal = True
166
+
167
+ # Fused QKV projection - 3 operations combined into 1
168
+ self.qkv_proj = nn.Linear(
169
+ config.hidden_dim,
170
+ (config.n_heads + 2 * config.n_kv_heads) * self.head_dim,
171
+ bias=False,
172
+ )
173
+ self.o_proj = nn.Linear(
174
+ config.n_heads * self.head_dim, config.hidden_dim, bias=False
175
+ )
176
+
177
+ def forward(
178
+ self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor
179
+ ) -> torch.Tensor:
180
+ batch_size, seq_len, _ = x.shape
181
+
182
+ # Fused QKV projection, split into Q, K, V
183
+ qkv = self.qkv_proj(x)
184
+ q_size = self.n_heads * self.head_dim
185
+ kv_size = self.n_kv_heads * self.head_dim
186
+
187
+ q = qkv[:, :, :q_size].view(batch_size, seq_len, self.n_heads, self.head_dim)
188
+ k = qkv[:, :, q_size : q_size + kv_size].view(
189
+ batch_size, seq_len, self.n_kv_heads, self.head_dim
190
+ )
191
+ v = qkv[:, :, q_size + kv_size :].view(
192
+ batch_size, seq_len, self.n_kv_heads, self.head_dim
193
+ )
194
+
195
+ # Apply rotary position embeddings
196
+ q, k = RotaryPositionEmbedding.apply_rotary_embedding(q, k, cos, sin)
197
+
198
+ # Transpose for attention computation
199
+ q = q.transpose(1, 2) # (batch, n_heads, seq_len, head_dim)
200
+ k = k.transpose(1, 2)
201
+ v = v.transpose(1, 2)
202
+
203
+ # SERVING CHANGE 1: v2 repeats the K/V heads here and calls
204
+ # F.scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, is_causal=True)
205
+ # directly. transformers' "sdpa" interface is that same call, GQA repeat included, and lets
206
+ # vLLM swap in its own kernel and KV cache. It returns [batch, seq_len, n_heads, head_dim],
207
+ # already transposed back.
208
+ attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(
209
+ self.config._attn_implementation, sdpa_attention_forward
210
+ )
211
+ attn_output, _ = attention_interface(
212
+ self, q, k, v, None, dropout=0.0, scaling=self.scale
213
+ )
214
+
215
+ attn_output = attn_output.contiguous().view(batch_size, seq_len, -1)
216
+ return self.o_proj(attn_output)
217
+
218
+
219
+ class FusedSwiGLU(nn.Module):
220
+ """Optimized SwiGLU with fused gate/up projections."""
221
+
222
+ def __init__(self, config: TinyLlamaConfig):
223
+ super().__init__()
224
+ # Fused gate and up projection - 2 operations combined into 1
225
+ self.gate_up_proj = nn.Linear(
226
+ config.hidden_dim, 2 * config.intermediate_dim, bias=False
227
+ )
228
+ self.down_proj = nn.Linear(
229
+ config.intermediate_dim, config.hidden_dim, bias=False
230
+ )
231
+
232
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
233
+ gate_up = self.gate_up_proj(x)
234
+ gate, up = gate_up.chunk(2, dim=-1)
235
+ intermediate = F.silu(gate) * up
236
+ return self.down_proj(intermediate)
237
+
238
+
239
+ class FusedTransformerBlock(nn.Module):
240
+ """Optimized transformer block with fusion capabilities."""
241
+
242
+ def __init__(self, config: TinyLlamaConfig, layer_idx: int):
243
+ super().__init__()
244
+ self.attention = FusedAttention(config, layer_idx)
245
+ self.feed_forward = FusedSwiGLU(config)
246
+ self.norm1 = RMSNorm(config.hidden_dim, config.norm_eps)
247
+ self.norm2 = RMSNorm(config.hidden_dim, config.norm_eps)
248
+
249
+ def forward(
250
+ self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor
251
+ ) -> torch.Tensor:
252
+ # Pre-norm attention with residual connection
253
+ x = x + self.attention(self.norm1(x), cos, sin)
254
+ # Pre-norm feed-forward with residual connection
255
+ x = x + self.feed_forward(self.norm2(x))
256
+ return x
257
+
258
+
259
+ class TinyLlamaV2(PreTrainedModel):
260
+ """Tiny LLaMA V2 with comprehensive fusion optimizations.
261
+
262
+ SERVING CHANGE 3: a PreTrainedModel ending at the final norm (see module docstring).
263
+ """
264
+
265
+ config_class = TinyLlamaConfig
266
+ _supports_sdpa = True
267
+ # vLLM's Transformers backend requires this (or source it can inspect) to use its attention.
268
+ _supports_attention_backend = True
269
+
270
+ def __init__(self, config: TinyLlamaConfig):
271
+ super().__init__(config)
272
+
273
+ # Token embeddings
274
+ self.token_embedding = nn.Embedding(config.vocab_size, config.hidden_dim)
275
+
276
+ # Transformer blocks with fusion
277
+ self.blocks = nn.ModuleList(
278
+ [
279
+ FusedTransformerBlock(config, layer_idx)
280
+ for layer_idx in range(config.n_layers)
281
+ ]
282
+ )
283
+
284
+ # Final norm
285
+ self.norm = RMSNorm(config.hidden_dim, config.norm_eps)
286
+
287
+ self.rope = RotaryPositionEmbedding(
288
+ config.hidden_dim // config.n_heads, config.rope_theta
289
+ )
290
+
291
+ self.post_init()
292
+
293
+ def get_input_embeddings(self):
294
+ return self.token_embedding
295
+
296
+ def forward(
297
+ self,
298
+ input_ids: torch.Tensor | None = None,
299
+ position_ids: torch.Tensor | None = None,
300
+ inputs_embeds: torch.Tensor | None = None,
301
+ **kwargs,
302
+ ):
303
+ # SERVING CHANGE 2: vLLM may pass embeddings, and always passes positions; default to v2's
304
+ # 0..seq_len-1. vLLM also passes use_cache/return_dict etc., unused here (**kwargs).
305
+ x = self.token_embedding(input_ids) if inputs_embeds is None else inputs_embeds
306
+ if position_ids is None:
307
+ position_ids = torch.arange(x.shape[1], device=x.device).unsqueeze(0)
308
+ cos, sin = self.rope.cos_sin(position_ids, x.dtype)
309
+
310
+ for block in self.blocks:
311
+ x = block(x, cos, sin)
312
+
313
+ # SERVING CHANGE 3: stop at the final norm; vLLM applies its tied lm_head. A tuple — vLLM
314
+ # reads the hidden states as outputs[0].
315
+ return (self.norm(x),)