mg-kog commited on
Commit
027051d
·
verified ·
1 Parent(s): 2a589a0

Copy Laneformer repo with BF16 weights

Browse files
.eval_results/humaneval.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ - dataset:
2
+ id: openai/openai_humaneval
3
+ task_id: default
4
+ value: 53.05
5
+ date: "2026-06-11"
6
+ - dataset:
7
+ id: evalplus/humanevalplus
8
+ task_id: default
9
+ value: 50.00
10
+ date: "2026-06-11"
LICENSE ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Kog LaneformerTP Repository License Notice
2
+ =========================================
3
+
4
+ This repository contains materials under different licenses.
5
+
6
+ 1. Kog-owned materials
7
+ ----------------------
8
+ Unless a file states otherwise, the model weights, Hugging Face custom modeling and configuration code, model configuration files, metadata files, documentation, and README/model card are licensed under the Apache License, Version 2.0 below.
9
+
10
+ Apache License
11
+ Version 2.0, January 2004
12
+ http://www.apache.org/licenses/
13
+
14
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
15
+
16
+ 1. Definitions.
17
+
18
+ "License" shall mean the terms and conditions for use, reproduction,
19
+ and distribution as defined by Sections 1 through 9 of this document.
20
+
21
+ "Licensor" shall mean the copyright owner or entity authorized by
22
+ the copyright owner that is granting the License.
23
+
24
+ "Legal Entity" shall mean the union of the acting entity and all
25
+ other entities that control, are controlled by, or are under common
26
+ control with that entity. For the purposes of this definition,
27
+ "control" means (i) the power, direct or indirect, to cause the
28
+ direction or management of such entity, whether by contract or
29
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
30
+ outstanding shares, or (iii) beneficial ownership of such entity.
31
+
32
+ "You" (or "Your") shall mean an individual or Legal Entity
33
+ exercising permissions granted by this License.
34
+
35
+ "Source" form shall mean the preferred form for making modifications,
36
+ including but not limited to software source code, documentation
37
+ source, and configuration files.
38
+
39
+ "Object" form shall mean any form resulting from mechanical
40
+ transformation or translation of a Source form, including but
41
+ not limited to compiled object code, generated documentation,
42
+ and conversions to other media types.
43
+
44
+ "Work" shall mean the work of authorship, whether in Source or
45
+ Object form, made available under the License, as indicated by a
46
+ copyright notice that is included in or attached to the work
47
+ (an example is provided in the Appendix below).
48
+
49
+ "Derivative Works" shall mean any work, whether in Source or Object
50
+ form, that is based on (or derived from) the Work and for which the
51
+ editorial revisions, annotations, elaborations, or other modifications
52
+ represent, as a whole, an original work of authorship. For the purposes
53
+ of this License, Derivative Works shall not include works that remain
54
+ separable from, or merely link (or bind by name) to the interfaces of,
55
+ the Work and Derivative Works thereof.
56
+
57
+ "Contribution" shall mean any work of authorship, including
58
+ the original version of the Work and any modifications or additions
59
+ to that Work or Derivative Works thereof, that is intentionally
60
+ submitted to Licensor for inclusion in the Work by the copyright owner
61
+ or by an individual or Legal Entity authorized to submit on behalf of
62
+ the copyright owner. For the purposes of this definition, "submitted"
63
+ means any form of electronic, verbal, or written communication sent
64
+ to the Licensor or its representatives, including but not limited to
65
+ communication on electronic mailing lists, source code control systems,
66
+ and issue tracking systems that are managed by, or on behalf of, the
67
+ Licensor for the purpose of discussing and improving the Work, but
68
+ excluding communication that is conspicuously marked or otherwise
69
+ designated in writing by the copyright owner as "Not a Contribution."
70
+
71
+ "Contributor" shall mean Licensor and any individual or Legal Entity
72
+ on behalf of whom a Contribution has been received by Licensor and
73
+ subsequently incorporated within the Work.
74
+
75
+ 2. Grant of Copyright License. Subject to the terms and conditions of
76
+ this License, each Contributor hereby grants to You a perpetual,
77
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
78
+ copyright license to reproduce, prepare Derivative Works of,
79
+ publicly display, publicly perform, sublicense, and distribute the
80
+ Work and such Derivative Works in Source or Object form.
81
+
82
+ 3. Grant of Patent License. Subject to the terms and conditions of
83
+ this License, each Contributor hereby grants to You a perpetual,
84
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
85
+ (except as stated in this section) patent license to make, have made,
86
+ use, offer to sell, sell, import, and otherwise transfer the Work,
87
+ where such license applies only to those patent claims licensable
88
+ by such Contributor that are necessarily infringed by their
89
+ Contribution(s) alone or by combination of their Contribution(s)
90
+ with the Work to which such Contribution(s) was submitted. If You
91
+ institute patent litigation against any entity (including a
92
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
93
+ or a Contribution incorporated within the Work constitutes direct
94
+ or contributory patent infringement, then any patent licenses
95
+ granted to You under this License for that Work shall terminate
96
+ as of the date such litigation is filed.
97
+
98
+ 4. Redistribution. You may reproduce and distribute copies of the
99
+ Work or Derivative Works thereof in any medium, with or without
100
+ modifications, and in Source or Object form, provided that You
101
+ meet the following conditions:
102
+
103
+ (a) You must give any other recipients of the Work or
104
+ Derivative Works a copy of this License; and
105
+
106
+ (b) You must cause any modified files to carry prominent notices
107
+ stating that You changed the files; and
108
+
109
+ (c) You must retain, in the Source form of any Derivative Works
110
+ that You distribute, all copyright, patent, trademark, and
111
+ attribution notices from the Source form of the Work,
112
+ excluding those notices that do not pertain to any part of
113
+ the Derivative Works; and
114
+
115
+ (d) If the Work includes a "NOTICE" text file as part of its
116
+ distribution, then any Derivative Works that You distribute must
117
+ include a readable copy of the attribution notices contained
118
+ within such NOTICE file, excluding those notices that do not
119
+ pertain to any part of the Derivative Works, in at least one
120
+ of the following places: within a NOTICE text file distributed
121
+ as part of the Derivative Works; within the Source form or
122
+ documentation, if provided along with the Derivative Works; or,
123
+ within a display generated by the Derivative Works, if and
124
+ wherever such third-party notices normally appear. The contents
125
+ of the NOTICE file are for informational purposes only and
126
+ do not modify the License. You may add Your own attribution
127
+ notices within Derivative Works that You distribute, alongside
128
+ or as an addendum to the NOTICE text from the Work, provided
129
+ that such additional attribution notices cannot be construed
130
+ as modifying the License.
131
+
132
+ You may add Your own copyright statement to Your modifications and
133
+ may provide additional or different license terms and conditions
134
+ for use, reproduction, or distribution of Your modifications, or
135
+ for any such Derivative Works as a whole, provided Your use,
136
+ reproduction, and distribution of the Work otherwise complies with
137
+ the conditions stated in this License.
138
+
139
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
140
+ any Contribution intentionally submitted for inclusion in the Work
141
+ by You to the Licensor shall be under the terms and conditions of
142
+ this License, without any additional terms or conditions.
143
+ Notwithstanding the above, nothing herein shall supersede or modify
144
+ the terms of any separate license agreement you may have executed
145
+ with Licensor regarding such Contributions.
146
+
147
+ 6. Trademarks. This License does not grant permission to use the trade
148
+ names, trademarks, service marks, or product names of the Licensor,
149
+ except as required for reasonable and customary use in describing the
150
+ origin of the Work and reproducing the content of the NOTICE file.
151
+
152
+ 7. Disclaimer of Warranty. Unless required by applicable law or
153
+ agreed to in writing, Licensor provides the Work (and each
154
+ Contributor provides its Contributions) on an "AS IS" BASIS,
155
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
156
+ implied, including, without limitation, any warranties or conditions
157
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
158
+ PARTICULAR PURPOSE. You are solely responsible for determining the
159
+ appropriateness of using or redistributing the Work and assume any
160
+ risks associated with Your exercise of permissions under this License.
161
+
162
+ 8. Limitation of Liability. In no event and under no legal theory,
163
+ whether in tort (including negligence), contract, or otherwise,
164
+ unless required by applicable law (such as deliberate and grossly
165
+ negligent acts) or agreed to in writing, shall any Contributor be
166
+ liable to You for damages, including any direct, indirect, special,
167
+ incidental, or consequential damages of any character arising as a
168
+ result of this License or out of the use or inability to use the
169
+ Work (including but not limited to damages for loss of goodwill,
170
+ work stoppage, computer failure or malfunction, or any and all
171
+ other commercial damages or losses), even if such Contributor
172
+ has been advised of the possibility of such damages.
173
+
174
+ 9. Accepting Warranty or Additional Liability. While redistributing
175
+ the Work or Derivative Works thereof, You may choose to offer,
176
+ and charge a fee for, acceptance of support, warranty, indemnity,
177
+ or other liability obligations and/or rights consistent with this
178
+ License. However, in accepting such obligations, You may act only
179
+ on Your own behalf and on Your sole responsibility, not on behalf
180
+ of any other Contributor, and only if You agree to indemnify,
181
+ defend, and hold each Contributor harmless for any liability
182
+ incurred by, or claims asserted against, such Contributor by reason
183
+ of your accepting any such warranty or additional liability.
184
+
185
+ END OF TERMS AND CONDITIONS
186
+
187
+ APPENDIX: How to apply the Apache License to your work.
188
+
189
+ To apply the Apache License to your work, attach the following
190
+ boilerplate notice, with the fields enclosed by brackets "[]"
191
+ replaced with your own identifying information. (Do not include
192
+ the brackets!) The text should be enclosed in the appropriate
193
+ comment syntax for the file format. We also recommend that a
194
+ file or class name and description of purpose be included on the
195
+ same "printed page" as the copyright notice for easier
196
+ identification within third-party archives.
197
+
198
+ Copyright 2026 Kog AI
199
+
200
+ Licensed under the Apache License, Version 2.0 (the "License");
201
+ you may not use this file except in compliance with the License.
202
+ You may obtain a copy of the License at
203
+
204
+ http://www.apache.org/licenses/LICENSE-2.0
205
+
206
+ Unless required by applicable law or agreed to in writing, software
207
+ distributed under the License is distributed on an "AS IS" BASIS,
208
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
209
+ See the License for the specific language governing permissions and
210
+ limitations under the License.
211
+
212
+ 2. Third-party tokenizer materials
213
+ ----------------------------------
214
+ The tokenizer files in this repository are based on the Llama 2 tokenizer and are not licensed under the Apache License, Version 2.0 above. These tokenizer materials include, without limitation, tokenizer.model, tokenizer.json, tokenizer_config.json, special_tokens_map.json, and any other file whose purpose is to reproduce or configure the Llama 2 tokenizer.
215
+
216
+ The Llama 2 tokenizer materials are distributed under the LLAMA 2 Community License Agreement. See THIRD_PARTY_LICENSES/LLAMA2_LICENSE for the full license text.
217
+
218
+ Required attribution notice for Llama 2 materials:
219
+
220
+ "Llama 2 is licensed under the LLAMA 2 Community License, Copyright (c) Meta Platforms, Inc. All Rights Reserved."
221
+
222
+ Users and redistributors are responsible for complying with the LLAMA 2 Community License Agreement, including the Acceptable Use Policy referenced by that agreement.
NOTICE ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Llama 2 tokenizer notice
2
+
3
+ This repository includes tokenizer artifacts based on the Llama 2 tokenizer.
4
+
5
+ Llama 2 is licensed under the LLAMA 2 Community License,
6
+ Copyright (c) Meta Platforms, Inc. All Rights Reserved.
7
+
8
+ The Llama 2 tokenizer materials are distributed under the LLAMA 2 Community License Agreement.
9
+ See THIRD_PARTY_LICENSES/LLAMA2_LICENSE for the full license text and consult Meta's Llama 2 Acceptable Use Policy referenced by that license.
10
+
11
+ All Kog-owned model weights, Hugging Face custom modeling/configuration code, documentation, and configuration files are licensed separately under the Apache License, Version 2.0 unless a file states otherwise.
README.md ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: transformers
3
+ pipeline_tag: text-generation
4
+ license: other
5
+ license_name: kog-apache-2.0-plus-llama2-tokenizer
6
+ license_link: https://huggingface.co/kogai/laneformer-2b-it/blob/main/LICENSE
7
+ # The repository is multi-license: Kog-owned model/code/docs are Apache-2.0;
8
+ # tokenizer artifacts based on the Llama 2 tokenizer are under the Llama 2 Community License.
9
+ tags:
10
+ - pytorch
11
+ - causal-lm
12
+ - text-generation
13
+ - laneformer
14
+ - delayed-tensor-parallelism
15
+ - dtp
16
+ language:
17
+ - en
18
+ datasets:
19
+ - nvidia/Nemotron-Pretraining-Dataset-sample
20
+ - nvidia/Nemotron-Pretraining-Legal-v1
21
+ - nvidia/Nemotron-Pretraining-Specialized-v1.2
22
+ - nvidia/Nemotron-Pretraining-Code-v3
23
+ - nvidia/Nemotron-Pretraining-Specialized-v1.1
24
+ - nvidia/Nemotron-CC-Code-v1
25
+ - nvidia/Nemotron-CC-v2.1
26
+ - nvidia/Nemotron-Pretraining-Code-v2
27
+ - nvidia/Nemotron-Pretraining-Specialized-v1
28
+ - nvidia/Nemotron-CC-Math-v1
29
+ - nvidia/Nemotron-CC-v2
30
+ - nvidia/Nemotron-Pretraining-SFT-v1
31
+ - nvidia/Nemotron-Pretraining-Code-v1
32
+ model_type: laneformer_tp
33
+ parameters: 2B
34
+ widget:
35
+ - text: "Explain the A* algorithm in details, then write a full Python implementation from scratch."
36
+ - text: "Explain the Union-Find / Disjoint Set data structure in detail, then write a complete implementation with path compression and union by rank."
37
+ - text: "Explain how an LRU cache works, then write a full implementation in Python without using built-in cache libraries"
38
+ - text: "Explain how a Trie works, then write a complete implementation supporting insert, search, and prefix queries."
39
+ - text: "Explain topological sorting in detail, then write a full implementation using both DFS and Kahn's algorithm."
40
+ - text: "Explain how a binary heap works, then write a complete min-heap implementation from scratch in Python."
41
+ - text: "Explain Dijkstra's algorithm in detail, then write a full Python implementation from scratch."
42
+ ---
43
+
44
+ # Kog Laneformer 2B
45
+
46
+ Kog Laneformer 2B is a 2B-class decoder-only causal language model built around **Laneformer** and **Delayed Tensor Parallelism (DTP)**, a latency-oriented Transformer variant designed to overlap tensor-parallel communication with useful computation and weight streaming.
47
+
48
+ The model is intended to make our Laneformer architecture available in the Hugging Face ecosystem for research, inspection, fine-tuning experiments, and compatibility testing. It is also the architecture family used in our public inference-engine preview, where single-request decoding speeds is **3,000 output tokens/s/request on 8x AMD MI300X** and **2,100 output tokens/s/request on 8x NVIDIA H200** in FP16 without speculative decoding.
49
+
50
+ Those numbers are **Kog Inference Engine (KIE) benchmark results**, not expected performance from the generic Transformers reference path.
51
+
52
+ For background, see:
53
+
54
+ - [Real-time LLM Inference on Standard Datacenter GPUs (3,000 tokens/s per request)](https://blog.kog.ai/real-time-llm-inference-on-standard-gpus-3-000-tokens-s-per-request/)
55
+ - [Delayed Tensor Parallelism for Faster Transformer Inference](https://blog.kog.ai/delayed-tensor-parallelism-for-faster-transformer-inference/)
56
+
57
+ > **Custom code notice:** this model architecture is not currently part of upstream Transformers. Loading with `AutoConfig`, `AutoModel`, or `AutoModelForCausalLM` requires `trust_remote_code=True`. For production or security-sensitive use, review the modeling code and pin a specific Hub commit hash with `revision="<commit-hash>"`.
58
+
59
+ ## Why this model exists
60
+
61
+ Many LLM serving systems optimize aggregate throughput across many concurrent requests. Our Laneformer DTP work targets a different regime: **low-batch, single-request decode speed**, which is important for agentic coding loops, real-time copilots, voice assistants, and other sequential workflows where each generated step gates the next one.
62
+
63
+ At batch size 1, autoregressive decoding is often constrained by memory bandwidth, synchronization, kernel launch overheads, and communication latency rather than raw FLOPs. Laneformer uses a lane-structured architecture and delayed communication pattern so tensor-parallel work can be organized around the latency structure of full-node GPU inference.
64
+
65
+ ## Model details
66
+
67
+ | Field | Value |
68
+ |---|---:|
69
+ | Model family | Laneformer |
70
+ | HF model type | `laneformer_tp` |
71
+ | Architecture class | `LaneformerTPForCausalLM` |
72
+ | Task | Decoder-only causal language modeling |
73
+ | Parameters | ~2.3B |
74
+ | Hidden size | 3072 |
75
+ | Layers | 15 |
76
+ | Attention heads | 32 |
77
+ | KV heads | 16 |
78
+ | Intermediate size | 12288 |
79
+ | Context length | 4096 tokens |
80
+ | Vocabulary size | 32000 |
81
+ | Tokenizer | Llama 2 tokenizer |
82
+ | Number of lanes | 8 |
83
+ | Broadcast delay | 2 |
84
+ | LM head type | `vocab_parallel` |
85
+ | Sliding window | 2048 tokens |
86
+ | Sliding-window layers | 0-9 |
87
+ | Full-attention layers | 10-14 |
88
+ | RoPE theta | 10000 |
89
+ | Tied word embeddings | false |
90
+ | Expected Transformers version | `>=4.57.1` |
91
+ | Published weight dtype | BFloat16 |
92
+
93
+ ## Architecture overview
94
+
95
+ Laneformer follows a Llama-style decoder-only architecture, but restructures tensor-parallel communication around **lanes**. In standard tensor parallelism, each attention or MLP module typically requires communication before downstream computation can proceed. In Delayed Tensor Parallelism, local outputs are communicated asynchronously and consumed several modules later, allowing communication latency to be hidden behind subsequent computation and weight streaming.
96
+
97
+ This release candidate uses:
98
+
99
+ - 8 lanes.
100
+ - Broadcast delay of 2.
101
+ - Grouped-query attention with 32 query heads and 16 KV heads.
102
+ - RoPE positional embeddings.
103
+ - 10 sliding-window attention layers followed by 5 full-attention layers.
104
+ - A vocab-parallel language-modeling head.
105
+ - Llama 2 tokenizer vocabulary and special-token convention.
106
+
107
+ The Hugging Face implementation is a reference/compatibility implementation. It is useful for loading, generation, inspection, and downstream experimentation, but it is not the same execution path as our production inference engine, which uses a latency-optimized runtime and low-level GPU kernels optimization.
108
+
109
+ ## Installation
110
+
111
+ ### Nvidia
112
+
113
+ ```bash
114
+ uv venv --python 3.12
115
+ source .venv/bin/activate
116
+ uv pip install torch --index-url https://download.pytorch.org/whl/cu130
117
+ uv pip install "transformers>=4.57.1" accelerate safetensors sentencepiece protobuf
118
+ ```
119
+
120
+ ### AMD
121
+
122
+ ```bash
123
+ uv venv --python 3.12
124
+ source .venv/bin/activate
125
+ uv pip install torch --index-url https://download.pytorch.org/whl/rocm7.2
126
+ uv pip install "transformers>=4.57.1" accelerate safetensors sentencepiece protobuf
127
+ ```
128
+
129
+ ## Usage
130
+
131
+ ```python
132
+ import torch
133
+ from transformers import AutoModelForCausalLM, AutoTokenizer, set_seed
134
+
135
+ model_id = "kogai/laneformer-2b-it"
136
+ revision = "main"
137
+ seed = 42
138
+ temperature = 0.8
139
+
140
+ set_seed(seed)
141
+ print(f"Using random seed {seed}.")
142
+
143
+ print(f"Loading tokenizer for {model_id} ({revision=})...")
144
+ tokenizer = AutoTokenizer.from_pretrained(
145
+ model_id,
146
+ trust_remote_code=True,
147
+ revision=revision,
148
+ )
149
+ print("Tokenizer loaded.")
150
+
151
+ print("Loading model. This may take a few minutes on first run while files download...")
152
+ model = AutoModelForCausalLM.from_pretrained(
153
+ model_id,
154
+ trust_remote_code=True,
155
+ revision=revision,
156
+ dtype="bfloat16",
157
+ device_map="auto",
158
+ )
159
+ print(f"Model loaded on {model.device}.")
160
+
161
+ # The Llama 2 tokenizer has no native pad token. If this repo sets PAD to EOS,
162
+ # always pass attention_mask for batched generation.
163
+ if tokenizer.pad_token is None:
164
+ tokenizer.pad_token = tokenizer.eos_token
165
+ print("Tokenizer had no pad token; using EOS as the pad token.")
166
+
167
+ prompts = [
168
+ "Explain how a binary heap works, then write a complete min-heap implementation from scratch in Python.",
169
+ ]
170
+
171
+ print("\nPrompt:")
172
+ print(prompts[0])
173
+ print("\nTokenizing prompt...")
174
+ inputs = tokenizer(
175
+ prompts,
176
+ return_tensors="pt",
177
+ padding=True,
178
+ truncation=True,
179
+ max_length=4096,
180
+ ).to(model.device)
181
+ print(f"Prompt token count: {inputs.input_ids.shape[-1]}")
182
+
183
+ print(f"Generating response with sampling enabled ({temperature=})...")
184
+ with torch.no_grad():
185
+ output_ids = model.generate(
186
+ **inputs,
187
+ max_new_tokens=1024,
188
+ do_sample=True,
189
+ temperature=temperature,
190
+ use_cache=True,
191
+ pad_token_id=tokenizer.pad_token_id,
192
+ eos_token_id=tokenizer.eos_token_id,
193
+ )
194
+ generated = output_ids[:, inputs.input_ids.shape[-1]:]
195
+
196
+ print("\nGenerated response:")
197
+ print("-" * 80)
198
+ print(tokenizer.batch_decode(generated, skip_special_tokens=True)[0])
199
+ ```
200
+
201
+ ### Safer custom-code loading
202
+
203
+ Because this model uses remote custom code, pin a reviewed commit hash for reproducible and safer usage:
204
+
205
+ ```python
206
+ commit_hash = "<reviewed-commit-hash>"
207
+ model = AutoModelForCausalLM.from_pretrained(
208
+ "kogai/laneformer-2b-it",
209
+ trust_remote_code=True,
210
+ revision=commit_hash,
211
+ dtype="auto",
212
+ device_map="auto",
213
+ )
214
+ ```
215
+
216
+ ## Tokenizer
217
+
218
+ This repository uses the **Llama 2 tokenizer** with a 32,000-token vocabulary. The expected special-token convention is:
219
+
220
+ | Token | ID |
221
+ |---|---:|
222
+ | `<unk>` | 0 |
223
+ | `<s>` | 1 |
224
+ | `</s>` | 2 |
225
+
226
+ The model config uses `eos_token_id = 2` and `pad_token_id = 2`.
227
+
228
+ ## Training data and procedure
229
+
230
+ This checkpoint was trained with a staged language-modeling recipe designed to first learn broad language/modeling capabilities and then continue training on a code- and reasoning-focused mixture. The TorchTitan training configs use sequence length 4096 and global batch size 1536, or 6,291,456 tokens per optimizer step.
231
+
232
+ ### Training stages
233
+
234
+ | Stage | Focus | Framework | Tokens | Steps | Approx. tokens / step | Notes |
235
+ |---|---|---|---:|---:|---:|---|
236
+ | Pre-training | General language-model pre-training | TorchTitan | ~4T | 620,000 | ~6.29M | NVIDIA Nemotron pre-training datasets; final checkpoint selected. |
237
+ | Mid-training | Code- and reasoning-focused continuation training | TorchTitan | ~2T | 310,000 | ~6.29M | NVIDIA Nemotron pre-training datasets; initialized from the Pre-training checkpoint. |
238
+ | Post-training | SFT, instruction tuning | Hugging Face Transformers | ~210M | 200 | ~1.05M | Custom data mixture; Initialized from the mid-training checkpoint. |
239
+
240
+ ### Data sources
241
+
242
+ Both TorchTitan stages depend primarily on [NVIDIA Nemotron pre-training datasets](https://huggingface.co/collections/nvidia/nemotron-pre-training-datasets). Pre-training uses a Nemotron-CC-v2-centered mixture for broad language-model pretraining, with web, synthetic web, QA, math, SFT-style, and code components. Mid-training continues from the pre-training checkpoint on a more code- and reasoning-heavy Nemotron-derived mixture, increasing the emphasis on code metadata, synthetic code data, Common Crawl code pages, math, STEM, and reasoning data.
243
+
244
+ ### Training infrastructure
245
+
246
+ | Field | Value |
247
+ |---|---|
248
+ | Pre-training framework | TorchTitan |
249
+ | Post-training framework | Hugging Face Transformers |
250
+ | Training hardware | 24 nodes × 8 NVIDIA H100 GPUs = 192 H100 GPUs |
251
+ | Training clusters | Scaleway cluster; ADASTRA cluster |
252
+ | Cloud/provider/region | France |
253
+ | Training time | ~21 days |
254
+ | Precision | FP32/BF16 mixed precision |
255
+ | Parallelism | Data-parallel |
256
+ | Optimizer | AdamW |
257
+ | Learning-rate schedule | WSD |
258
+ | Sequence length during training | 4096 |
259
+ | Checkpoint selection | final step |
260
+
261
+ ## Inference and performance
262
+
263
+ Kog Inference Engine running the Laneformer 2B model public-preview numbers:
264
+
265
+ | Setting | Reported speed | Notes |
266
+ |---|---:|---|
267
+ | 8x AMD MI300X | 3,000 output tokens/s/request | FP16, batch size 1, no speculative decoding |
268
+ | 8x NVIDIA H200 | 2,100 output tokens/s/request | FP16, batch size 1, no speculative decoding |
269
+
270
+ These benchmark numbers are for Kog's optimized inference stack, not the plain Hugging Face Transformers implementation in this repository. This preview does not rely on quantization, speculative decoding, pruning, early exit, or KV-cache compression to reach this speed.
271
+
272
+ ## Evaluation
273
+
274
+ The following internal Kog evaluations were run in June 2026 with `lm-evaluation-harness` 0.4.12 against a local Kog serving endpoint for `Kog Laneformer 2B` @ batch size 1 in FP16. These numbers evaluate the served preview model.
275
+
276
+ All values are percentages.
277
+
278
+ | Benchmark | Metric | Value | Samples | Setting |
279
+ |---|---:|---:|---:|---|
280
+ | HumanEval | pass@1 | 53.05 | 164 | 0-shot generation; greedy decoding; `max_gen_toks=1024` |
281
+ | HumanEval+ | pass@1 | 50.00 | 164 | Same as HumanEval pass@1, using `evalplus/humanevalplus` |
282
+ | HumanEval | pass@16 | 77.44 | 164 | 16 sampled completions; `temperature=0.8`; `top_p=1.0`; `max_gen_toks=1024` |
283
+ | IFEval | prompt-level strict accuracy | 12.57 | 541 | 0-shot chat generation; greedy decoding; `temperature=0`; `max_gen_toks=1280` |
284
+ | IFEval | instruction-level strict accuracy | 23.74 | 541 | Same IFEval run |
285
+ | ARC-Challenge | normalized accuracy | 31.06 | 1,172 | 0-shot multiple-choice logprobs |
286
+ | ARC-Easy | normalized accuracy | 47.90 | 2,376 | 0-shot multiple-choice logprobs |
287
+ | MMLU-Pro | exact match, custom extract | 11.77 | 12,032 | 5-shot chain-of-thought generation; greedy decoding; |
288
+ | GPQA Diamond | normalized accuracy | 25.25 | 198 | 0-shot multiple-choice logprobs |
289
+ | GPQA Main | normalized accuracy | 25.22 | 448 | 0-shot multiple-choice logprobs |
290
+ | GPQA Extended | normalized accuracy | 21.98 | 546 | 0-shot multiple-choice logprobs |
291
+
292
+ Long-context checks were also run with RULER-style synthetic tasks at 2,048 and 4,096 tokens using 0-shot greedy chat generation (`temperature=0`, remote tokenizer, `max_length=4096`). Values below are string-match scores.
293
+
294
+ | Task | 2,048 tokens | 4,096 tokens | Effective samples |
295
+ |---|---:|---:|---:|
296
+ | NIAH single 1 | 100.00 | 100.00 | 500 |
297
+ | NIAH single 2 | 100.00 | 100.00 | 500 |
298
+ | NIAH single 3 | 99.80 | 91.60 | 500 |
299
+ | NIAH multikey 1 | 99.20 | 83.40 | 500 |
300
+ | NIAH multikey 2 | 97.80 | 60.00 | 500 |
301
+ | NIAH multikey 3 | 91.80 | 91.20 | 500 |
302
+ | NIAH multiquery | 95.40 | 69.70 | 500 |
303
+ | NIAH multivalue | 94.60 | 82.20 | 500 |
304
+ | RULER variable tracking | 77.92 | 3.92 | 500 |
305
+ | RULER common words extraction | 24.72 | 78.14 | 500 |
306
+ | RULER frequent words extraction | 78.80 | 64.73 | 500 |
307
+
308
+ TODO (I'll add all benchmark and remove this sentence): HellaSwag, standard MMLU, and GSM8K are not reported for this release.
309
+
310
+ ## Intended use
311
+
312
+ This model is intended for:
313
+
314
+ - Research and experimentation with latency-oriented Transformer architectures.
315
+ - Evaluation of Laneformer / Delayed Tensor Parallelism design choices.
316
+ - Causal language modeling and code-generation experiments.
317
+ - Fine-tuning experiments, subject to all applicable license terms.
318
+ - Inference-system and attention-backend testing.
319
+
320
+ This model is not automatically suitable for high-stakes settings such as medical, legal, financial, employment, education, public-sector, law-enforcement, or safety-critical decision-making.
321
+
322
+ ## Out-of-scope use
323
+
324
+ Do not use this model or tokenizer in ways that violate the repository licenses, the Llama 2 Community License, the Llama 2 Acceptable Use Policy, applicable law, privacy rights, or safety policies. Do not present generated outputs as factual without independent verification. Do not use the model as the sole decision-maker in high-stakes workflows.
325
+
326
+ ## Limitations and risks
327
+
328
+ - This is a 2B-class model and is not a frontier general-purpose assistant.
329
+ - The model is mid-trained and post-trained for code generation only.
330
+ - The model may generate incorrect, insecure, biased, toxic, or misleading content.
331
+ - The model may hallucinate facts, APIs, package names, citations, and code behavior.
332
+ - The base model may not follow instructions reliably unless it has been instruction-tuned.
333
+ - The public HF implementation prioritizes compatibility and inspection, not the full Kog Inference Engine latency path.
334
+ - Performance may depend on the exact PyTorch, Transformers, device, dtype, and attention backend used.
335
+ - Because this repo uses custom code, downstream users should review code before execution and pin a revision in production.
336
+
337
+ ## License
338
+
339
+ This repository is **multi-license**.
340
+
341
+ ### Kog-owned materials: Apache License 2.0
342
+
343
+ Unless a file states otherwise, the model weights, Hugging Face custom modeling and configuration code, model configuration files, metadata files, documentation, and README/model card are released under the **Apache License 2.0**.
344
+
345
+ See [`LICENSE`](./LICENSE) for the full Apache License 2.0 text.
346
+
347
+ ### Tokenizer materials: Llama 2 Community License
348
+
349
+ The tokenizer files are based on the **Llama 2 tokenizer** and are not licensed under Apache License 2.0. These tokenizer materials include, without limitation:
350
+
351
+ - `tokenizer.model`
352
+ - `tokenizer.json`
353
+ - `tokenizer_config.json`
354
+ - `special_tokens_map.json`
355
+ - any other file whose purpose is to reproduce or configure the Llama 2 tokenizer
356
+
357
+ These tokenizer materials are distributed under the **LLAMA 2 Community License Agreement**. See [`THIRD_PARTY_LICENSES/LLAMA2_LICENSE`](./THIRD_PARTY_LICENSES/LLAMA2_LICENSE) and [`NOTICE`](./NOTICE).
358
+
359
+ Required Llama 2 attribution notice:
360
+
361
+ > Llama 2 is licensed under the LLAMA 2 Community License, Copyright (c) Meta Platforms, Inc. All Rights Reserved.
362
+
363
+ Users and redistributors are responsible for complying with the Llama 2 Community License and its Acceptable Use Policy.
364
+
365
+ ## Citation
366
+
367
+ If you use this model or architecture, please cite the model repository and the Kog technical blog posts:
368
+
369
+ ```bibtex
370
+ @misc{kog_laneformer_tp_2b_2026,
371
+ title = {Kog Laneformer 2B},
372
+ author = {Kog AI},
373
+ year = {2026},
374
+ publisher = {Hugging Face},
375
+ howpublished = {\url{https://huggingface.co/kogai/laneformer-2b-it}}
376
+ }
377
+
378
+ @misc{kog_real_time_llm_inference_2026,
379
+ title = {Real-time LLM Inference on Standard Datacenter GPUs (3,000 tokens/s per request)},
380
+ author = {Kog Team},
381
+ year = {2026},
382
+ howpublished = {\url{https://blog.kog.ai/real-time-llm-inference-on-standard-gpus-3-000-tokens-s-per-request/}}
383
+ }
384
+
385
+ @misc{kog_delayed_tensor_parallelism_2026,
386
+ title = {Delayed Tensor Parallelism for Faster Transformer Inference},
387
+ author = {Kog Team},
388
+ year = {2026},
389
+ howpublished = {\url{https://blog.kog.ai/delayed-tensor-parallelism-for-faster-transformer-inference/}}
390
+ }
391
+ ```
392
+
393
+ ## Contact
394
+
395
+ For questions about this model, open a discussion or issue on the Hugging Face repository, or contact Kog AI through the channels listed on [kog.ai](https://www.kog.ai/).
THIRD_PARTY_LICENSES/LLAMA2_LICENSE ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ LLAMA 2 COMMUNITY LICENSE AGREEMENT
2
+ Llama 2 Version Release Date: July 18, 2023
3
+
4
+ "Agreement" means the terms and conditions for use, reproduction, distribution and
5
+ modification of the Llama Materials set forth herein.
6
+
7
+ "Documentation" means the specifications, manuals and documentation
8
+ accompanying Llama 2 distributed by Meta at ai.meta.com/resources/models-and-
9
+ libraries/llama-downloads/.
10
+
11
+ "Licensee" or "you" means you, or your employer or any other person or entity (if
12
+ you are entering into this Agreement on such person or entity's behalf), of the age
13
+ required under applicable laws, rules or regulations to provide legal consent and that
14
+ has legal authority to bind your employer or such other person or entity if you are
15
+ entering in this Agreement on their behalf.
16
+
17
+ "Llama 2" means the foundational large language models and software and
18
+ algorithms, including machine-learning model code, trained model weights,
19
+ inference-enabling code, training-enabling code, fine-tuning enabling code and other
20
+ elements of the foregoing distributed by Meta at ai.meta.com/resources/models-and-
21
+ libraries/llama-downloads/.
22
+
23
+ "Llama Materials" means, collectively, Meta's proprietary Llama 2 and
24
+ Documentation (and any portion thereof) made available under this Agreement.
25
+
26
+ "Meta" or "we" means Meta Platforms Ireland Limited (if you are located in or, if you
27
+ are an entity, your principal place of business is in the EEA or Switzerland) and Meta
28
+ Platforms, Inc. (if you are located outside of the EEA or Switzerland).
29
+
30
+ By clicking "I Accept" below or by using or distributing any portion or element of the
31
+ Llama Materials, you agree to be bound by this Agreement.
32
+
33
+ 1. License Rights and Redistribution.
34
+
35
+ a. Grant of Rights. You are granted a non-exclusive, worldwide, non-
36
+ transferable and royalty-free limited license under Meta's intellectual property or
37
+ other rights owned by Meta embodied in the Llama Materials to use, reproduce,
38
+ distribute, copy, create derivative works of, and make modifications to the Llama
39
+ Materials.
40
+
41
+ b. Redistribution and Use.
42
+
43
+ i. If you distribute or make the Llama Materials, or any derivative works
44
+ thereof, available to a third party, you shall provide a copy of this Agreement to such
45
+ third party.
46
+ ii. If you receive Llama Materials, or any derivative works thereof, from
47
+ a Licensee as part of an integrated end user product, then Section 2 of this
48
+ Agreement will not apply to you.
49
+
50
+ iii. You must retain in all copies of the Llama Materials that you
51
+ distribute the following attribution notice within a "Notice" text file distributed as a
52
+ part of such copies: "Llama 2 is licensed under the LLAMA 2 Community License,
53
+ Copyright (c) Meta Platforms, Inc. All Rights Reserved."
54
+
55
+ iv. Your use of the Llama Materials must comply with applicable laws
56
+ and regulations (including trade compliance laws and regulations) and adhere to the
57
+ Acceptable Use Policy for the Llama Materials (available at
58
+ https://ai.meta.com/llama/use-policy), which is hereby incorporated by reference into
59
+ this Agreement.
60
+
61
+ v. You will not use the Llama Materials or any output or results of the
62
+ Llama Materials to improve any other large language model (excluding Llama 2 or
63
+ derivative works thereof).
64
+
65
+ 2. Additional Commercial Terms. If, on the Llama 2 version release date, the
66
+ monthly active users of the products or services made available by or for Licensee,
67
+ or Licensee's affiliates, is greater than 700 million monthly active users in the
68
+ preceding calendar month, you must request a license from Meta, which Meta may
69
+ grant to you in its sole discretion, and you are not authorized to exercise any of the
70
+ rights under this Agreement unless or until Meta otherwise expressly grants you
71
+ such rights.
72
+
73
+ 3. Disclaimer of Warranty. UNLESS REQUIRED BY APPLICABLE LAW, THE
74
+ LLAMA MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE
75
+ PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
76
+ EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY
77
+ WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR
78
+ FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE
79
+ FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING
80
+ THE LLAMA MATERIALS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR
81
+ USE OF THE LLAMA MATERIALS AND ANY OUTPUT AND RESULTS.
82
+
83
+ 4. Limitation of Liability. IN NO EVENT WILL META OR ITS AFFILIATES BE
84
+ LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT,
85
+ NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS
86
+ AGREEMENT, FOR ANY LOST PROFITS OR ANY INDIRECT, SPECIAL,
87
+ CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN
88
+ IF META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF
89
+ ANY OF THE FOREGOING.
90
+
91
+ 5. Intellectual Property.
92
+
93
+ a. No trademark licenses are granted under this Agreement, and in
94
+ connection with the Llama Materials, neither Meta nor Licensee may use any name
95
+ or mark owned by or associated with the other or any of its affiliates, except as
96
+ required for reasonable and customary use in describing and redistributing the
97
+ Llama Materials.
98
+
99
+ b. Subject to Meta's ownership of Llama Materials and derivatives made by or
100
+ for Meta, with respect to any derivative works and modifications of the Llama
101
+ Materials that are made by you, as between you and Meta, you are and will be the
102
+ owner of such derivative works and modifications.
103
+
104
+ c. If you institute litigation or other proceedings against Meta or any entity
105
+ (including a cross-claim or counterclaim in a lawsuit) alleging that the Llama
106
+ Materials or Llama 2 outputs or results, or any portion of any of the foregoing,
107
+ constitutes infringement of intellectual property or other rights owned or licensable
108
+ by you, then any licenses granted to you under this Agreement shall terminate as of
109
+ the date such litigation or claim is filed or instituted. You will indemnify and hold
110
+ harmless Meta from and against any claim by any third party arising out of or related
111
+ to your use or distribution of the Llama Materials.
112
+
113
+ 6. Term and Termination. The term of this Agreement will commence upon your
114
+ acceptance of this Agreement or access to the Llama Materials and will continue in
115
+ full force and effect until terminated in accordance with the terms and conditions
116
+ herein. Meta may terminate this Agreement if you are in breach of any term or
117
+ condition of this Agreement. Upon termination of this Agreement, you shall delete
118
+ and cease use of the Llama Materials. Sections 3, 4 and 7 shall survive the
119
+ termination of this Agreement.
120
+
121
+ 7. Governing Law and Jurisdiction. This Agreement will be governed and
122
+ construed under the laws of the State of California without regard to choice of law
123
+ principles, and the UN Convention on Contracts for the International Sale of Goods
124
+ does not apply to this Agreement. The courts of California shall have exclusive
125
+ jurisdiction of any dispute arising out of this Agreement.
__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoConfig
2
+
3
+ from .configuration_laneformer import LaneformerTPConfig
4
+ from .modeling_laneformer import LaneformerTPForCausalLM, LaneformerTPModel
5
+
6
+ LaneformerTPConfig.register_for_auto_class()
7
+ LaneformerTPModel.register_for_auto_class("AutoModel")
8
+ LaneformerTPForCausalLM.register_for_auto_class("AutoModelForCausalLM")
9
+ AutoConfig.register("laneformer_tp", LaneformerTPConfig)
10
+
11
+ __all__ = ["LaneformerTPConfig", "LaneformerTPModel", "LaneformerTPForCausalLM"]
chat_template.jinja ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- bos_token }}
2
+ {%- for message in messages %}
3
+ {%- if message['role'] == 'system' %}
4
+ {#- Ignore system messages entirely in this template. #}
5
+ {%- elif message['role'] == 'user' %}
6
+ {{- '<|start_header_id|>user<|end_header_id|>\n\n' }}
7
+ {{- message['content'] | trim }}
8
+ {{- eos_token }}
9
+ {%- elif message['role'] == 'assistant' %}
10
+ {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' }}
11
+ {%- generation -%}
12
+ {{- message['content'] | trim }}
13
+ {{- eos_token }}
14
+ {%- endgeneration -%}
15
+ {%- else %}
16
+ {{- raise_exception("Unsupported role for no-system/no-tools template: " + message['role']) }}
17
+ {%- endif %}
18
+ {%- endfor %}
19
+ {%- if add_generation_prompt %}
20
+ {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' }}
21
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "laneformer_tp",
3
+ "architectures": [
4
+ "LaneformerTPForCausalLM"
5
+ ],
6
+ "auto_map": {
7
+ "AutoConfig": "configuration_laneformer.LaneformerTPConfig",
8
+ "AutoModel": "modeling_laneformer.LaneformerTPModel",
9
+ "AutoModelForCausalLM": "modeling_laneformer.LaneformerTPForCausalLM"
10
+ },
11
+ "hidden_size": 3072,
12
+ "num_hidden_layers": 15,
13
+ "num_attention_heads": 32,
14
+ "num_key_value_heads": 16,
15
+ "intermediate_size": 12288,
16
+ "max_position_embeddings": 8192,
17
+ "max_seq_len": 8192,
18
+ "eos_token_id": 2,
19
+ "pad_token_id": 2,
20
+ "vocab_size": 32000,
21
+ "rope_theta": 10000,
22
+ "norm_eps": 1e-05,
23
+ "use_cache": false,
24
+ "num_lanes": 8,
25
+ "broadcast_delay": 2,
26
+ "use_attention_comm": true,
27
+ "use_mlp_comm": true,
28
+ "use_early_comm": false,
29
+ "lm_head_type": "vocab_parallel",
30
+ "pre_norm_lane_agg": false,
31
+ "replicated_rmsn_scale": true,
32
+ "tie_word_embeddings": false,
33
+ "sliding_window": 2048,
34
+ "swa_layers": [
35
+ 0,
36
+ 1,
37
+ 2,
38
+ 3,
39
+ 4,
40
+ 5,
41
+ 6,
42
+ 7,
43
+ 8,
44
+ 9
45
+ ],
46
+ "layer_types": [
47
+ "sliding_attention",
48
+ "sliding_attention",
49
+ "sliding_attention",
50
+ "sliding_attention",
51
+ "sliding_attention",
52
+ "sliding_attention",
53
+ "sliding_attention",
54
+ "sliding_attention",
55
+ "sliding_attention",
56
+ "sliding_attention",
57
+ "full_attention",
58
+ "full_attention",
59
+ "full_attention",
60
+ "full_attention",
61
+ "full_attention"
62
+ ],
63
+ "_attn_implementation": "flex_attention",
64
+ "dtype": "bfloat16",
65
+ "transformers_version": "4.57.6"
66
+ }
configuration_laneformer.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Optional
4
+
5
+ from transformers import PretrainedConfig
6
+
7
+
8
+ _VALID_LM_HEAD_TYPES = {"replicate", "lane", "vocab_parallel"}
9
+ _VALID_ROPE_SCALING_KEYS = {
10
+ "scaling_factor",
11
+ "low_freq_factor",
12
+ "high_freq_factor",
13
+ "original_max_position_embeddings",
14
+ }
15
+
16
+
17
+ def _infer_layer_types(
18
+ *,
19
+ num_hidden_layers: int,
20
+ sliding_window: Optional[int],
21
+ swa_layers: list[int],
22
+ use_sliding_window: Optional[bool],
23
+ ) -> list[str]:
24
+ if (
25
+ sliding_window is None
26
+ or int(sliding_window) <= 0
27
+ or use_sliding_window is False
28
+ ):
29
+ return ["full_attention"] * int(num_hidden_layers)
30
+
31
+ sliding_layer_indices = {int(layer) for layer in swa_layers}
32
+ return [
33
+ "sliding_attention"
34
+ if layer_index in sliding_layer_indices
35
+ else "full_attention"
36
+ for layer_index in range(int(num_hidden_layers))
37
+ ]
38
+
39
+
40
+ def _validate_positive_int(name: str, value: int) -> int:
41
+ value = int(value)
42
+ if value <= 0:
43
+ raise ValueError(f"{name} must be a positive integer, got {value}")
44
+ return value
45
+
46
+
47
+ def _validate_nonnegative_int(name: str, value: int) -> int:
48
+ value = int(value)
49
+ if value < 0:
50
+ raise ValueError(f"{name} must be >= 0, got {value}")
51
+ return value
52
+
53
+
54
+ def _validate_positive_float(name: str, value: float) -> float:
55
+ value = float(value)
56
+ if value <= 0.0:
57
+ raise ValueError(f"{name} must be > 0, got {value}")
58
+ return value
59
+
60
+
61
+ def _validate_probability(name: str, value: float) -> float:
62
+ value = float(value)
63
+ if not 0.0 <= value < 1.0:
64
+ raise ValueError(f"{name} must satisfy 0.0 <= {name} < 1.0, got {value}")
65
+ return value
66
+
67
+
68
+ def _validate_divisible(name: str, numerator: int, denominator: int) -> None:
69
+ if int(numerator) % int(denominator) != 0:
70
+ raise ValueError(f"{name} must be divisible by {denominator}, got {numerator}")
71
+
72
+
73
+ def _is_power_of_two(value: int) -> bool:
74
+ return value > 0 and (value & (value - 1)) == 0
75
+
76
+
77
+ def _is_rocm_torch_build() -> bool:
78
+ try:
79
+ import torch
80
+ except ImportError:
81
+ return False
82
+
83
+ return getattr(torch.version, "hip", None) is not None
84
+
85
+
86
+ def _validate_swa_layers(swa_layers: list[int], num_hidden_layers: int) -> None:
87
+ for layer in swa_layers:
88
+ if not 0 <= layer < num_hidden_layers:
89
+ raise ValueError(
90
+ "swa_layers must satisfy 0 <= layer < num_hidden_layers, "
91
+ f"got layer {layer} with num_hidden_layers={num_hidden_layers}"
92
+ )
93
+
94
+
95
+ def _validate_rope_scaling(rope_scaling: Optional[dict[str, Any]]) -> None:
96
+ if rope_scaling is None:
97
+ return
98
+ if not isinstance(rope_scaling, dict):
99
+ raise ValueError("rope_scaling must be a dictionary")
100
+
101
+ unknown_keys = set(rope_scaling) - _VALID_ROPE_SCALING_KEYS
102
+ if unknown_keys:
103
+ raise ValueError(f"Unknown rope_scaling keys: {sorted(unknown_keys)}")
104
+
105
+ scaling_factor = float(rope_scaling.get("scaling_factor", 1.0))
106
+ low_freq_factor = float(rope_scaling.get("low_freq_factor", 1.0))
107
+ high_freq_factor = float(rope_scaling.get("high_freq_factor", 1.0))
108
+ original_max_position_embeddings = int(
109
+ rope_scaling.get("original_max_position_embeddings", 4096)
110
+ )
111
+
112
+ if scaling_factor <= 0:
113
+ raise ValueError("rope_scaling.scaling_factor must be > 0")
114
+ if low_freq_factor <= 0 or high_freq_factor <= 0:
115
+ raise ValueError("rope_scaling frequency factors must be > 0")
116
+ if high_freq_factor == low_freq_factor:
117
+ raise ValueError(
118
+ "rope_scaling.high_freq_factor and low_freq_factor must differ"
119
+ )
120
+ if original_max_position_embeddings <= 0:
121
+ raise ValueError("rope_scaling.original_max_position_embeddings must be > 0")
122
+
123
+
124
+ class LaneformerTPConfig(PretrainedConfig):
125
+ model_type = "laneformer_tp"
126
+ keys_to_ignore_at_inference = ["past_key_values"]
127
+
128
+ def __init__(
129
+ self,
130
+ hidden_size: int = 4096,
131
+ num_hidden_layers: int = 32,
132
+ num_attention_heads: int = 32,
133
+ num_key_value_heads: Optional[int] = None,
134
+ intermediate_size: int = 4 * 4096,
135
+ max_position_embeddings: int = 131072,
136
+ eos_token_id: int = 0,
137
+ pad_token_id: Optional[int] = None,
138
+ vocab_size: int = 128256,
139
+ rope_theta: float = 10000.0,
140
+ norm_eps: float = 1e-5,
141
+ multiple_of: int = 32,
142
+ depth_init: bool = True,
143
+ use_flex_attn: bool = False,
144
+ attn_mask_type: str = "causal",
145
+ initializer_range: float = 0.02,
146
+ attention_dropout: float = 0.0,
147
+ use_cache: bool = False,
148
+ # laneformer-specific extras (HF is fine with extra fields):
149
+ num_lanes: int = 1,
150
+ broadcast_delay: int = 1,
151
+ use_attention_comm: bool = True,
152
+ use_mlp_comm: bool = True,
153
+ use_early_comm: bool = True,
154
+ lm_head_type: str = "replicate",
155
+ pre_norm_lane_agg: bool = False,
156
+ replicated_rmsn_scale: bool = True,
157
+ tie_word_embeddings: bool = False,
158
+ sliding_window: Optional[int] = None,
159
+ sliding_window_n_layers: int = 0,
160
+ swa_layers: Optional[list[int]] = None,
161
+ rope_scaling: Optional[dict[str, Any]] = None,
162
+ **kwargs,
163
+ ):
164
+ if pad_token_id is None:
165
+ pad_token_id = eos_token_id
166
+ if num_key_value_heads is None:
167
+ num_key_value_heads = num_attention_heads
168
+
169
+ hidden_size = _validate_positive_int("hidden_size", hidden_size)
170
+ num_hidden_layers = _validate_positive_int(
171
+ "num_hidden_layers", num_hidden_layers
172
+ )
173
+ num_attention_heads = _validate_positive_int(
174
+ "num_attention_heads", num_attention_heads
175
+ )
176
+ num_key_value_heads = _validate_positive_int(
177
+ "num_key_value_heads", num_key_value_heads
178
+ )
179
+ intermediate_size = _validate_positive_int(
180
+ "intermediate_size", intermediate_size
181
+ )
182
+ max_position_embeddings = _validate_positive_int(
183
+ "max_position_embeddings", max_position_embeddings
184
+ )
185
+ vocab_size = _validate_positive_int("vocab_size", vocab_size)
186
+ num_lanes = _validate_positive_int("num_lanes", num_lanes)
187
+ rope_theta = _validate_positive_float("rope_theta", rope_theta)
188
+ norm_eps = _validate_positive_float("norm_eps", norm_eps)
189
+ multiple_of = _validate_positive_int("multiple_of", multiple_of)
190
+ attention_dropout = _validate_probability(
191
+ "attention_dropout", attention_dropout
192
+ )
193
+ broadcast_delay = _validate_nonnegative_int("broadcast_delay", broadcast_delay)
194
+ sliding_window_n_layers = _validate_nonnegative_int(
195
+ "sliding_window_n_layers", sliding_window_n_layers
196
+ )
197
+ if sliding_window_n_layers > num_hidden_layers:
198
+ raise ValueError(
199
+ "sliding_window_n_layers must satisfy "
200
+ "0 <= sliding_window_n_layers <= num_hidden_layers, "
201
+ f"got {sliding_window_n_layers} with "
202
+ f"num_hidden_layers={num_hidden_layers}"
203
+ )
204
+ _validate_divisible("hidden_size", hidden_size, num_attention_heads)
205
+ _validate_divisible(
206
+ "num_attention_heads", num_attention_heads, num_key_value_heads
207
+ )
208
+ _validate_divisible("hidden_size", hidden_size, num_lanes)
209
+ _validate_divisible("intermediate_size", intermediate_size, num_lanes)
210
+ head_dim = hidden_size // num_attention_heads
211
+ if head_dim % 2 != 0:
212
+ raise ValueError(
213
+ "hidden_size // num_attention_heads must be even for RoPE, "
214
+ f"got {head_dim}"
215
+ )
216
+ _validate_divisible(
217
+ "num_key_value_heads * head_dim",
218
+ num_key_value_heads * head_dim,
219
+ num_lanes,
220
+ )
221
+ if lm_head_type not in _VALID_LM_HEAD_TYPES:
222
+ raise ValueError(
223
+ f"lm_head_type must be one of {sorted(_VALID_LM_HEAD_TYPES)}, "
224
+ f"got {lm_head_type!r}"
225
+ )
226
+ if lm_head_type == "vocab_parallel":
227
+ _validate_divisible("vocab_size", vocab_size, num_lanes)
228
+ if sliding_window is not None:
229
+ sliding_window = _validate_positive_int("sliding_window", sliding_window)
230
+ if tie_word_embeddings:
231
+ raise ValueError("tie_word_embeddings is not supported for LaneformerTP")
232
+ _validate_rope_scaling(rope_scaling)
233
+ if swa_layers is None:
234
+ swa_layers = list(range(sliding_window_n_layers))
235
+ else:
236
+ swa_layers = sorted({int(layer) for layer in swa_layers})
237
+ _validate_swa_layers(swa_layers, num_hidden_layers)
238
+
239
+ super().__init__(
240
+ eos_token_id=eos_token_id,
241
+ pad_token_id=pad_token_id,
242
+ vocab_size=vocab_size,
243
+ tie_word_embeddings=tie_word_embeddings,
244
+ **kwargs,
245
+ )
246
+ if (
247
+ self._attn_implementation == "flex_attention"
248
+ and _is_rocm_torch_build()
249
+ and not _is_power_of_two(head_dim)
250
+ ):
251
+ self._attn_implementation = "sdpa"
252
+
253
+ self.hidden_size = hidden_size
254
+ self.num_hidden_layers = num_hidden_layers
255
+ self.num_attention_heads = num_attention_heads
256
+ self.num_key_value_heads = num_key_value_heads
257
+ self.intermediate_size = intermediate_size
258
+ self.max_position_embeddings = max_position_embeddings
259
+ self.rope_theta = rope_theta
260
+ self.norm_eps = norm_eps
261
+ self.multiple_of = multiple_of
262
+ self.depth_init = depth_init
263
+ self.use_flex_attn = use_flex_attn
264
+ self.attn_mask_type = attn_mask_type
265
+ self.initializer_range = initializer_range
266
+ self.attention_dropout = attention_dropout
267
+ self.use_cache = use_cache
268
+ self.sliding_window = sliding_window
269
+ self.rope_scaling = rope_scaling
270
+ self.swa_layers = swa_layers
271
+ # legacy field kept for backward compatibility
272
+ self.sliding_window_n_layers = len(self.swa_layers)
273
+ if getattr(self, "layer_types", None) is None:
274
+ self.layer_types = _infer_layer_types(
275
+ num_hidden_layers=num_hidden_layers,
276
+ sliding_window=sliding_window,
277
+ swa_layers=self.swa_layers,
278
+ use_sliding_window=getattr(self, "use_sliding_window", None),
279
+ )
280
+
281
+ # custom fields
282
+ self.num_lanes = num_lanes
283
+
284
+ self.use_attention_comm = use_attention_comm
285
+ self.use_mlp_comm = use_mlp_comm
286
+ # legacy aggregate flag kept for compatibility
287
+ self.use_comm = bool(self.use_attention_comm and self.use_mlp_comm)
288
+ self.use_early_comm = use_early_comm
289
+ self.broadcast_delay = broadcast_delay
290
+ self.lm_head_type = lm_head_type
291
+ self.pre_norm_lane_agg = pre_norm_lane_agg
292
+ self.replicated_rmsn_scale = replicated_rmsn_scale
generation_config.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "eos_token_id": 2,
4
+ "transformers_version": "4.57.6",
5
+ "pad_token_id": 2
6
+ }
model-00001-of-00002.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:504fb463be222f3be7afa16a13208f4bcd050e5d21986274e09e5f53c27c43b6
3
+ size 2499387800
model-00002-of-00002.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c17071a6a63d05c59c50b73e4aff902cfe0b3e7add7eddf5be9546997b579d91
3
+ size 2140767104
model.safetensors.index.json ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "total_parameters": 2320069632,
4
+ "total_size": 4640139264
5
+ },
6
+ "weight_map": {
7
+ "lm_head.weight": "model-00002-of-00002.safetensors",
8
+ "model.layers.0.attention.wk.weight": "model-00001-of-00002.safetensors",
9
+ "model.layers.0.attention.wo.weight": "model-00001-of-00002.safetensors",
10
+ "model.layers.0.attention.wq.weight": "model-00001-of-00002.safetensors",
11
+ "model.layers.0.attention.wv.weight": "model-00001-of-00002.safetensors",
12
+ "model.layers.0.attention_norm.weight": "model-00001-of-00002.safetensors",
13
+ "model.layers.0.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
14
+ "model.layers.0.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
15
+ "model.layers.0.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
16
+ "model.layers.0.ffn_norm.weight": "model-00001-of-00002.safetensors",
17
+ "model.layers.1.attention.wk.weight": "model-00001-of-00002.safetensors",
18
+ "model.layers.1.attention.wo.weight": "model-00001-of-00002.safetensors",
19
+ "model.layers.1.attention.wq.weight": "model-00001-of-00002.safetensors",
20
+ "model.layers.1.attention.wv.weight": "model-00001-of-00002.safetensors",
21
+ "model.layers.1.attention_norm.weight": "model-00001-of-00002.safetensors",
22
+ "model.layers.1.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
23
+ "model.layers.1.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
24
+ "model.layers.1.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
25
+ "model.layers.1.ffn_norm.weight": "model-00001-of-00002.safetensors",
26
+ "model.layers.10.attention.wk.weight": "model-00002-of-00002.safetensors",
27
+ "model.layers.10.attention.wo.weight": "model-00002-of-00002.safetensors",
28
+ "model.layers.10.attention.wq.weight": "model-00002-of-00002.safetensors",
29
+ "model.layers.10.attention.wv.weight": "model-00002-of-00002.safetensors",
30
+ "model.layers.10.attention_norm.weight": "model-00002-of-00002.safetensors",
31
+ "model.layers.10.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
32
+ "model.layers.10.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
33
+ "model.layers.10.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
34
+ "model.layers.10.ffn_norm.weight": "model-00002-of-00002.safetensors",
35
+ "model.layers.11.attention.wk.weight": "model-00002-of-00002.safetensors",
36
+ "model.layers.11.attention.wo.weight": "model-00002-of-00002.safetensors",
37
+ "model.layers.11.attention.wq.weight": "model-00002-of-00002.safetensors",
38
+ "model.layers.11.attention.wv.weight": "model-00002-of-00002.safetensors",
39
+ "model.layers.11.attention_norm.weight": "model-00002-of-00002.safetensors",
40
+ "model.layers.11.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
41
+ "model.layers.11.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
42
+ "model.layers.11.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
43
+ "model.layers.11.ffn_norm.weight": "model-00002-of-00002.safetensors",
44
+ "model.layers.12.attention.wk.weight": "model-00002-of-00002.safetensors",
45
+ "model.layers.12.attention.wo.weight": "model-00002-of-00002.safetensors",
46
+ "model.layers.12.attention.wq.weight": "model-00002-of-00002.safetensors",
47
+ "model.layers.12.attention.wv.weight": "model-00002-of-00002.safetensors",
48
+ "model.layers.12.attention_norm.weight": "model-00002-of-00002.safetensors",
49
+ "model.layers.12.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
50
+ "model.layers.12.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
51
+ "model.layers.12.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
52
+ "model.layers.12.ffn_norm.weight": "model-00002-of-00002.safetensors",
53
+ "model.layers.13.attention.wk.weight": "model-00002-of-00002.safetensors",
54
+ "model.layers.13.attention.wo.weight": "model-00002-of-00002.safetensors",
55
+ "model.layers.13.attention.wq.weight": "model-00002-of-00002.safetensors",
56
+ "model.layers.13.attention.wv.weight": "model-00002-of-00002.safetensors",
57
+ "model.layers.13.attention_norm.weight": "model-00002-of-00002.safetensors",
58
+ "model.layers.13.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
59
+ "model.layers.13.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
60
+ "model.layers.13.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
61
+ "model.layers.13.ffn_norm.weight": "model-00002-of-00002.safetensors",
62
+ "model.layers.14.attention.wk.weight": "model-00002-of-00002.safetensors",
63
+ "model.layers.14.attention.wo.weight": "model-00002-of-00002.safetensors",
64
+ "model.layers.14.attention.wq.weight": "model-00002-of-00002.safetensors",
65
+ "model.layers.14.attention.wv.weight": "model-00002-of-00002.safetensors",
66
+ "model.layers.14.attention_norm.weight": "model-00002-of-00002.safetensors",
67
+ "model.layers.14.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
68
+ "model.layers.14.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
69
+ "model.layers.14.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
70
+ "model.layers.14.ffn_norm.weight": "model-00002-of-00002.safetensors",
71
+ "model.layers.2.attention.wk.weight": "model-00001-of-00002.safetensors",
72
+ "model.layers.2.attention.wo.weight": "model-00001-of-00002.safetensors",
73
+ "model.layers.2.attention.wq.weight": "model-00001-of-00002.safetensors",
74
+ "model.layers.2.attention.wv.weight": "model-00001-of-00002.safetensors",
75
+ "model.layers.2.attention_norm.weight": "model-00001-of-00002.safetensors",
76
+ "model.layers.2.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
77
+ "model.layers.2.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
78
+ "model.layers.2.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
79
+ "model.layers.2.ffn_norm.weight": "model-00001-of-00002.safetensors",
80
+ "model.layers.3.attention.wk.weight": "model-00001-of-00002.safetensors",
81
+ "model.layers.3.attention.wo.weight": "model-00001-of-00002.safetensors",
82
+ "model.layers.3.attention.wq.weight": "model-00001-of-00002.safetensors",
83
+ "model.layers.3.attention.wv.weight": "model-00001-of-00002.safetensors",
84
+ "model.layers.3.attention_norm.weight": "model-00001-of-00002.safetensors",
85
+ "model.layers.3.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
86
+ "model.layers.3.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
87
+ "model.layers.3.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
88
+ "model.layers.3.ffn_norm.weight": "model-00001-of-00002.safetensors",
89
+ "model.layers.4.attention.wk.weight": "model-00001-of-00002.safetensors",
90
+ "model.layers.4.attention.wo.weight": "model-00001-of-00002.safetensors",
91
+ "model.layers.4.attention.wq.weight": "model-00001-of-00002.safetensors",
92
+ "model.layers.4.attention.wv.weight": "model-00001-of-00002.safetensors",
93
+ "model.layers.4.attention_norm.weight": "model-00001-of-00002.safetensors",
94
+ "model.layers.4.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
95
+ "model.layers.4.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
96
+ "model.layers.4.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
97
+ "model.layers.4.ffn_norm.weight": "model-00001-of-00002.safetensors",
98
+ "model.layers.5.attention.wk.weight": "model-00001-of-00002.safetensors",
99
+ "model.layers.5.attention.wo.weight": "model-00001-of-00002.safetensors",
100
+ "model.layers.5.attention.wq.weight": "model-00001-of-00002.safetensors",
101
+ "model.layers.5.attention.wv.weight": "model-00001-of-00002.safetensors",
102
+ "model.layers.5.attention_norm.weight": "model-00001-of-00002.safetensors",
103
+ "model.layers.5.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
104
+ "model.layers.5.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
105
+ "model.layers.5.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
106
+ "model.layers.5.ffn_norm.weight": "model-00001-of-00002.safetensors",
107
+ "model.layers.6.attention.wk.weight": "model-00001-of-00002.safetensors",
108
+ "model.layers.6.attention.wo.weight": "model-00001-of-00002.safetensors",
109
+ "model.layers.6.attention.wq.weight": "model-00001-of-00002.safetensors",
110
+ "model.layers.6.attention.wv.weight": "model-00001-of-00002.safetensors",
111
+ "model.layers.6.attention_norm.weight": "model-00001-of-00002.safetensors",
112
+ "model.layers.6.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
113
+ "model.layers.6.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
114
+ "model.layers.6.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
115
+ "model.layers.6.ffn_norm.weight": "model-00001-of-00002.safetensors",
116
+ "model.layers.7.attention.wk.weight": "model-00001-of-00002.safetensors",
117
+ "model.layers.7.attention.wo.weight": "model-00001-of-00002.safetensors",
118
+ "model.layers.7.attention.wq.weight": "model-00001-of-00002.safetensors",
119
+ "model.layers.7.attention.wv.weight": "model-00001-of-00002.safetensors",
120
+ "model.layers.7.attention_norm.weight": "model-00001-of-00002.safetensors",
121
+ "model.layers.7.feed_forward.w1.weight": "model-00001-of-00002.safetensors",
122
+ "model.layers.7.feed_forward.w2.weight": "model-00001-of-00002.safetensors",
123
+ "model.layers.7.feed_forward.w3.weight": "model-00001-of-00002.safetensors",
124
+ "model.layers.7.ffn_norm.weight": "model-00001-of-00002.safetensors",
125
+ "model.layers.8.attention.wk.weight": "model-00001-of-00002.safetensors",
126
+ "model.layers.8.attention.wo.weight": "model-00002-of-00002.safetensors",
127
+ "model.layers.8.attention.wq.weight": "model-00001-of-00002.safetensors",
128
+ "model.layers.8.attention.wv.weight": "model-00001-of-00002.safetensors",
129
+ "model.layers.8.attention_norm.weight": "model-00002-of-00002.safetensors",
130
+ "model.layers.8.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
131
+ "model.layers.8.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
132
+ "model.layers.8.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
133
+ "model.layers.8.ffn_norm.weight": "model-00002-of-00002.safetensors",
134
+ "model.layers.9.attention.wk.weight": "model-00002-of-00002.safetensors",
135
+ "model.layers.9.attention.wo.weight": "model-00002-of-00002.safetensors",
136
+ "model.layers.9.attention.wq.weight": "model-00002-of-00002.safetensors",
137
+ "model.layers.9.attention.wv.weight": "model-00002-of-00002.safetensors",
138
+ "model.layers.9.attention_norm.weight": "model-00002-of-00002.safetensors",
139
+ "model.layers.9.feed_forward.w1.weight": "model-00002-of-00002.safetensors",
140
+ "model.layers.9.feed_forward.w2.weight": "model-00002-of-00002.safetensors",
141
+ "model.layers.9.feed_forward.w3.weight": "model-00002-of-00002.safetensors",
142
+ "model.layers.9.ffn_norm.weight": "model-00002-of-00002.safetensors",
143
+ "model.norm.weight": "model-00002-of-00002.safetensors",
144
+ "model.tok_embeddings.weight": "model-00001-of-00002.safetensors"
145
+ }
146
+ }
modeling_laneformer.py ADDED
@@ -0,0 +1,1047 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Hugging Face-compatible Laneformer implementation.
3
+
4
+ This file defines:
5
+ - LaneformerTPPreTrainedModel
6
+ - LaneformerTPModel (backbone)
7
+ - LaneformerTPForCausalLM (head + loss)
8
+
9
+ It mirrors the TorchTitan Laneformer structure so that state_dict keys largely match,
10
+ which makes converting checkpoints trivial (often identity mapping).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import inspect
16
+ import math
17
+ from dataclasses import dataclass
18
+ from enum import Enum
19
+ from functools import partial
20
+ from typing import Optional, Tuple, Union, Unpack
21
+
22
+ import torch
23
+ import torch.nn.functional as F
24
+ from torch import nn
25
+ from transformers.cache_utils import Cache, DynamicCache
26
+ from transformers.generation import GenerationMixin
27
+ from transformers.masking_utils import (
28
+ create_causal_mask,
29
+ create_sliding_window_causal_mask,
30
+ )
31
+ from transformers.modeling_outputs import (
32
+ BaseModelOutputWithPast,
33
+ CausalLMOutputWithPast,
34
+ )
35
+ from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
36
+ from transformers.utils import auto_docstring, can_return_tuple, TransformersKwargs
37
+
38
+ from .configuration_laneformer import LaneformerTPConfig
39
+
40
+
41
+ # ============================================================
42
+ # Rotary helpers (mirrors your implementation)
43
+ # ============================================================
44
+ @dataclass
45
+ class RoPEScalingArgs:
46
+ scaling_factor: float = 1.0
47
+ low_freq_factor: float = 1.0
48
+ high_freq_factor: float = 1.0
49
+ original_max_position_embeddings: int = 4096
50
+
51
+
52
+ def _rope_scaling_from_config(
53
+ config: LaneformerTPConfig,
54
+ ) -> RoPEScalingArgs | None:
55
+ if config.rope_scaling is None:
56
+ return None
57
+ try:
58
+ args = RoPEScalingArgs(**config.rope_scaling)
59
+ except TypeError as exc:
60
+ raise ValueError(f"Invalid rope_scaling configuration: {exc}") from exc
61
+
62
+ if args.scaling_factor <= 0:
63
+ raise ValueError("rope_scaling.scaling_factor must be > 0")
64
+ if args.low_freq_factor <= 0 or args.high_freq_factor <= 0:
65
+ raise ValueError("rope_scaling frequency factors must be > 0")
66
+ if args.high_freq_factor == args.low_freq_factor:
67
+ raise ValueError(
68
+ "rope_scaling.high_freq_factor and low_freq_factor must differ"
69
+ )
70
+ if args.original_max_position_embeddings <= 0:
71
+ raise ValueError("rope_scaling.original_max_position_embeddings must be > 0")
72
+ return args
73
+
74
+
75
+ def compute_rope_freqs(
76
+ dim: int,
77
+ theta: float = 10000.0,
78
+ scaling_args: RoPEScalingArgs | None = None,
79
+ device: torch.device | None = None,
80
+ ) -> torch.Tensor:
81
+ freqs = 1.0 / (
82
+ theta ** (torch.arange(0, dim, 2, device=device)[: (dim // 2)].float() / dim)
83
+ )
84
+ if scaling_args is not None:
85
+ scaling_factor = scaling_args.scaling_factor
86
+ low_freq_factor = scaling_args.low_freq_factor
87
+ high_freq_factor = scaling_args.high_freq_factor
88
+ original_max_position_embeddings = scaling_args.original_max_position_embeddings
89
+ wavelen = 2 * math.pi / freqs
90
+ high_freq_wavelen = original_max_position_embeddings / high_freq_factor
91
+ low_freq_wavelen = original_max_position_embeddings / low_freq_factor
92
+ freqs = torch.where(wavelen > low_freq_wavelen, freqs / scaling_factor, freqs)
93
+ smooth_factor = (
94
+ original_max_position_embeddings / wavelen - low_freq_factor
95
+ ) / (high_freq_factor - low_freq_factor)
96
+ smoothed_freqs = (
97
+ 1 - smooth_factor
98
+ ) * freqs / scaling_factor + smooth_factor * freqs
99
+ is_medium_freqs = ~(wavelen < high_freq_wavelen) * ~(wavelen > low_freq_wavelen)
100
+ freqs = torch.where(is_medium_freqs, smoothed_freqs, freqs)
101
+ return freqs
102
+
103
+
104
+ def precompute_freqs_cis(
105
+ dim: int,
106
+ end: int,
107
+ theta: float = 10000.0,
108
+ scaling_args: RoPEScalingArgs | None = None,
109
+ ) -> torch.Tensor:
110
+ freqs = compute_rope_freqs(dim, theta, scaling_args)
111
+ t = torch.arange(end, device=freqs.device)
112
+ freqs = torch.outer(t, freqs).float()
113
+ freqs_cis = torch.polar(torch.ones_like(freqs), freqs) # complex64
114
+ return freqs_cis
115
+
116
+
117
+ def freqs_cis_for_position_ids(
118
+ position_ids: torch.Tensor,
119
+ dim: int,
120
+ theta: float = 10000.0,
121
+ scaling_args: RoPEScalingArgs | None = None,
122
+ ) -> torch.Tensor:
123
+ freqs = compute_rope_freqs(
124
+ dim,
125
+ theta,
126
+ scaling_args,
127
+ device=position_ids.device,
128
+ )
129
+ angles = position_ids.float().unsqueeze(-1) * freqs
130
+ return torch.polar(torch.ones_like(angles), angles)
131
+
132
+
133
+ def reshape_for_broadcast(freqs_cis: torch.Tensor, x: torch.Tensor) -> torch.Tensor:
134
+ ndim = x.ndim
135
+ assert ndim > 1
136
+ seqlen = x.shape[1]
137
+ freqs_cis = freqs_cis[0:seqlen]
138
+ assert freqs_cis.shape == (seqlen, x.shape[-1])
139
+ shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
140
+ return freqs_cis.view(*shape)
141
+
142
+
143
+ def apply_rotary_emb(
144
+ xq: torch.Tensor,
145
+ xk: torch.Tensor,
146
+ freqs_cis: torch.Tensor,
147
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
148
+ xq_ = torch.view_as_complex(xq.float().reshape(*xq.shape[:-1], -1, 2))
149
+ xk_ = torch.view_as_complex(xk.float().reshape(*xk.shape[:-1], -1, 2))
150
+ # freqs_cis = reshape_for_broadcast(freqs_cis, xq_)
151
+ xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(3)
152
+ xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(3)
153
+ return xq_out.type_as(xq), xk_out.type_as(xk)
154
+
155
+
156
+ def repeat_kv(x: torch.Tensor, n_rep: int) -> torch.Tensor:
157
+ bs, slen, n_kv_heads, head_dim = x.shape
158
+ if n_rep == 1:
159
+ return x
160
+ return (
161
+ torch.unsqueeze(x, dim=3)
162
+ .expand(bs, slen, n_kv_heads, n_rep, head_dim)
163
+ .reshape(bs, slen, n_kv_heads * n_rep, head_dim)
164
+ )
165
+
166
+
167
+ class LaneLinear(nn.Module):
168
+ def __init__(self, in_features: int, out_features: int, num_lanes: int):
169
+ super().__init__()
170
+ self.num_lanes = num_lanes
171
+ self.in_features = in_features
172
+ self.out_features = out_features
173
+ self.weight = torch.empty(self.get_shape())
174
+ self.reset_parameters()
175
+
176
+ def reset_parameters(self):
177
+ raise NotImplementedError
178
+
179
+ def get_shape(self) -> Tuple[int, int, int]:
180
+ raise NotImplementedError
181
+
182
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
183
+ return torch.einsum(
184
+ "bsli,loi->bslo", x, self.weight
185
+ ) # [L, out_features, 1] @ [B*S, L, in_features // L, 1] -> [B*S, L, out_features, 1]
186
+
187
+
188
+ class LaneColumnLinear(LaneLinear):
189
+ def __init__(
190
+ self,
191
+ in_features: int,
192
+ out_features: int,
193
+ num_lanes: int,
194
+ ):
195
+ super().__init__(
196
+ in_features=in_features, out_features=out_features, num_lanes=num_lanes
197
+ )
198
+
199
+ def get_shape(self) -> Tuple[int, int, int]:
200
+ return (self.num_lanes, self.out_features, self.in_features // self.num_lanes)
201
+
202
+ def reset_parameters(self):
203
+ w = torch.empty(self.out_features, self.in_features)
204
+ nn.init.kaiming_uniform_(w, a=math.sqrt(5))
205
+ self.weight = nn.Parameter(
206
+ w.reshape(
207
+ self.out_features, self.num_lanes, self.in_features // self.num_lanes
208
+ )
209
+ .permute(1, 0, 2)
210
+ .contiguous()
211
+ )
212
+
213
+
214
+ class LaneRowLinear(LaneLinear):
215
+ def __init__(
216
+ self,
217
+ in_features: int,
218
+ out_features: int,
219
+ num_lanes: int,
220
+ ):
221
+ super().__init__(
222
+ in_features=in_features, out_features=out_features, num_lanes=num_lanes
223
+ )
224
+
225
+ def get_shape(self) -> Tuple[int, int, int]:
226
+ return (self.num_lanes, self.out_features // self.num_lanes, self.in_features)
227
+
228
+ def reset_parameters(self):
229
+ w = torch.empty(self.out_features, self.in_features)
230
+ nn.init.kaiming_uniform_(w, a=math.sqrt(5))
231
+ self.weight = nn.Parameter(w.reshape(self.weight.shape).contiguous())
232
+
233
+
234
+ class LaneLMHead(nn.Module):
235
+ def __init__(self, in_features: int, out_features: int, num_lanes: int):
236
+ super().__init__()
237
+ self.num_lanes = num_lanes
238
+ self.linear = nn.Linear(
239
+ in_features=num_lanes * in_features, out_features=out_features, bias=False
240
+ )
241
+
242
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
243
+ B, S, L, d = x.shape
244
+ return self.linear(x.view(B, S, L * d))
245
+
246
+
247
+ class LaneRMSNorm(nn.Module):
248
+ def __init__(self, dim: int, num_lanes: int, eps: float = 1e-8):
249
+ super().__init__()
250
+ self.rms_norm = nn.RMSNorm(dim, eps=eps, elementwise_affine=False)
251
+ self.dim = dim
252
+ self.eps = eps
253
+ self.scale = nn.Parameter(torch.ones(num_lanes, dim))
254
+
255
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
256
+ return self.rms_norm(x) * self.scale
257
+
258
+ def reset_parameters(self):
259
+ nn.init.ones_(self.scale)
260
+
261
+
262
+ def eager_attention_forward(
263
+ module: nn.Module,
264
+ query: torch.Tensor,
265
+ key: torch.Tensor,
266
+ value: torch.Tensor,
267
+ attention_mask: Optional[torch.Tensor],
268
+ scaling: Optional[float] = None,
269
+ dropout: float = 0.0,
270
+ **kwargs,
271
+ ):
272
+ num_key_value_groups = getattr(module, "num_key_value_groups", 1)
273
+ key_states = repeat_kv(key.transpose(1, 2), num_key_value_groups).transpose(1, 2)
274
+ value_states = repeat_kv(value.transpose(1, 2), num_key_value_groups).transpose(
275
+ 1, 2
276
+ )
277
+
278
+ if scaling is None:
279
+ scaling = query.shape[-1] ** -0.5
280
+
281
+ attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
282
+ if attention_mask is not None:
283
+ causal_mask = attention_mask[:, :, :, : key_states.shape[-2]]
284
+ attn_weights = attn_weights + causal_mask
285
+
286
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(
287
+ query.dtype
288
+ )
289
+ attn_weights = nn.functional.dropout(
290
+ attn_weights, p=dropout, training=module.training
291
+ )
292
+ attn_output = torch.matmul(attn_weights, value_states)
293
+ attn_output = attn_output.transpose(1, 2).contiguous()
294
+
295
+ return attn_output, attn_weights
296
+
297
+
298
+ def _attention_interface(config: LaneformerTPConfig):
299
+ attn_implementation = getattr(config, "_attn_implementation", "eager")
300
+ if attn_implementation == "eager":
301
+ return eager_attention_forward
302
+
303
+ get_interface = getattr(ALL_ATTENTION_FUNCTIONS, "get_interface", None)
304
+ if get_interface is not None:
305
+ return get_interface(attn_implementation, eager_attention_forward)
306
+
307
+ return ALL_ATTENTION_FUNCTIONS[attn_implementation]
308
+
309
+
310
+ _CAUSAL_MASK_USES_INPUTS_EMBEDS = (
311
+ "inputs_embeds" in inspect.signature(create_causal_mask).parameters
312
+ )
313
+ _SLIDING_MASK_USES_INPUTS_EMBEDS = (
314
+ "inputs_embeds" in inspect.signature(create_sliding_window_causal_mask).parameters
315
+ )
316
+
317
+
318
+ def _call_attention_mask_factory(
319
+ mask_factory,
320
+ *,
321
+ uses_inputs_embeds: bool,
322
+ config: LaneformerTPConfig,
323
+ inputs_embeds: torch.Tensor,
324
+ attention_mask: Optional[torch.Tensor],
325
+ cache_position: torch.Tensor,
326
+ past_key_values: Optional[Cache],
327
+ position_ids: Optional[torch.Tensor],
328
+ ):
329
+ if uses_inputs_embeds:
330
+ return mask_factory(
331
+ config=config,
332
+ inputs_embeds=inputs_embeds,
333
+ attention_mask=attention_mask,
334
+ past_key_values=past_key_values,
335
+ position_ids=position_ids,
336
+ )
337
+
338
+ return mask_factory(
339
+ config=config,
340
+ input_embeds=inputs_embeds,
341
+ attention_mask=attention_mask,
342
+ cache_position=cache_position,
343
+ past_key_values=past_key_values,
344
+ position_ids=position_ids,
345
+ )
346
+
347
+
348
+ def _attention_mask_needs_sliding_window_overlay(
349
+ attention_mask: Optional[torch.Tensor],
350
+ ) -> bool:
351
+ return (
352
+ isinstance(attention_mask, torch.Tensor)
353
+ and attention_mask.ndim == 4
354
+ and attention_mask.shape[-1] == attention_mask.shape[-2]
355
+ )
356
+
357
+
358
+ def _apply_sliding_window_to_attention_mask(
359
+ attention_mask: Optional[torch.Tensor],
360
+ *,
361
+ sliding_window: int,
362
+ ) -> Optional[torch.Tensor]:
363
+ if not _attention_mask_needs_sliding_window_overlay(attention_mask):
364
+ return attention_mask
365
+ sequence_length = int(attention_mask.shape[-1])
366
+ if sequence_length <= sliding_window:
367
+ return attention_mask
368
+
369
+ positions = torch.arange(sequence_length, device=attention_mask.device)
370
+ outside_window = positions[None, :] <= positions[:, None] - int(sliding_window)
371
+ if not bool(outside_window.any()):
372
+ return attention_mask
373
+
374
+ sliding_window_attention_mask = attention_mask.clone()
375
+ if attention_mask.dtype == torch.bool:
376
+ fill_value = False
377
+ elif torch.is_floating_point(attention_mask):
378
+ fill_value = torch.finfo(attention_mask.dtype).min
379
+ else:
380
+ fill_value = 0
381
+ sliding_window_attention_mask.masked_fill_(
382
+ outside_window[None, None, :, :],
383
+ fill_value,
384
+ )
385
+ return sliding_window_attention_mask
386
+
387
+
388
+ def _layer_uses_sliding_window_attention(
389
+ config: LaneformerTPConfig,
390
+ layer_index: int,
391
+ ) -> bool:
392
+ sliding_window = getattr(config, "sliding_window", None)
393
+ if sliding_window is None or int(sliding_window) <= 0:
394
+ return False
395
+
396
+ swa_layers = getattr(config, "swa_layers", None)
397
+ if swa_layers is not None:
398
+ return layer_index in {int(layer) for layer in swa_layers}
399
+
400
+ layer_types = getattr(config, "layer_types", None)
401
+ if isinstance(layer_types, (list, tuple)) and layer_index < len(layer_types):
402
+ return layer_types[layer_index] == "sliding_attention"
403
+
404
+ sliding_window_n_layers = getattr(config, "sliding_window_n_layers", None)
405
+ if sliding_window_n_layers is not None:
406
+ return layer_index < int(sliding_window_n_layers)
407
+
408
+ return True
409
+
410
+
411
+ def _layer_attention_masks_from_provided_mask(
412
+ config: LaneformerTPConfig,
413
+ attention_mask: Optional[torch.Tensor],
414
+ ) -> Optional[list[Optional[torch.Tensor]]]:
415
+ if not _attention_mask_needs_sliding_window_overlay(attention_mask):
416
+ return None
417
+
418
+ sliding_window = getattr(config, "sliding_window", None)
419
+ if sliding_window is None or int(sliding_window) <= 0:
420
+ return [attention_mask] * config.num_hidden_layers
421
+
422
+ sliding_window_attention_mask = _apply_sliding_window_to_attention_mask(
423
+ attention_mask,
424
+ sliding_window=int(sliding_window),
425
+ )
426
+ return [
427
+ sliding_window_attention_mask
428
+ if _layer_uses_sliding_window_attention(config, layer_id)
429
+ else attention_mask
430
+ for layer_id in range(config.num_hidden_layers)
431
+ ]
432
+
433
+
434
+ class ReduceMode(Enum):
435
+ NO_REDUCE = "no_reduce"
436
+ PRESENT = "present"
437
+ PAST = "past"
438
+
439
+
440
+ class LaneModule:
441
+ _NO_REDUCE_MODE = 0
442
+ _PRESENT_MODE = 1
443
+ _PAST_MODE = 2
444
+
445
+ def __init__(self, no_reduce_scale: float, reduce_mode: ReduceMode):
446
+ super().__init__()
447
+ self.no_reduce_scale = no_reduce_scale
448
+ self.reduce_mode = reduce_mode
449
+ if reduce_mode is ReduceMode.NO_REDUCE:
450
+ self.reduce_mode_code = self._NO_REDUCE_MODE
451
+ elif reduce_mode is ReduceMode.PRESENT:
452
+ self.reduce_mode_code = self._PRESENT_MODE
453
+ elif reduce_mode is ReduceMode.PAST:
454
+ self.reduce_mode_code = self._PAST_MODE
455
+ else:
456
+ raise ValueError(f"Unknown reduce mode: {reduce_mode}")
457
+
458
+ def reduce_lanes(self, x: torch.Tensor, past: torch.Tensor | None) -> torch.Tensor:
459
+ if self.reduce_mode_code == self._NO_REDUCE_MODE:
460
+ return x * self.no_reduce_scale
461
+ elif self.reduce_mode_code == self._PRESENT_MODE:
462
+ return x.sum(dim=2, keepdim=True)
463
+ elif self.reduce_mode_code == self._PAST_MODE:
464
+ assert past is not None
465
+ sum_past = torch.sum(past, dim=-2, keepdim=True) - past
466
+ return x + sum_past
467
+ else:
468
+ raise ValueError(f"Unknown reduce mode code: {self.reduce_mode_code}")
469
+
470
+
471
+ class LaneformerAttention(LaneModule, nn.Module):
472
+ def __init__(
473
+ self,
474
+ config: LaneformerTPConfig,
475
+ layer_idx: int,
476
+ reduce_mode: ReduceMode = ReduceMode.PRESENT,
477
+ ):
478
+ super().__init__(
479
+ no_reduce_scale=math.sqrt(config.num_lanes), reduce_mode=reduce_mode
480
+ )
481
+ self.config = config
482
+ self.layer_idx = layer_idx
483
+ self.n_heads = config.num_attention_heads
484
+ self.num_lanes = config.num_lanes
485
+ self.n_kv_heads = (
486
+ config.num_attention_heads
487
+ if config.num_key_value_heads is None
488
+ else config.num_key_value_heads
489
+ )
490
+ self.n_rep = config.num_attention_heads // self.n_kv_heads
491
+ self.head_dim = config.hidden_size // config.num_attention_heads
492
+ # Scaling & causal flag for backend attention APIs
493
+ self.scaling = self.head_dim**-0.5
494
+ self.is_causal = True # decoder-only model
495
+ self.num_key_value_groups = self.n_rep
496
+ self.attention_dropout = getattr(config, "attention_dropout", 0.0)
497
+ self.wq = LaneRowLinear(
498
+ in_features=config.hidden_size,
499
+ out_features=self.n_heads * self.head_dim,
500
+ num_lanes=config.num_lanes,
501
+ )
502
+ self.wk = LaneRowLinear(
503
+ in_features=config.hidden_size,
504
+ out_features=self.n_kv_heads * self.head_dim,
505
+ num_lanes=config.num_lanes,
506
+ )
507
+ self.wv = LaneRowLinear(
508
+ in_features=config.hidden_size,
509
+ out_features=self.n_kv_heads * self.head_dim,
510
+ num_lanes=config.num_lanes,
511
+ )
512
+ self.wo = LaneColumnLinear(
513
+ in_features=self.n_heads * self.head_dim,
514
+ out_features=config.hidden_size,
515
+ num_lanes=config.num_lanes,
516
+ )
517
+
518
+ def forward(
519
+ self,
520
+ x: torch.Tensor,
521
+ freqs_cis: torch.Tensor,
522
+ attention_mask: Optional[torch.Tensor],
523
+ *,
524
+ past_key_values: Optional[Cache] = None,
525
+ cache_position: Optional[torch.LongTensor] = None,
526
+ **kwargs,
527
+ ):
528
+ """
529
+ Forward pass of the attention module.
530
+
531
+ Args:
532
+ x (torch.Tensor): Input tensor (B, S, L, D)
533
+ freqs_cis (torch.Tensor): Precomputed frequency tensor.
534
+
535
+ Returns:
536
+ torch.Tensor: Output tensor after attention (B, S, L, D)
537
+
538
+ """
539
+ bs, seqlen, _, _ = x.shape
540
+
541
+ xq, xk, xv = self.wq(x), self.wk(x), self.wv(x)
542
+ xq = xq.reshape(bs, seqlen, -1, self.head_dim)
543
+ # (B, T, L, n_kv_heads / L, head_dim)
544
+ xk = xk.reshape(bs, seqlen, -1, self.head_dim)
545
+ # (B, T, L, n_kv_heads / L, head_dim)
546
+ xv = xv.reshape(bs, seqlen, -1, self.head_dim)
547
+
548
+ xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs_cis)
549
+ xq = xq.transpose(1, 2) # (B, n_heads, T, head_dim)
550
+ xk = xk.transpose(1, 2) # (B, n_kv_heads, T, head_dim)
551
+ xv = xv.transpose(1, 2) # (B, n_kv_heads, T, head_dim)
552
+
553
+ # Cache update BEFORE replication
554
+ if past_key_values is not None:
555
+ # sin and cos are specific to RoPE models; cache_position needed for the static cache
556
+ cache_kwargs = {"sin": None, "cos": None, "cache_position": cache_position}
557
+ xk, xv = past_key_values.update(xk, xv, self.layer_idx, cache_kwargs)
558
+
559
+ attention_interface = _attention_interface(self.config)
560
+ output, _ = attention_interface(
561
+ self,
562
+ query=xq,
563
+ key=xk,
564
+ value=xv,
565
+ attention_mask=attention_mask,
566
+ scaling=self.scaling,
567
+ dropout=0.0 if not self.training else self.attention_dropout,
568
+ **kwargs,
569
+ )
570
+
571
+ output = output.contiguous().view(
572
+ bs,
573
+ seqlen,
574
+ self.num_lanes,
575
+ self.n_heads * self.head_dim // self.num_lanes,
576
+ )
577
+ output = self.wo(output)
578
+ return output
579
+
580
+
581
+ class LaneformerMLP(LaneModule, nn.Module):
582
+ def __init__(
583
+ self, config: LaneformerTPConfig, reduce_mode: ReduceMode = ReduceMode.PRESENT
584
+ ):
585
+ super().__init__(
586
+ no_reduce_scale=math.sqrt(config.num_lanes), reduce_mode=reduce_mode
587
+ )
588
+ ffn_dim = config.intermediate_size
589
+ dim = config.hidden_size
590
+ num_lanes = config.num_lanes
591
+
592
+ self.w1 = LaneRowLinear(dim, ffn_dim, num_lanes=num_lanes)
593
+ self.w2 = LaneColumnLinear(ffn_dim, dim, num_lanes=num_lanes)
594
+ self.w3 = LaneRowLinear(dim, ffn_dim, num_lanes=num_lanes)
595
+
596
+ def forward(self, x):
597
+ return self.w2(F.silu(self.w1(x)) * self.w3(x))
598
+
599
+
600
+ class LaneformerDecoderLayer(nn.Module):
601
+ def __init__(
602
+ self,
603
+ config: LaneformerTPConfig,
604
+ layer_idx: int,
605
+ attention_reduce_mode: ReduceMode,
606
+ mlp_reduce_mode: ReduceMode,
607
+ broadcast_attention_to_future: bool,
608
+ broadcast_mlp_to_future: bool,
609
+ ):
610
+ super().__init__()
611
+ self.n_heads = config.num_attention_heads
612
+ self.dim = config.hidden_size
613
+ self.attention = LaneformerAttention(
614
+ config, layer_idx=layer_idx, reduce_mode=attention_reduce_mode
615
+ )
616
+ self.feed_forward = LaneformerMLP(config, reduce_mode=mlp_reduce_mode)
617
+ norm_fun = (
618
+ nn.RMSNorm
619
+ if config.replicated_rmsn_scale
620
+ else partial(LaneRMSNorm, num_lanes=config.num_lanes)
621
+ )
622
+ self.attention_norm = norm_fun(config.hidden_size, eps=config.norm_eps)
623
+ self.ffn_norm = norm_fun(config.hidden_size, eps=config.norm_eps)
624
+ self.num_lanes = config.num_lanes
625
+ self.broadcast_attention_to_future = broadcast_attention_to_future
626
+ self.broadcast_mlp_to_future = broadcast_mlp_to_future
627
+
628
+ def forward(
629
+ self,
630
+ hidden_states: torch.Tensor,
631
+ attention_mask: Optional[torch.Tensor] = None,
632
+ position_ids: Optional[torch.LongTensor] = None,
633
+ past_key_values: Optional[Cache] = None,
634
+ past_attention: Optional[torch.Tensor] = None,
635
+ past_mlp: Optional[torch.Tensor] = None,
636
+ use_cache: Optional[bool] = False,
637
+ cache_position: Optional[torch.LongTensor] = None,
638
+ freqs_cis: Optional[torch.Tensor] = None,
639
+ **kwargs,
640
+ ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
641
+ residual = hidden_states
642
+ hidden_states = self.attention_norm(hidden_states)
643
+ hidden_states = self.attention(
644
+ x=hidden_states,
645
+ freqs_cis=freqs_cis,
646
+ attention_mask=attention_mask,
647
+ position_ids=position_ids,
648
+ past_key_values=past_key_values,
649
+ use_cache=use_cache,
650
+ cache_position=cache_position,
651
+ **kwargs,
652
+ )
653
+ future_attention = hidden_states if self.broadcast_attention_to_future else None
654
+ hidden_states = self.attention.reduce_lanes(hidden_states, past=past_attention)
655
+ hidden_states = residual + hidden_states
656
+
657
+ residual = hidden_states
658
+ hidden_states = self.ffn_norm(hidden_states)
659
+ hidden_states = self.feed_forward(hidden_states)
660
+ future_mlp = hidden_states if self.broadcast_mlp_to_future else None
661
+ hidden_states = self.feed_forward.reduce_lanes(hidden_states, past=past_mlp)
662
+ hidden_states = residual + hidden_states
663
+ return hidden_states, future_attention, future_mlp
664
+
665
+
666
+ # ============================================================
667
+ # Backbone & HF wrappers
668
+ # ============================================================
669
+ class LaneformerPreTrainedModel(PreTrainedModel):
670
+ config_class = LaneformerTPConfig
671
+ config: LaneformerTPConfig
672
+ base_model_prefix = "model"
673
+ supports_gradient_checkpointing = False
674
+ _no_split_modules = [
675
+ "LaneformerTPModel",
676
+ "LaneformerDecoderLayer",
677
+ "LaneformerAttention",
678
+ "LaneformerMLP",
679
+ ]
680
+ _skip_keys_device_placement = ["past_key_values"]
681
+ # Advertise support for Transformers attention backends (vLLM / flash / sdpa routing)
682
+ _supports_attention_backend = True
683
+ _supports_sdpa = True
684
+ _supports_flex_attn = True
685
+
686
+
687
+ class LaneformerTPModel(LaneformerPreTrainedModel):
688
+ def __init__(self, config: LaneformerTPConfig):
689
+ super().__init__(config)
690
+ self.padding_idx = config.pad_token_id
691
+ self.config = config
692
+ self.vocab_size = config.vocab_size
693
+ self.n_layers = config.num_hidden_layers
694
+ self.eos_id = config.eos_token_id
695
+
696
+ self.num_lanes = config.num_lanes
697
+ self.broadcast_delay = config.broadcast_delay
698
+ self.use_attention_comm = getattr(config, "use_attention_comm", config.use_comm)
699
+ self.use_mlp_comm = getattr(config, "use_mlp_comm", config.use_comm)
700
+ self.use_early_comm = config.use_early_comm
701
+ self.pre_norm_lane_agg = config.pre_norm_lane_agg
702
+ self.lm_head_type = config.lm_head_type
703
+ self.replicated_rmsn_scale = config.replicated_rmsn_scale
704
+ self.swa_layers = set(config.swa_layers)
705
+ self.rope_dim = config.hidden_size // config.num_attention_heads
706
+ self.rope_theta = config.rope_theta
707
+ self.rope_scaling_args = _rope_scaling_from_config(config)
708
+
709
+ self.tok_embeddings = nn.Embedding(
710
+ config.vocab_size, config.hidden_size, self.padding_idx
711
+ )
712
+
713
+ # Build lane blocks
714
+ self.layers = nn.ModuleList()
715
+ for layer_id in range(config.num_hidden_layers):
716
+ if self.broadcast_delay == 0 or layer_id < self.broadcast_delay:
717
+ attention_reduce_mode = (
718
+ ReduceMode.PRESENT if self.use_early_comm else ReduceMode.NO_REDUCE
719
+ )
720
+ mlp_reduce_mode = (
721
+ ReduceMode.PRESENT if self.use_early_comm else ReduceMode.NO_REDUCE
722
+ )
723
+ else:
724
+ attention_reduce_mode = (
725
+ ReduceMode.NO_REDUCE
726
+ if not (self.use_attention_comm)
727
+ else ReduceMode.PAST
728
+ )
729
+ mlp_reduce_mode = (
730
+ ReduceMode.NO_REDUCE if not (self.use_mlp_comm) else ReduceMode.PAST
731
+ )
732
+
733
+ broadcast_attention_to_future = (
734
+ config.num_hidden_layers - self.broadcast_delay > layer_id
735
+ ) and self.use_attention_comm
736
+ broadcast_mlp_to_future = (
737
+ config.num_hidden_layers - self.broadcast_delay > layer_id
738
+ ) and self.use_mlp_comm
739
+
740
+ self.layers.append(
741
+ LaneformerDecoderLayer(
742
+ config=config,
743
+ layer_idx=layer_id,
744
+ attention_reduce_mode=attention_reduce_mode,
745
+ mlp_reduce_mode=mlp_reduce_mode,
746
+ broadcast_attention_to_future=broadcast_attention_to_future,
747
+ broadcast_mlp_to_future=broadcast_mlp_to_future,
748
+ )
749
+ )
750
+ if self.pre_norm_lane_agg and not self.lm_head_type == "replicate":
751
+ raise ValueError(
752
+ "pre_norm_lane_agg is only supported with lm_head_type='replicate'"
753
+ )
754
+
755
+ norm_fun = (
756
+ nn.RMSNorm
757
+ if config.replicated_rmsn_scale or config.pre_norm_lane_agg
758
+ else partial(LaneRMSNorm, num_lanes=self.num_lanes)
759
+ )
760
+
761
+ self.norm = norm_fun(config.hidden_size, eps=config.norm_eps)
762
+ self.gradient_checkpointing = False
763
+ self.post_init()
764
+
765
+ # Required by vllm integration
766
+ def get_input_embeddings(self):
767
+ return self.tok_embeddings
768
+
769
+ # Required by vllm integration
770
+ def set_input_embeddings(self, new_emb):
771
+ self.tok_embeddings = new_emb
772
+
773
+ def _compute_freqs_cis(self, position_ids: torch.Tensor) -> torch.Tensor:
774
+ return freqs_cis_for_position_ids(
775
+ position_ids,
776
+ self.rope_dim,
777
+ self.rope_theta,
778
+ self.rope_scaling_args,
779
+ )
780
+
781
+ def forward(
782
+ self,
783
+ input_ids: Optional[torch.LongTensor] = None,
784
+ attention_mask: Optional[torch.Tensor] = None,
785
+ position_ids: Optional[torch.LongTensor] = None,
786
+ past_key_values: Optional[Cache] = None,
787
+ inputs_embeds: Optional[torch.Tensor] = None,
788
+ cache_position: Optional[torch.LongTensor] = None,
789
+ use_cache: Optional[bool] = None,
790
+ **kwargs,
791
+ ):
792
+ if (input_ids is None) ^ (inputs_embeds is not None):
793
+ raise ValueError(
794
+ "You must specify exactly one of input_ids or inputs_embeds"
795
+ )
796
+
797
+ if inputs_embeds is None:
798
+ inputs_embeds: torch.Tensor = self.tok_embeddings(input_ids)
799
+
800
+ use_cache = use_cache if use_cache is not None else self.config.use_cache
801
+ past_key_values_for_forward = past_key_values if use_cache else None
802
+
803
+ if use_cache and past_key_values_for_forward is None:
804
+ past_key_values_for_forward = DynamicCache(config=self.config)
805
+
806
+ if cache_position is None:
807
+ past_seen_tokens = (
808
+ past_key_values_for_forward.get_seq_length()
809
+ if past_key_values_for_forward is not None
810
+ else 0
811
+ )
812
+ cache_position: torch.Tensor = torch.arange(
813
+ past_seen_tokens,
814
+ past_seen_tokens + inputs_embeds.shape[1],
815
+ device=inputs_embeds.device,
816
+ )
817
+
818
+ if position_ids is None:
819
+ position_ids = cache_position.unsqueeze(0)
820
+
821
+ layer_types = list(getattr(self.config, "layer_types", []))
822
+ if len(layer_types) != self.config.num_hidden_layers:
823
+ layer_types = [
824
+ "sliding_attention" if layer_id in self.swa_layers else "full_attention"
825
+ for layer_id in range(self.config.num_hidden_layers)
826
+ ]
827
+ unknown_layer_types = set(layer_types) - {"full_attention", "sliding_attention"}
828
+ if unknown_layer_types:
829
+ raise ValueError(
830
+ f"Unknown attention layer types: {sorted(unknown_layer_types)}"
831
+ )
832
+
833
+ has_sliding_layers = "sliding_attention" in layer_types
834
+ if self.config.sliding_window is None and (
835
+ self.swa_layers or has_sliding_layers
836
+ ):
837
+ raise ValueError("sliding_window must be set for layers in swa_layers")
838
+
839
+ causal_mask_mapping = {}
840
+ if "full_attention" in layer_types:
841
+ causal_mask_mapping["full_attention"] = _call_attention_mask_factory(
842
+ create_causal_mask,
843
+ uses_inputs_embeds=_CAUSAL_MASK_USES_INPUTS_EMBEDS,
844
+ config=self.config,
845
+ inputs_embeds=inputs_embeds,
846
+ attention_mask=attention_mask,
847
+ cache_position=cache_position,
848
+ past_key_values=past_key_values_for_forward,
849
+ position_ids=position_ids,
850
+ )
851
+
852
+ if has_sliding_layers:
853
+ sliding_attention_mask = _apply_sliding_window_to_attention_mask(
854
+ attention_mask,
855
+ sliding_window=int(self.config.sliding_window),
856
+ )
857
+ causal_mask_mapping["sliding_attention"] = _call_attention_mask_factory(
858
+ create_sliding_window_causal_mask,
859
+ uses_inputs_embeds=_SLIDING_MASK_USES_INPUTS_EMBEDS,
860
+ config=self.config,
861
+ inputs_embeds=inputs_embeds,
862
+ attention_mask=sliding_attention_mask,
863
+ cache_position=cache_position,
864
+ past_key_values=past_key_values_for_forward,
865
+ position_ids=position_ids,
866
+ )
867
+ freqs_cis = self._compute_freqs_cis(position_ids).unsqueeze(-2)
868
+
869
+ hidden_states = inputs_embeds
870
+ hidden_states = hidden_states[:, :, None, :].expand(-1, -1, self.num_lanes, -1)
871
+ past_attentions = []
872
+ past_mlps = []
873
+ for i in range(self.config.num_hidden_layers):
874
+ if self.broadcast_delay == 0 or i < self.broadcast_delay:
875
+ past_attention = None
876
+ past_mlp = None
877
+ else:
878
+ past_attention = past_attentions[i - self.broadcast_delay]
879
+ past_mlp = past_mlps[i - self.broadcast_delay]
880
+ hidden_states, future_attention, future_mlp = self.layers[i](
881
+ hidden_states=hidden_states,
882
+ attention_mask=causal_mask_mapping[layer_types[i]],
883
+ position_ids=position_ids,
884
+ past_key_values=past_key_values_for_forward,
885
+ past_attention=past_attention,
886
+ past_mlp=past_mlp,
887
+ use_cache=use_cache,
888
+ cache_position=cache_position,
889
+ freqs_cis=freqs_cis,
890
+ **kwargs,
891
+ )
892
+ past_attentions.append(future_attention)
893
+ past_mlps.append(future_mlp)
894
+
895
+ if self.pre_norm_lane_agg:
896
+ # (B, S, L, D) -> (B, S, D)
897
+ hidden_states = hidden_states.sum(dim=-2)
898
+ hidden_states = self.norm(hidden_states)
899
+ elif self.lm_head_type == "replicate": # and naturally not pre_lane_agg
900
+ # (B, S, L, D) -> (B, S, D)
901
+ hidden_states = self.norm(hidden_states)
902
+ hidden_states = hidden_states.mean(dim=-2)
903
+ else:
904
+ # (B, S, L, D)
905
+ hidden_states = self.norm(hidden_states)
906
+
907
+ return BaseModelOutputWithPast(
908
+ last_hidden_state=hidden_states,
909
+ past_key_values=past_key_values_for_forward if use_cache else None,
910
+ )
911
+
912
+
913
+ @auto_docstring
914
+ class LaneformerTPForCausalLM(LaneformerPreTrainedModel, GenerationMixin):
915
+ _pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
916
+
917
+ def __init__(self, config: LaneformerTPConfig):
918
+ super().__init__(config)
919
+ if config.tie_word_embeddings:
920
+ raise ValueError("tie_word_embeddings is not supported for LaneformerTP")
921
+ self.model = LaneformerTPModel(config)
922
+ self.vocab_size = config.vocab_size
923
+ self.lm_head_type = config.lm_head_type
924
+ if self.lm_head_type == "replicate":
925
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
926
+ elif self.lm_head_type == "lane":
927
+ self.lm_head = LaneLMHead(
928
+ in_features=config.hidden_size,
929
+ out_features=config.vocab_size,
930
+ num_lanes=config.num_lanes,
931
+ )
932
+ elif self.lm_head_type == "vocab_parallel":
933
+ self.lm_head = LaneRowLinear(
934
+ in_features=config.hidden_size,
935
+ out_features=config.vocab_size,
936
+ num_lanes=config.num_lanes,
937
+ )
938
+
939
+ # Initialize weights and apply final processing
940
+ self.post_init()
941
+
942
+ def get_output_embeddings(self):
943
+ return self.lm_head
944
+
945
+ def set_output_embeddings(self, new_embeddings):
946
+ self.lm_head = new_embeddings
947
+
948
+ def resize_token_embeddings(
949
+ self,
950
+ new_num_tokens: Optional[int] = None,
951
+ pad_to_multiple_of: Optional[int] = None,
952
+ mean_resizing: bool = True,
953
+ ) -> nn.Embedding:
954
+ if self.lm_head_type != "replicate" and (
955
+ new_num_tokens is not None or pad_to_multiple_of is not None
956
+ ):
957
+ raise NotImplementedError(
958
+ "resize_token_embeddings is only supported for "
959
+ "lm_head_type='replicate'"
960
+ )
961
+ return super().resize_token_embeddings(
962
+ new_num_tokens=new_num_tokens,
963
+ pad_to_multiple_of=pad_to_multiple_of,
964
+ mean_resizing=mean_resizing,
965
+ )
966
+
967
+ @can_return_tuple
968
+ @auto_docstring
969
+ def forward(
970
+ self,
971
+ input_ids: Optional[torch.LongTensor] = None,
972
+ attention_mask: Optional[torch.Tensor] = None,
973
+ position_ids: Optional[torch.LongTensor] = None,
974
+ past_key_values: Optional[Cache] = None,
975
+ inputs_embeds: Optional[torch.FloatTensor] = None,
976
+ labels: Optional[torch.LongTensor] = None,
977
+ use_cache: Optional[bool] = None,
978
+ logits_to_keep: Union[int, torch.Tensor] = 0,
979
+ **kwargs: Unpack[TransformersKwargs],
980
+ ) -> CausalLMOutputWithPast:
981
+ r"""
982
+ Example with a tiny randomly initialized LaneformerTP model:
983
+
984
+ ```python
985
+ >>> import torch
986
+ >>> from torchtitan.models.laneformer_tp.hf import (
987
+ ... LaneformerTPConfig,
988
+ ... LaneformerTPForCausalLM,
989
+ ... )
990
+ >>> config = LaneformerTPConfig(
991
+ ... hidden_size=16,
992
+ ... num_hidden_layers=2,
993
+ ... num_attention_heads=4,
994
+ ... num_key_value_heads=2,
995
+ ... intermediate_size=32,
996
+ ... vocab_size=64,
997
+ ... num_lanes=2,
998
+ ... )
999
+ >>> model = LaneformerTPForCausalLM(config)
1000
+ >>> input_ids = torch.tensor([[1, 2, 3]])
1001
+ >>> logits = model(input_ids=input_ids, use_cache=False).logits
1002
+ >>> logits.shape
1003
+ torch.Size([1, 3, 64])
1004
+ ```"""
1005
+ outputs: BaseModelOutputWithPast = self.model(
1006
+ input_ids=input_ids,
1007
+ attention_mask=attention_mask,
1008
+ position_ids=position_ids,
1009
+ past_key_values=past_key_values,
1010
+ inputs_embeds=inputs_embeds,
1011
+ use_cache=use_cache,
1012
+ **kwargs,
1013
+ )
1014
+
1015
+ hidden_states = outputs.last_hidden_state
1016
+ # Only compute necessary logits, and do not upcast them to float if
1017
+ # we are not computing the loss.
1018
+ slice_indices = (
1019
+ slice(-logits_to_keep, None)
1020
+ if isinstance(logits_to_keep, int)
1021
+ else logits_to_keep
1022
+ )
1023
+ if self.lm_head_type == "replicate":
1024
+ logits = self.lm_head(hidden_states[:, slice_indices, :])
1025
+ else:
1026
+ logits = self.lm_head(hidden_states[:, slice_indices, :, :])
1027
+ if self.lm_head_type == "vocab_parallel":
1028
+ # (B, S, L, D) -> (B, S, D)
1029
+ B, S, L, D = logits.shape
1030
+ logits = logits.reshape(B, S, L * D)
1031
+
1032
+ loss = None
1033
+ if labels is not None:
1034
+ loss = self.loss_function(
1035
+ logits=logits,
1036
+ labels=labels,
1037
+ vocab_size=self.config.vocab_size,
1038
+ **kwargs,
1039
+ )
1040
+
1041
+ return CausalLMOutputWithPast(
1042
+ loss=loss,
1043
+ logits=logits,
1044
+ past_key_values=outputs.past_key_values,
1045
+ hidden_states=outputs.hidden_states,
1046
+ attentions=outputs.attentions,
1047
+ )
special_tokens_map.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "</s>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": "</s>",
17
+ "unk_token": {
18
+ "content": "<unk>",
19
+ "lstrip": false,
20
+ "normalized": false,
21
+ "rstrip": false,
22
+ "single_word": false
23
+ }
24
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_bos_token": true,
3
+ "add_eos_token": false,
4
+ "add_prefix_space": null,
5
+ "added_tokens_decoder": {
6
+ "0": {
7
+ "content": "<unk>",
8
+ "lstrip": false,
9
+ "normalized": false,
10
+ "rstrip": false,
11
+ "single_word": false,
12
+ "special": true
13
+ },
14
+ "1": {
15
+ "content": "<s>",
16
+ "lstrip": false,
17
+ "normalized": false,
18
+ "rstrip": false,
19
+ "single_word": false,
20
+ "special": true
21
+ },
22
+ "2": {
23
+ "content": "</s>",
24
+ "lstrip": false,
25
+ "normalized": false,
26
+ "rstrip": false,
27
+ "single_word": false,
28
+ "special": true
29
+ }
30
+ },
31
+ "bos_token": "<s>",
32
+ "clean_up_tokenization_spaces": false,
33
+ "eos_token": "</s>",
34
+ "extra_special_tokens": {},
35
+ "legacy": false,
36
+ "model_max_length": 1000000000000000019884624838656,
37
+ "pad_token": "</s>",
38
+ "padding_side": "right",
39
+ "sp_model_kwargs": {},
40
+ "tokenizer_class": "LlamaTokenizer",
41
+ "unk_token": "<unk>",
42
+ "use_default_system_prompt": false
43
+ }
torchtitan_metadata.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "format": "torchtitan_laneformer_tp_metadata",
3
+ "version": 1,
4
+ "model_type": "laneformer_tp",
5
+ "torchtitan_model_args": {
6
+ "attn_mask_type": "block_causal",
7
+ "depth_init": true,
8
+ "multiple_of": 32,
9
+ "attn_type": "flex"
10
+ },
11
+ "deprecated_config_fields": {
12
+ "sliding_window_n_layers": 10,
13
+ "use_comm": true
14
+ }
15
+ }