yujiepan commited on
Commit
ff4b581
·
verified ·
1 Parent(s): bc7965d

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
.meta.json ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "source_model": {
3
+ "name": "nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16",
4
+ "commit_id": "b366b87f762ea334ba3eb55912031baba1515810"
5
+ },
6
+ "env": {
7
+ "python": "3.12.13",
8
+ "packages": {
9
+ "huggingface_hub": "2.3.0",
10
+ "safetensors": "0.8.0",
11
+ "tokenizers": "0.23.3",
12
+ "torch": "2.13.0+cu126",
13
+ "transformers": "5.20.2"
14
+ },
15
+ "cuda": "12.6"
16
+ },
17
+ "environments": {
18
+ "creation": {
19
+ "python": "3.12.13",
20
+ "packages": {
21
+ "huggingface_hub": "2.3.0",
22
+ "safetensors": "0.8.0",
23
+ "tokenizers": "0.23.3",
24
+ "torch": "2.13.0+cu126",
25
+ "transformers": "5.20.2"
26
+ },
27
+ "cuda": "12.6"
28
+ },
29
+ "vllm-offline": {
30
+ "python": "3.12.13",
31
+ "packages": {
32
+ "flashinfer-python": "0.7.0.post1",
33
+ "huggingface_hub": "2.3.0",
34
+ "safetensors": "0.8.0",
35
+ "tokenizers": "0.23.3",
36
+ "torch": "2.13.0+cu130",
37
+ "transformers": "5.19.0",
38
+ "vllm": "0.32.0"
39
+ },
40
+ "cuda": "13.0"
41
+ },
42
+ "vllm-serving": {
43
+ "python": "3.12.13",
44
+ "packages": {
45
+ "flashinfer-python": "0.7.0.post1",
46
+ "huggingface_hub": "2.3.0",
47
+ "safetensors": "0.8.0",
48
+ "tokenizers": "0.23.3",
49
+ "torch": "2.13.0+cu130",
50
+ "transformers": "5.19.0",
51
+ "vllm": "0.32.0"
52
+ },
53
+ "cuda": "13.0"
54
+ },
55
+ "vllm-verify": {
56
+ "python": "3.12.13",
57
+ "packages": {
58
+ "flashinfer-python": "0.7.0.post1",
59
+ "huggingface_hub": "2.3.0",
60
+ "safetensors": "0.8.0",
61
+ "tokenizers": "0.23.3",
62
+ "torch": "2.13.0+cu130",
63
+ "transformers": "5.19.0",
64
+ "vllm": "0.32.0"
65
+ },
66
+ "cuda": "13.0"
67
+ }
68
+ }
69
+ }
README.md ADDED
@@ -0,0 +1,899 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: vllm
3
+ pipeline_tag: text-generation
4
+ base_model:
5
+ - nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16
6
+ ---
7
+
8
+ This tiny model is randomly initialized for debugging using [nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16](https://huggingface.co/nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16).
9
+
10
+ Dory preserves two recurrent passes, input reinjection, nGPT residuals,
11
+ SWA/full attention, and untied BF16 token matrices. The pinned official vLLM
12
+ implementation is included with tensor-parallel vector loading and distributed
13
+ nGPT normalization. Transformers has no Dory model implementation or source
14
+ auto_map; checkpoint generation follows the official source tensor schema.
15
+
16
+ | Feature | Source | Tiny |
17
+ |---|---|---|
18
+ | Checkpoint tensor elements | 3,975,229,440 BF16 | 689,248 BF16 |
19
+ | Safetensors weight files | 7,950,515,472 bytes (model.safetensors) | 1,412,480 bytes (model.safetensors) |
20
+ | Input / recurrent / output sublayers | 16 / 40 / 16 | 16 / 16 / 16 |
21
+ | Recurrent passes | 2 | 2 |
22
+ | SWA/full cycle | 3 SWA+MLP pairs, then full+MLP | Same; two cycles per partition |
23
+ | Vocabulary / embedding tying | 131,072 / false | Same |
24
+ | Hidden width / MLP width | 2,560 / 7,168 | 2 / 32 |
25
+ | Q heads / KV heads / head dimension | 16 / 4 / 256 | 4 / 1 / 32 |
26
+ | Checkpoint precision | BF16 | Same |
27
+
28
+ Install the included runtime once with `pip install --no-deps <snapshot directory>`
29
+ before running the offline example. It registers Dory in every vLLM worker.
30
+ The native vLLM sampler avoids FlashInfer sampling JIT; attention uses FlashAttention.
31
+ Width 1 was rejected because scalar nGPT normalization collapses the latent state:
32
+ one and two recurrent passes produced identical final states. Width 2 retains
33
+ continuous recurrent updates; both untied vocabulary matrices keep their source rows.
34
+ TP=1 and TP=4 were validated with English, Chinese and a 1,100-token prompt,
35
+ generating ten tokens each. Both per-loop and last-loop caches and CUDA Graph
36
+ were exercised; TP=1/TP=4 returned identical token IDs with at most 0.000644
37
+ logprob difference. The independent creation and offline snippets passed outside
38
+ the checkout with repository imports blocked.
39
+ The current offline and HTTP serving examples were verified on four NVIDIA H20
40
+ GPUs with TP=4, FlashAttention and CUDA Graph. Both chat requests (English and
41
+ Chinese) and a 1,100-token completion request generated ten tokens with finite
42
+ log probabilities. The CUDA 13.0 test environment used NVIDIA's CUDA compatibility
43
+ libraries on a CUDA 12.6 driver; use a compatible driver/runtime combination.
44
+
45
+ | File path | Size |
46
+ |------|------|
47
+ | model.safetensors | 1.4MB |
48
+
49
+ ### Example usage:
50
+
51
+ - vLLM offline (✅ verified)
52
+
53
+ ```python
54
+ def run_vllm(model_id: str):
55
+ import os
56
+ from pathlib import Path
57
+ from huggingface_hub import snapshot_download
58
+ from transformers import AutoTokenizer
59
+
60
+ # Use vLLM's native sampler; FlashAttention and CUDA Graph remain enabled.
61
+ os.environ.setdefault("VLLM_USE_FLASHINFER_SAMPLER", "0")
62
+ os.environ.setdefault("VLLM_ALLREDUCE_USE_FLASHINFER", "0")
63
+ os.environ.setdefault("VLLM_ALLREDUCE_USE_SYMM_MEM", "0")
64
+ from vllm import LLM, SamplingParams
65
+
66
+ model_id = str(model_id)
67
+ folder = Path(model_id) if Path(model_id).is_dir() else Path(snapshot_download(model_id))
68
+ tokenizer = AutoTokenizer.from_pretrained(folder, trust_remote_code=True)
69
+ prompt = tokenizer.apply_chat_template(
70
+ [{"role": "user", "content": "Hello"}], tokenize=False, add_generation_prompt=True
71
+ )
72
+ llm = LLM(
73
+ model=str(folder),
74
+ trust_remote_code=True,
75
+ tensor_parallel_size=4,
76
+ max_model_len=2048,
77
+ max_num_batched_tokens=256,
78
+ max_num_seqs=4,
79
+ gpu_memory_utilization=0.2,
80
+ disable_custom_all_reduce=True,
81
+ compilation_config={"cudagraph_capture_sizes": [1, 2, 4, 8]},
82
+ )
83
+ try:
84
+ print(llm)
85
+ print(llm.generate([prompt], SamplingParams(temperature=0, max_tokens=10, ignore_eos=True))[0].outputs[0].text)
86
+ finally:
87
+ llm.llm_engine.engine_core.shutdown(timeout=30)
88
+
89
+
90
+ if __name__ == "__main__":
91
+ run_vllm(model_id="tiny-random/dory-1.0")
92
+ ```
93
+
94
+ - vLLM serving (✅ verified)
95
+
96
+ Download `tiny-random/dory-1.0` and install its included runtime before starting the server.
97
+
98
+ ```bash
99
+ export VLLM_USE_FLASHINFER_SAMPLER=0 VLLM_ALLREDUCE_USE_FLASHINFER=0 VLLM_ALLREDUCE_USE_SYMM_MEM=0
100
+ python - <<'PY'
101
+ from huggingface_hub import snapshot_download
102
+ snapshot_download("tiny-random/dory-1.0", local_dir="dory-1.0")
103
+ PY
104
+ pip install --no-deps ./dory-1.0
105
+
106
+ vllm serve ./dory-1.0 \
107
+ --trust-remote-code \
108
+ --tensor-parallel-size 4 \
109
+ --hf-overrides '{"n_recurrent_loops": 2, "recurrent_kv_cache_mode": "per_loop"}' \
110
+ --max-model-len 2048 \
111
+ --max-num-batched-tokens 256 \
112
+ --max-num-seqs 4 \
113
+ --gpu-memory-utilization 0.2 \
114
+ --disable-custom-all-reduce \
115
+ --compilation-config '{"cudagraph_capture_sizes": [1, 2, 4, 8]}'
116
+ ```
117
+
118
+ ### Codes to create this repo:
119
+
120
+ <details><summary>Click to expand</summary>
121
+
122
+ ```python
123
+ def create_model(source_model_id: str, source_revision: str, save_folder: str):
124
+ import json
125
+ import urllib.request
126
+ from pathlib import Path
127
+
128
+ import torch
129
+ from huggingface_hub import hf_hub_download
130
+ from safetensors.torch import save_file
131
+
132
+ runtime_revision = "b5007e42b09c3990685fe564a31ae6917394a80b"
133
+ folder = Path(save_folder)
134
+ folder.mkdir(parents=True, exist_ok=True)
135
+ config = json.loads(Path(hf_hub_download(source_model_id, "config.json", revision=source_revision)).read_text())
136
+ # Two complete SWA/SWA/SWA/full cycles in every physical partition.
137
+ config.update(
138
+ hidden_size=2,
139
+ intermediate_size=32,
140
+ num_attention_heads=4,
141
+ num_key_value_heads=1,
142
+ head_dim=32,
143
+ num_hidden_layers=48,
144
+ n_input_layers=16,
145
+ n_recurrent_layers=16,
146
+ n_output_layers=16,
147
+ )
148
+ config["layer_types"] = config["layer_types"][:48]
149
+ config["auto_map"] = {"AutoConfig": "configuration_dory.DoryConfig"}
150
+ (folder / "config.json").write_text(json.dumps(config, indent=2) + "\n")
151
+ for name in (
152
+ "tokenizer.json",
153
+ "tokenizer_config.json",
154
+ "special_tokens_map.json",
155
+ "chat_template.jinja",
156
+ "generation_config.json",
157
+ ):
158
+ (folder / name).write_bytes(Path(hf_hub_download(source_model_id, name, revision=source_revision)).read_bytes())
159
+
160
+ # No Transformers model class or source auto_map exists. Preserve the pinned
161
+ # official checkpoint schema and ship its vLLM runtime with TP adaptations.
162
+ base = f"https://raw.githubusercontent.com/vllm-project/vllm/{runtime_revision}/"
163
+ for remote, local in (
164
+ ("vllm/transformers_utils/configs/dory.py", "configuration_dory.py"),
165
+ ("vllm/model_executor/models/dory.py", "vllm_dory.py"),
166
+ ):
167
+ with urllib.request.urlopen(base + remote) as response:
168
+ code = response.read().decode()
169
+ if local == "vllm_dory.py":
170
+ code = code.replace(
171
+ "from .utils import maybe_prefix", "from vllm.model_executor.models.utils import maybe_prefix"
172
+ )
173
+ code = code.replace(
174
+ "from vllm.distributed import get_tensor_model_parallel_world_size",
175
+ "from vllm.distributed import (get_tensor_model_parallel_world_size, "
176
+ "get_tensor_model_parallel_rank, tensor_model_parallel_all_reduce)",
177
+ )
178
+ code = code.replace(
179
+ "EPS = 1e-6",
180
+ "EPS = 1e-6\n\n"
181
+ "def partition_norm(x):\n"
182
+ " total = tensor_model_parallel_all_reduce(x.float().square().sum(dim=-1, keepdim=True))\n"
183
+ " return (x.float() * torch.rsqrt(total + EPS)).to(x.dtype)\n\n"
184
+ "def load_vector(param, weight):\n"
185
+ " rank = get_tensor_model_parallel_rank()\n"
186
+ " param.data.copy_(weight.narrow(0, rank * param.numel(), param.numel()))\n",
187
+ )
188
+ code = code.replace(
189
+ "self.num_heads = config.num_attention_heads",
190
+ "self.num_heads = config.num_attention_heads // get_tensor_model_parallel_world_size()",
191
+ )
192
+ code = code.replace(
193
+ "self.num_kv_heads = config.num_key_value_heads",
194
+ "self.num_kv_heads = max(1, config.num_key_value_heads // get_tensor_model_parallel_world_size())",
195
+ )
196
+ code = code.replace(
197
+ " self.num_heads,\n self.num_kv_heads,",
198
+ " config.num_attention_heads,\n config.num_key_value_heads,",
199
+ )
200
+ code = code.replace(
201
+ " self.q_size,\n bias=False,",
202
+ " config.num_attention_heads * self.head_dim,\n bias=False,",
203
+ )
204
+ code = code.replace(
205
+ " self.q_size,\n self.hidden_size,",
206
+ " config.num_attention_heads * self.head_dim,\n self.hidden_size,",
207
+ )
208
+ code = code.replace(
209
+ "self.s_gate = nn.Parameter(torch.empty(self.q_size))",
210
+ "self.s_gate = nn.Parameter(torch.empty(self.q_size))\n"
211
+ " self.sqk.weight_loader = self.s_gate.weight_loader = load_vector",
212
+ )
213
+ code = code.replace(
214
+ "self.ffn = config.intermediate_size",
215
+ "self.ffn = config.intermediate_size // get_tensor_model_parallel_world_size()",
216
+ )
217
+ code = code.replace("[self.ffn] * 2", "[config.intermediate_size] * 2")
218
+ code = code.replace(
219
+ " self.ffn,\n config.hidden_size,",
220
+ " config.intermediate_size,\n config.hidden_size,",
221
+ )
222
+ code = code.replace(
223
+ "self.suv_up = nn.Parameter(torch.empty(self.ffn))",
224
+ "self.suv_up = nn.Parameter(torch.empty(self.ffn))\n"
225
+ " self.suv_gate.weight_loader = self.suv_up.weight_loader = load_vector",
226
+ )
227
+ code = code.replace("out = justnorm(out)", "out = partition_norm(out)")
228
+ code = code.replace("m = justnorm(m)", "m = partition_norm(m)")
229
+ code = code.replace(
230
+ " if get_tensor_model_parallel_world_size() != 1:\n"
231
+ ' raise ValueError("Dory currently supports tensor_parallel_size=1 only")\n',
232
+ "",
233
+ )
234
+ code = code.replace(
235
+ " self._check_weight_shape(name, w, shape)\n" " getattr(param,",
236
+ ' if name.endswith((".sqk", ".s_gate")):\n'
237
+ " shape = (self.config.num_attention_heads * self.config.head_dim,)\n"
238
+ ' elif name.endswith((".suv_gate", ".suv_up")):\n'
239
+ " shape = (self.config.intermediate_size,)\n"
240
+ ' elif name.endswith(".g_proj.weight"):\n'
241
+ " shape = (self.config.num_attention_heads * self.config.head_dim, self.config.hidden_size)\n"
242
+ ' elif name.endswith(".o_proj.weight"):\n'
243
+ " shape = (self.config.hidden_size, self.config.num_attention_heads * self.config.head_dim)\n"
244
+ ' elif name.endswith(".down_proj.weight"):\n'
245
+ " shape = (self.config.hidden_size, self.config.intermediate_size)\n"
246
+ " self._check_weight_shape(name, w, shape)\n"
247
+ " getattr(param,",
248
+ )
249
+ assert "tensor_parallel_size=1 only" not in code
250
+ assert code.count("partition_norm(") == 3
251
+ (folder / local).write_text(code)
252
+ # vLLM spawns fresh interpreters. A general plugin registers the model in
253
+ # every process; parent-process ModelRegistry changes alone do not survive.
254
+ (folder / "dory_plugin.py").write_text(
255
+ "def register():\n"
256
+ " from vllm import ModelRegistry\n"
257
+ " ModelRegistry.register_model('DoryForCausalLM', 'vllm_dory:DoryForCausalLM')\n"
258
+ )
259
+ (folder / "pyproject.toml").write_text(
260
+ '[build-system]\nrequires = ["setuptools>=61"]\nbuild-backend = "setuptools.build_meta"\n'
261
+ '[project]\nname = "dory-inference"\nversion = "0.1.0"\n'
262
+ '[project.entry-points."vllm.general_plugins"]\ndory = "dory_plugin:register"\n'
263
+ '[tool.setuptools]\npy-modules = ["dory_plugin", "vllm_dory", "configuration_dory"]\n'
264
+ )
265
+
266
+ torch.manual_seed(42)
267
+ h, f = config["hidden_size"], config["intermediate_size"]
268
+ q, kv = config["num_attention_heads"] * config["head_dim"], config["num_key_value_heads"] * config["head_dim"]
269
+ tensors = {}
270
+
271
+ class CheckpointModule(torch.nn.Module):
272
+ def extra_repr(self):
273
+ return "\n".join(
274
+ f"{name}: shape={tuple(p.shape)}, dtype={p.dtype}" for name, p in self.named_parameters(recurse=False)
275
+ )
276
+
277
+ graph = CheckpointModule()
278
+
279
+ def add(name, shape):
280
+ tensor = torch.randn(shape, dtype=torch.bfloat16) * config["initializer_range"]
281
+ tensors[name] = tensor
282
+ module = graph
283
+ parts = name.split(".")
284
+ for part in parts[:-1]:
285
+ if part not in module._modules:
286
+ module.add_module(part, CheckpointModule())
287
+ module = module._modules[part]
288
+ module.register_parameter(parts[-1], torch.nn.Parameter(tensor))
289
+
290
+ add("backbone.embeddings.weight", (config["vocab_size"], h))
291
+ add("lm_head.weight", (config["vocab_size"], h))
292
+ add("lm_head.logit_scale", (config["vocab_size"],))
293
+ for i, kind in enumerate(config["layer_types"]):
294
+ prefix = f"backbone.layers.{i}"
295
+ if kind == "mlp":
296
+ add(prefix + ".mlp_alpha", (h,))
297
+ for name in ("gate_proj", "up_proj"):
298
+ add(prefix + f".mixer.{name}.weight", (f, h))
299
+ add(prefix + ".mixer.down_proj.weight", (h, f))
300
+ for name in ("suv_gate", "suv_up"):
301
+ add(prefix + f".mixer.{name}", (f,))
302
+ else:
303
+ add(prefix + ".attn_alpha", (h,))
304
+ for name, rows in (("q_proj", q), ("k_proj", kv), ("v_proj", kv), ("g_proj", q)):
305
+ add(prefix + f".mixer.{name}.weight", (rows, h))
306
+ add(prefix + ".mixer.o_proj.weight", (h, q))
307
+ for name in ("sqk", "s_gate"):
308
+ add(prefix + f".mixer.{name}", (q,))
309
+ save_file(tensors, str(folder / "model.safetensors"), metadata={"format": "pt"})
310
+ return str(graph)
311
+
312
+
313
+ create_model(
314
+ source_model_id="nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16",
315
+ source_revision="b366b87f762ea334ba3eb55912031baba1515810",
316
+ save_folder="/mlx_devbox/users/yujie.pan/playground/tiny-random/tmp/scratch/dory-builder-v1",
317
+ )
318
+ ```
319
+
320
+ </details>
321
+
322
+ ### Printing the model:
323
+
324
+ <details><summary>Click to expand</summary>
325
+
326
+ ```text
327
+ CheckpointModule(
328
+ (backbone): CheckpointModule(
329
+ (embeddings): CheckpointModule(weight: shape=(131072, 2), dtype=torch.bfloat16)
330
+ (layers): CheckpointModule(
331
+ (0): CheckpointModule(
332
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
333
+ (mixer): CheckpointModule(
334
+ sqk: shape=(128,), dtype=torch.bfloat16
335
+ s_gate: shape=(128,), dtype=torch.bfloat16
336
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
337
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
338
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
339
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
340
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
341
+ )
342
+ )
343
+ (1): CheckpointModule(
344
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
345
+ (mixer): CheckpointModule(
346
+ suv_gate: shape=(32,), dtype=torch.bfloat16
347
+ suv_up: shape=(32,), dtype=torch.bfloat16
348
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
349
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
350
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
351
+ )
352
+ )
353
+ (2): CheckpointModule(
354
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
355
+ (mixer): CheckpointModule(
356
+ sqk: shape=(128,), dtype=torch.bfloat16
357
+ s_gate: shape=(128,), dtype=torch.bfloat16
358
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
359
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
360
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
361
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
362
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
363
+ )
364
+ )
365
+ (3): CheckpointModule(
366
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
367
+ (mixer): CheckpointModule(
368
+ suv_gate: shape=(32,), dtype=torch.bfloat16
369
+ suv_up: shape=(32,), dtype=torch.bfloat16
370
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
371
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
372
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
373
+ )
374
+ )
375
+ (4): CheckpointModule(
376
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
377
+ (mixer): CheckpointModule(
378
+ sqk: shape=(128,), dtype=torch.bfloat16
379
+ s_gate: shape=(128,), dtype=torch.bfloat16
380
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
381
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
382
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
383
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
384
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
385
+ )
386
+ )
387
+ (5): CheckpointModule(
388
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
389
+ (mixer): CheckpointModule(
390
+ suv_gate: shape=(32,), dtype=torch.bfloat16
391
+ suv_up: shape=(32,), dtype=torch.bfloat16
392
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
393
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
394
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
395
+ )
396
+ )
397
+ (6): CheckpointModule(
398
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
399
+ (mixer): CheckpointModule(
400
+ sqk: shape=(128,), dtype=torch.bfloat16
401
+ s_gate: shape=(128,), dtype=torch.bfloat16
402
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
403
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
404
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
405
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
406
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
407
+ )
408
+ )
409
+ (7): CheckpointModule(
410
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
411
+ (mixer): CheckpointModule(
412
+ suv_gate: shape=(32,), dtype=torch.bfloat16
413
+ suv_up: shape=(32,), dtype=torch.bfloat16
414
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
415
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
416
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
417
+ )
418
+ )
419
+ (8): CheckpointModule(
420
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
421
+ (mixer): CheckpointModule(
422
+ sqk: shape=(128,), dtype=torch.bfloat16
423
+ s_gate: shape=(128,), dtype=torch.bfloat16
424
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
425
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
426
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
427
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
428
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
429
+ )
430
+ )
431
+ (9): CheckpointModule(
432
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
433
+ (mixer): CheckpointModule(
434
+ suv_gate: shape=(32,), dtype=torch.bfloat16
435
+ suv_up: shape=(32,), dtype=torch.bfloat16
436
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
437
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
438
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
439
+ )
440
+ )
441
+ (10): CheckpointModule(
442
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
443
+ (mixer): CheckpointModule(
444
+ sqk: shape=(128,), dtype=torch.bfloat16
445
+ s_gate: shape=(128,), dtype=torch.bfloat16
446
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
447
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
448
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
449
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
450
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
451
+ )
452
+ )
453
+ (11): CheckpointModule(
454
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
455
+ (mixer): CheckpointModule(
456
+ suv_gate: shape=(32,), dtype=torch.bfloat16
457
+ suv_up: shape=(32,), dtype=torch.bfloat16
458
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
459
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
460
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
461
+ )
462
+ )
463
+ (12): CheckpointModule(
464
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
465
+ (mixer): CheckpointModule(
466
+ sqk: shape=(128,), dtype=torch.bfloat16
467
+ s_gate: shape=(128,), dtype=torch.bfloat16
468
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
469
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
470
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
471
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
472
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
473
+ )
474
+ )
475
+ (13): CheckpointModule(
476
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
477
+ (mixer): CheckpointModule(
478
+ suv_gate: shape=(32,), dtype=torch.bfloat16
479
+ suv_up: shape=(32,), dtype=torch.bfloat16
480
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
481
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
482
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
483
+ )
484
+ )
485
+ (14): CheckpointModule(
486
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
487
+ (mixer): CheckpointModule(
488
+ sqk: shape=(128,), dtype=torch.bfloat16
489
+ s_gate: shape=(128,), dtype=torch.bfloat16
490
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
491
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
492
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
493
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
494
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
495
+ )
496
+ )
497
+ (15): CheckpointModule(
498
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
499
+ (mixer): CheckpointModule(
500
+ suv_gate: shape=(32,), dtype=torch.bfloat16
501
+ suv_up: shape=(32,), dtype=torch.bfloat16
502
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
503
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
504
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
505
+ )
506
+ )
507
+ (16): CheckpointModule(
508
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
509
+ (mixer): CheckpointModule(
510
+ sqk: shape=(128,), dtype=torch.bfloat16
511
+ s_gate: shape=(128,), dtype=torch.bfloat16
512
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
513
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
514
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
515
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
516
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
517
+ )
518
+ )
519
+ (17): CheckpointModule(
520
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
521
+ (mixer): CheckpointModule(
522
+ suv_gate: shape=(32,), dtype=torch.bfloat16
523
+ suv_up: shape=(32,), dtype=torch.bfloat16
524
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
525
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
526
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
527
+ )
528
+ )
529
+ (18): CheckpointModule(
530
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
531
+ (mixer): CheckpointModule(
532
+ sqk: shape=(128,), dtype=torch.bfloat16
533
+ s_gate: shape=(128,), dtype=torch.bfloat16
534
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
535
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
536
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
537
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
538
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
539
+ )
540
+ )
541
+ (19): CheckpointModule(
542
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
543
+ (mixer): CheckpointModule(
544
+ suv_gate: shape=(32,), dtype=torch.bfloat16
545
+ suv_up: shape=(32,), dtype=torch.bfloat16
546
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
547
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
548
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
549
+ )
550
+ )
551
+ (20): CheckpointModule(
552
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
553
+ (mixer): CheckpointModule(
554
+ sqk: shape=(128,), dtype=torch.bfloat16
555
+ s_gate: shape=(128,), dtype=torch.bfloat16
556
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
557
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
558
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
559
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
560
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
561
+ )
562
+ )
563
+ (21): CheckpointModule(
564
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
565
+ (mixer): CheckpointModule(
566
+ suv_gate: shape=(32,), dtype=torch.bfloat16
567
+ suv_up: shape=(32,), dtype=torch.bfloat16
568
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
569
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
570
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
571
+ )
572
+ )
573
+ (22): CheckpointModule(
574
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
575
+ (mixer): CheckpointModule(
576
+ sqk: shape=(128,), dtype=torch.bfloat16
577
+ s_gate: shape=(128,), dtype=torch.bfloat16
578
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
579
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
580
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
581
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
582
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
583
+ )
584
+ )
585
+ (23): CheckpointModule(
586
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
587
+ (mixer): CheckpointModule(
588
+ suv_gate: shape=(32,), dtype=torch.bfloat16
589
+ suv_up: shape=(32,), dtype=torch.bfloat16
590
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
591
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
592
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
593
+ )
594
+ )
595
+ (24): CheckpointModule(
596
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
597
+ (mixer): CheckpointModule(
598
+ sqk: shape=(128,), dtype=torch.bfloat16
599
+ s_gate: shape=(128,), dtype=torch.bfloat16
600
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
601
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
602
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
603
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
604
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
605
+ )
606
+ )
607
+ (25): CheckpointModule(
608
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
609
+ (mixer): CheckpointModule(
610
+ suv_gate: shape=(32,), dtype=torch.bfloat16
611
+ suv_up: shape=(32,), dtype=torch.bfloat16
612
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
613
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
614
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
615
+ )
616
+ )
617
+ (26): CheckpointModule(
618
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
619
+ (mixer): CheckpointModule(
620
+ sqk: shape=(128,), dtype=torch.bfloat16
621
+ s_gate: shape=(128,), dtype=torch.bfloat16
622
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
623
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
624
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
625
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
626
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
627
+ )
628
+ )
629
+ (27): CheckpointModule(
630
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
631
+ (mixer): CheckpointModule(
632
+ suv_gate: shape=(32,), dtype=torch.bfloat16
633
+ suv_up: shape=(32,), dtype=torch.bfloat16
634
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
635
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
636
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
637
+ )
638
+ )
639
+ (28): CheckpointModule(
640
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
641
+ (mixer): CheckpointModule(
642
+ sqk: shape=(128,), dtype=torch.bfloat16
643
+ s_gate: shape=(128,), dtype=torch.bfloat16
644
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
645
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
646
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
647
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
648
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
649
+ )
650
+ )
651
+ (29): CheckpointModule(
652
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
653
+ (mixer): CheckpointModule(
654
+ suv_gate: shape=(32,), dtype=torch.bfloat16
655
+ suv_up: shape=(32,), dtype=torch.bfloat16
656
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
657
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
658
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
659
+ )
660
+ )
661
+ (30): CheckpointModule(
662
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
663
+ (mixer): CheckpointModule(
664
+ sqk: shape=(128,), dtype=torch.bfloat16
665
+ s_gate: shape=(128,), dtype=torch.bfloat16
666
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
667
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
668
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
669
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
670
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
671
+ )
672
+ )
673
+ (31): CheckpointModule(
674
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
675
+ (mixer): CheckpointModule(
676
+ suv_gate: shape=(32,), dtype=torch.bfloat16
677
+ suv_up: shape=(32,), dtype=torch.bfloat16
678
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
679
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
680
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
681
+ )
682
+ )
683
+ (32): CheckpointModule(
684
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
685
+ (mixer): CheckpointModule(
686
+ sqk: shape=(128,), dtype=torch.bfloat16
687
+ s_gate: shape=(128,), dtype=torch.bfloat16
688
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
689
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
690
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
691
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
692
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
693
+ )
694
+ )
695
+ (33): CheckpointModule(
696
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
697
+ (mixer): CheckpointModule(
698
+ suv_gate: shape=(32,), dtype=torch.bfloat16
699
+ suv_up: shape=(32,), dtype=torch.bfloat16
700
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
701
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
702
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
703
+ )
704
+ )
705
+ (34): CheckpointModule(
706
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
707
+ (mixer): CheckpointModule(
708
+ sqk: shape=(128,), dtype=torch.bfloat16
709
+ s_gate: shape=(128,), dtype=torch.bfloat16
710
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
711
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
712
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
713
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
714
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
715
+ )
716
+ )
717
+ (35): CheckpointModule(
718
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
719
+ (mixer): CheckpointModule(
720
+ suv_gate: shape=(32,), dtype=torch.bfloat16
721
+ suv_up: shape=(32,), dtype=torch.bfloat16
722
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
723
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
724
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
725
+ )
726
+ )
727
+ (36): CheckpointModule(
728
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
729
+ (mixer): CheckpointModule(
730
+ sqk: shape=(128,), dtype=torch.bfloat16
731
+ s_gate: shape=(128,), dtype=torch.bfloat16
732
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
733
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
734
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
735
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
736
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
737
+ )
738
+ )
739
+ (37): CheckpointModule(
740
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
741
+ (mixer): CheckpointModule(
742
+ suv_gate: shape=(32,), dtype=torch.bfloat16
743
+ suv_up: shape=(32,), dtype=torch.bfloat16
744
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
745
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
746
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
747
+ )
748
+ )
749
+ (38): CheckpointModule(
750
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
751
+ (mixer): CheckpointModule(
752
+ sqk: shape=(128,), dtype=torch.bfloat16
753
+ s_gate: shape=(128,), dtype=torch.bfloat16
754
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
755
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
756
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
757
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
758
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
759
+ )
760
+ )
761
+ (39): CheckpointModule(
762
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
763
+ (mixer): CheckpointModule(
764
+ suv_gate: shape=(32,), dtype=torch.bfloat16
765
+ suv_up: shape=(32,), dtype=torch.bfloat16
766
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
767
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
768
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
769
+ )
770
+ )
771
+ (40): CheckpointModule(
772
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
773
+ (mixer): CheckpointModule(
774
+ sqk: shape=(128,), dtype=torch.bfloat16
775
+ s_gate: shape=(128,), dtype=torch.bfloat16
776
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
777
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
778
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
779
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
780
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
781
+ )
782
+ )
783
+ (41): CheckpointModule(
784
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
785
+ (mixer): CheckpointModule(
786
+ suv_gate: shape=(32,), dtype=torch.bfloat16
787
+ suv_up: shape=(32,), dtype=torch.bfloat16
788
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
789
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
790
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
791
+ )
792
+ )
793
+ (42): CheckpointModule(
794
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
795
+ (mixer): CheckpointModule(
796
+ sqk: shape=(128,), dtype=torch.bfloat16
797
+ s_gate: shape=(128,), dtype=torch.bfloat16
798
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
799
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
800
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
801
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
802
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
803
+ )
804
+ )
805
+ (43): CheckpointModule(
806
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
807
+ (mixer): CheckpointModule(
808
+ suv_gate: shape=(32,), dtype=torch.bfloat16
809
+ suv_up: shape=(32,), dtype=torch.bfloat16
810
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
811
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
812
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
813
+ )
814
+ )
815
+ (44): CheckpointModule(
816
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
817
+ (mixer): CheckpointModule(
818
+ sqk: shape=(128,), dtype=torch.bfloat16
819
+ s_gate: shape=(128,), dtype=torch.bfloat16
820
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
821
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
822
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
823
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
824
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
825
+ )
826
+ )
827
+ (45): CheckpointModule(
828
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
829
+ (mixer): CheckpointModule(
830
+ suv_gate: shape=(32,), dtype=torch.bfloat16
831
+ suv_up: shape=(32,), dtype=torch.bfloat16
832
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
833
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
834
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
835
+ )
836
+ )
837
+ (46): CheckpointModule(
838
+ attn_alpha: shape=(2,), dtype=torch.bfloat16
839
+ (mixer): CheckpointModule(
840
+ sqk: shape=(128,), dtype=torch.bfloat16
841
+ s_gate: shape=(128,), dtype=torch.bfloat16
842
+ (q_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
843
+ (k_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
844
+ (v_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
845
+ (g_proj): CheckpointModule(weight: shape=(128, 2), dtype=torch.bfloat16)
846
+ (o_proj): CheckpointModule(weight: shape=(2, 128), dtype=torch.bfloat16)
847
+ )
848
+ )
849
+ (47): CheckpointModule(
850
+ mlp_alpha: shape=(2,), dtype=torch.bfloat16
851
+ (mixer): CheckpointModule(
852
+ suv_gate: shape=(32,), dtype=torch.bfloat16
853
+ suv_up: shape=(32,), dtype=torch.bfloat16
854
+ (gate_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
855
+ (up_proj): CheckpointModule(weight: shape=(32, 2), dtype=torch.bfloat16)
856
+ (down_proj): CheckpointModule(weight: shape=(2, 32), dtype=torch.bfloat16)
857
+ )
858
+ )
859
+ )
860
+ )
861
+ (lm_head): CheckpointModule(
862
+ weight: shape=(131072, 2), dtype=torch.bfloat16
863
+ logit_scale: shape=(131072,), dtype=torch.bfloat16
864
+ )
865
+ )
866
+ ```
867
+
868
+ </details>
869
+
870
+ ### Creation environment:
871
+
872
+ - python: 3.12.13
873
+ - cuda: 12.6
874
+ - huggingface_hub: 2.3.0
875
+ - safetensors: 0.8.0
876
+ - tokenizers: 0.23.3
877
+ - torch: 2.13.0+cu126
878
+ - transformers: 5.20.2
879
+
880
+ ### Test environment:
881
+
882
+ **vLLM offline / vLLM serving**
883
+
884
+ - python: 3.12.13
885
+ - cuda: 13.0
886
+ - flashinfer-python: 0.7.0.post1
887
+ - huggingface_hub: 2.3.0
888
+ - safetensors: 0.8.0
889
+ - tokenizers: 0.23.3
890
+ - torch: 2.13.0+cu130
891
+ - transformers: 5.19.0
892
+ - vllm: 0.32.0
893
+
894
+ ### Change log:
895
+
896
+ - 2026-10-25: Created BF16 Dory with a two-dimensional latent and verified TP=4 inference.
897
+ - 2026-10-26: Verified the current standalone offline and HTTP serving examples on four H20 GPUs.
898
+
899
+ This repo is generated by GPT-6.1-Sol
__pycache__/dory_plugin.cpython-312.pyc ADDED
Binary file (448 Bytes). View file
 
__pycache__/vllm_dory.cpython-312.pyc ADDED
Binary file (22.8 kB). View file
 
chat_template.jinja ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro render_extra_keys(json_dict, handled_keys) %}
2
+ {%- if json_dict is mapping %}
3
+ {%- for json_key in json_dict if json_key not in handled_keys %}
4
+ {%- if json_dict[json_key] is mapping or (json_dict[json_key] is sequence and json_dict[json_key] is not string) %}
5
+ {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | tojson | safe) ~ '</' ~ json_key ~ '>' }}
6
+ {%- else %}
7
+ {{-'\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | string) ~ '</' ~ json_key ~ '>' }}
8
+ {%- endif %}
9
+ {%- endfor %}
10
+ {%- endif %}
11
+ {% endmacro %}
12
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else True %}
13
+ {%- set medium_effort = medium_effort if medium_effort is defined else False %}
14
+ {%- set truncate_history_thinking = truncate_history_thinking if truncate_history_thinking is defined else True %}
15
+ {%- set ns = namespace(last_user_idx = -1) %}
16
+ {%- set loop_messages = messages %}
17
+ {%- for m in loop_messages %}
18
+ {%- if m["role"] == "user" %}
19
+ {%- set ns.last_user_idx = loop.index0 %}
20
+ {%- endif %}
21
+ {%- endfor %}
22
+ {%- if messages[0]["role"] == "system" %}
23
+ {%- set system_message = messages[0]["content"] %}
24
+ {%- set loop_messages = messages[1:] %}
25
+ {%- else %}
26
+ {%- set system_message = "" %}
27
+ {%- set loop_messages = messages %}
28
+ {%- endif %}
29
+ {%- if not tools is defined %}
30
+ {%- set tools = [] %}
31
+ {%- endif %}
32
+ {%- set ns = namespace(last_user_idx = -1) %}
33
+ {%- for m in loop_messages %}
34
+ {%- if m["role"] == "user" %}
35
+ {%- set ns.last_user_idx = loop.index0 %}
36
+ {%- endif %}
37
+ {%- endfor %}
38
+ {%- if system_message is defined %}
39
+ {{- "<|im_start|>system\n" + system_message }}
40
+ {%- else %}
41
+ {%- if tools is iterable and tools | length > 0 %}
42
+ {{- "<|im_start|>system\n" }}
43
+ {%- endif %}
44
+ {%- endif %}
45
+ {%- if tools is iterable and tools | length > 0 %}
46
+ {%- if system_message is defined and system_message | length > 0 %}
47
+ {{- "\n\n" }}
48
+ {%- endif %}
49
+ {{- "# Tools\n\nYou have access to the following functions:\n\n" }}
50
+ {{- "<tools>" }}
51
+ {%- for tool in tools %}
52
+ {%- if tool.function is defined %}
53
+ {%- set tool = tool.function %}
54
+ {%- endif %}
55
+ {{- "\n<function>\n<name>" ~ tool.name ~ "</name>" }}
56
+ {%- if tool.description is defined %}
57
+ {{- '\n<description>' ~ (tool.description | trim) ~ '</description>' }}
58
+ {%- endif %}
59
+ {{- '\n<parameters>' }}
60
+ {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping %}
61
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
62
+ {{- '\n<parameter>' }}
63
+ {{- '\n<name>' ~ param_name ~ '</name>' }}
64
+ {%- if param_fields.type is defined %}
65
+ {{- '\n<type>' ~ (param_fields.type | string) ~ '</type>' }}
66
+ {%- endif %}
67
+ {%- if param_fields.description is defined %}
68
+ {{- '\n<description>' ~ (param_fields.description | trim) ~ '</description>' }}
69
+ {%- endif %}
70
+ {%- if param_fields.enum is defined %}
71
+ {{- '\n<enum>' ~ (param_fields.enum | tojson | safe) ~ '</enum>' }}
72
+ {%- endif %}
73
+ {%- set handled_keys = ['name', 'type', 'description', 'enum'] %}
74
+ {{- render_extra_keys(param_fields, handled_keys) }}
75
+ {{- '\n</parameter>' }}
76
+ {%- endfor %}
77
+ {%- endif %}
78
+ {% set handled_keys = ['type', 'properties', 'required'] %}
79
+ {{- render_extra_keys(tool.parameters, handled_keys) }}
80
+ {%- if tool.parameters is defined and tool.parameters.required is defined %}
81
+ {{- '\n<required>' ~ (tool.parameters.required | tojson | safe) ~ '</required>' }}
82
+ {%- endif %}
83
+ {{- '\n</parameters>' }}
84
+ {%- set handled_keys = ['type', 'name', 'description', 'parameters'] %}
85
+ {{- render_extra_keys(tool, handled_keys) }}
86
+ {{- '\n</function>' }}
87
+ {%- endfor %}
88
+ {{- "\n</tools>" }}
89
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
90
+ {%- endif %}
91
+ {%- if system_message is defined %}
92
+ {{- '<|im_end|>\n' }}
93
+ {%- else %}
94
+ {%- if tools is iterable and tools | length > 0 %}
95
+ {{- '<|im_end|>\n' }}
96
+ {%- endif %}
97
+ {%- endif %}
98
+ {%- for message in loop_messages %}
99
+ {%- if message.role == "assistant" %}
100
+ {%- if message.reasoning_content is defined and message.reasoning_content is string and message.reasoning_content | trim | length > 0 %}
101
+ {%- set content = "<think>\n" ~ message.reasoning_content ~ "</think>" ~ (message.content | default('', true)) %}
102
+ {%- else %}
103
+ {%- set content = message.content | default('', true) %}
104
+ {%- if content is string -%}
105
+ {%- if '<think>' not in content and '</think>' not in content -%}
106
+ {%- set content = "<think></think>" ~ content -%}
107
+ {%- endif -%}
108
+ {%- else -%}
109
+ {%- set content = content -%}
110
+ {%- endif -%}
111
+ {%- endif %}
112
+ {%- if message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}
113
+ {{- '<|im_start|>assistant\n' }}
114
+ {%- set include_content = not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
115
+ {%- if content is string and content | trim | length > 0 %}
116
+ {%- if include_content %}
117
+ {{- (content | trim) ~ '\n' -}}
118
+ {%- else %}
119
+ {%- set c = (content | string) %}
120
+ {%- if '</think>' in c %}
121
+ {%- set c = c.split('</think>')[-1] %}
122
+ {%- elif '<think>' in c %}
123
+ {%- set c = c.split('<think>')[0] %}
124
+ {%- endif %}
125
+ {%- set c = "<think></think>" ~ c %}
126
+ {%- if c | length > 0 %}
127
+ {{- c ~ '\n' -}}
128
+ {%- endif %}
129
+ {%- endif %}
130
+ {%- else %}
131
+ {{- "<think></think>" -}}
132
+ {%- endif %}
133
+ {%- for tool_call in message.tool_calls %}
134
+ {%- if tool_call.function is defined %}
135
+ {%- set tool_call = tool_call.function %}
136
+ {%- endif %}
137
+ {{- '<tool_call>\n<function=' ~ tool_call.name ~ '>\n' -}}
138
+ {%- if tool_call.arguments is defined %}
139
+ {%- for args_name, args_value in tool_call.arguments|items %}
140
+ {{- '<parameter=' ~ args_name ~ '>\n' -}}
141
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
142
+ {{- args_value ~ '\n</parameter>\n' -}}
143
+ {%- endfor %}
144
+ {%- endif %}
145
+ {{- '</function>\n</tool_call>\n' -}}
146
+ {%- endfor %}
147
+ {{- '<|im_end|>\n' }}
148
+ {%- else %}
149
+ {%- if not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
150
+ {{- '<|im_start|>assistant\n' ~ (content | default('', true) | string | trim) ~ '<|im_end|>\n' }}
151
+ {%- else %}
152
+ {%- set c = (content | default('', true) | string) %}
153
+ {%- if '<think>' in c and '</think>' in c %}
154
+ {%- set c = "<think></think>" ~ c.split('</think>')[-1] %}
155
+ {%- endif %}
156
+ {%- set c = c | trim %}
157
+ {%- if c | length > 0 %}
158
+ {{- '<|im_start|>assistant\n' ~ c ~ '<|im_end|>\n' }}
159
+ {%- else %}
160
+ {{- '<|im_start|>assistant\n<|im_end|>\n' }}
161
+ {%- endif %}
162
+ {%- endif %}
163
+ {%- endif %}
164
+ {%- elif message.role == "user" or message.role == "system" %}
165
+ {{- '<|im_start|>' + message.role + '\n' }}
166
+ {%- set content = message.content | string %}
167
+ {%- if message.role == "user" and loop.index0 == ns.last_user_idx and medium_effort %}
168
+ {{- content + '\n\n{reasoning effort: efficient}' }}
169
+ {%- else %}
170
+ {{- content }}
171
+ {%- endif %}
172
+ {{- '<|im_end|>\n' }}
173
+ {%- elif message.role == "tool" %}
174
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
175
+ {{- '<|im_start|>user\n' }}
176
+ {%- endif %}
177
+ {{- '<tool_response>\n' }}
178
+ {{- message.content }}
179
+ {{- '\n</tool_response>\n' }}
180
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
181
+ {{- '<|im_end|>\n' }}
182
+ {%- elif loop.last %}
183
+ {{- '<|im_end|>\n' }}
184
+ {%- endif %}
185
+ {%- else %}
186
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }}
187
+ {%- endif %}
188
+ {%- endfor %}
189
+ {%- if add_generation_prompt %}
190
+ {%- if enable_thinking %}
191
+ {{- '<|im_start|>assistant\n<think>\n' }}
192
+ {%- else %}
193
+ {{- '<|im_start|>assistant\n<think></think>' }}
194
+ {%- endif %}
195
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DoryForCausalLM"
4
+ ],
5
+ "model_type": "dory",
6
+ "vocab_size": 131072,
7
+ "hidden_size": 2,
8
+ "num_hidden_layers": 48,
9
+ "intermediate_size": 32,
10
+ "num_attention_heads": 4,
11
+ "num_key_value_heads": 1,
12
+ "max_position_embeddings": 262144,
13
+ "tie_word_embeddings": false,
14
+ "ngpt_alpha_init": 0.05,
15
+ "attention_output_gate_logit_scale_init": null,
16
+ "mlp_bias": false,
17
+ "attention_bias": false,
18
+ "n_input_layers": 16,
19
+ "n_recurrent_layers": 16,
20
+ "n_output_layers": 16,
21
+ "n_recurrent_loops": 2,
22
+ "head_dim": 32,
23
+ "hidden_act": "silu",
24
+ "initializer_range": 0.0177,
25
+ "dtype": "bfloat16",
26
+ "sliding_window": 1024,
27
+ "rope_parameters": {
28
+ "sliding_attention": {
29
+ "rope_type": "default",
30
+ "rope_theta": 10000,
31
+ "partial_rotary_factor": 1.0
32
+ },
33
+ "full_attention": {
34
+ "rope_type": "default",
35
+ "rope_theta": 10000000,
36
+ "partial_rotary_factor": 1.0
37
+ }
38
+ },
39
+ "layer_types": [
40
+ "sliding_attention",
41
+ "mlp",
42
+ "sliding_attention",
43
+ "mlp",
44
+ "sliding_attention",
45
+ "mlp",
46
+ "full_attention",
47
+ "mlp",
48
+ "sliding_attention",
49
+ "mlp",
50
+ "sliding_attention",
51
+ "mlp",
52
+ "sliding_attention",
53
+ "mlp",
54
+ "full_attention",
55
+ "mlp",
56
+ "sliding_attention",
57
+ "mlp",
58
+ "sliding_attention",
59
+ "mlp",
60
+ "sliding_attention",
61
+ "mlp",
62
+ "full_attention",
63
+ "mlp",
64
+ "sliding_attention",
65
+ "mlp",
66
+ "sliding_attention",
67
+ "mlp",
68
+ "sliding_attention",
69
+ "mlp",
70
+ "full_attention",
71
+ "mlp",
72
+ "sliding_attention",
73
+ "mlp",
74
+ "sliding_attention",
75
+ "mlp",
76
+ "sliding_attention",
77
+ "mlp",
78
+ "full_attention",
79
+ "mlp",
80
+ "sliding_attention",
81
+ "mlp",
82
+ "sliding_attention",
83
+ "mlp",
84
+ "sliding_attention",
85
+ "mlp",
86
+ "full_attention",
87
+ "mlp"
88
+ ],
89
+ "auto_map": {
90
+ "AutoConfig": "configuration_dory.DoryConfig"
91
+ }
92
+ }
configuration_dory.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+ """Configuration for the normalized latent recurrent Dory architecture."""
4
+
5
+ from huggingface_hub.dataclasses import strict
6
+ from transformers.configuration_utils import PreTrainedConfig
7
+
8
+
9
+ @strict
10
+ class DoryConfig(PreTrainedConfig):
11
+ model_type = "dory"
12
+ default_theta = 10_000.0
13
+
14
+ vocab_size: int = 131072
15
+ hidden_size: int = 2560
16
+ num_hidden_layers: int = 72
17
+ intermediate_size: int = 7168
18
+ num_attention_heads: int = 16
19
+ num_key_value_heads: int = 4
20
+ head_dim: int = 256
21
+ max_position_embeddings: int = 8192
22
+ tie_word_embeddings: bool = False
23
+ hidden_act: str = "silu"
24
+ # Also normalizes the learned nGPT scales at inference time.
25
+ initializer_range: float = 0.02
26
+ sliding_window: int | None = 1024
27
+ rope_parameters: dict | None = None
28
+ layer_types: list[str] | None = None
29
+ ngpt_alpha_init: float = 0.05
30
+ attention_output_gate_logit_scale_init: float | None = None
31
+ mlp_bias: bool = False
32
+ attention_bias: bool = False
33
+ n_input_layers: int = 0
34
+ n_recurrent_layers: int | None = None
35
+ n_output_layers: int = 0
36
+ n_recurrent_loops: int = 1
37
+ # "last_loop" reuses one cache, overwritten by each recurrent loop.
38
+ recurrent_kv_cache_mode: str = "per_loop"
39
+
40
+ def __post_init__(self, **kwargs):
41
+ if self.layer_types is None:
42
+ self.layer_types = [
43
+ "mlp"
44
+ if i % 2
45
+ else "full_attention"
46
+ if i % 8 == 6
47
+ else "sliding_attention"
48
+ for i in range(self.num_hidden_layers)
49
+ ]
50
+ if self.rope_parameters is None:
51
+ self.rope_parameters = {
52
+ kind: {
53
+ "rope_type": "default",
54
+ "partial_rotary_factor": 1.0,
55
+ }
56
+ for kind in ("sliding_attention", "full_attention")
57
+ if kind in self.layer_types
58
+ }
59
+ if self.n_recurrent_layers is None:
60
+ self.n_recurrent_layers = (
61
+ self.num_hidden_layers - self.n_input_layers - self.n_output_layers
62
+ )
63
+ super().__post_init__(**kwargs)
64
+
65
+ def validate_layer_type(self):
66
+ # Each physical block is attention-only or MLP-only.
67
+ valid_types = {"sliding_attention", "full_attention", "mlp"}
68
+ if self.layer_types is None or any(
69
+ kind not in valid_types for kind in self.layer_types
70
+ ):
71
+ raise ValueError(
72
+ "layer_types must be a list of sliding_attention, "
73
+ "full_attention, or mlp"
74
+ )
75
+ if len(self.layer_types) != self.num_hidden_layers:
76
+ raise ValueError("layer_types must have num_hidden_layers entries")
77
+
78
+ def validate_architecture(self):
79
+ if self.layer_types is None or self.n_recurrent_layers is None:
80
+ raise ValueError("Dory layer layout must be initialized")
81
+ partitions = (
82
+ self.n_input_layers,
83
+ self.n_recurrent_layers,
84
+ self.n_output_layers,
85
+ )
86
+ if any(n < 0 for n in partitions) or sum(partitions) != self.num_hidden_layers:
87
+ raise ValueError(
88
+ "Dory input, recurrent, and output layers must sum to num_hidden_layers"
89
+ )
90
+ if self.n_recurrent_loops < 1:
91
+ raise ValueError("n_recurrent_loops must be a positive integer")
92
+ if self.recurrent_kv_cache_mode not in ("per_loop", "last_loop"):
93
+ raise ValueError("recurrent_kv_cache_mode must be per_loop or last_loop")
94
+ if any(
95
+ n <= 0
96
+ for n in (self.head_dim, self.num_attention_heads, self.num_key_value_heads)
97
+ ):
98
+ raise ValueError("Attention dimensions must be positive integers")
99
+ if self.num_attention_heads % self.num_key_value_heads:
100
+ raise ValueError(
101
+ "num_attention_heads must be divisible by num_key_value_heads"
102
+ )
103
+ if self.initializer_range <= 0:
104
+ raise ValueError("initializer_range must be positive")
105
+ if "sliding_attention" in self.layer_types and (
106
+ self.sliding_window is None or self.sliding_window <= 0
107
+ ):
108
+ raise ValueError("sliding_window must be a positive integer")
109
+ if self.attention_bias or self.mlp_bias:
110
+ raise ValueError("Dory requires bias-free projections")
111
+ if self.hidden_act != "silu" or self.tie_word_embeddings:
112
+ raise ValueError("Dory requires SiLU and untied embeddings")
113
+
114
+ def validate_rope(self):
115
+ if self.layer_types is None:
116
+ raise ValueError("Dory layer layout must be initialized")
117
+ attention_types = set(self.layer_types) - {"mlp"}
118
+ if self.rope_parameters is None or (
119
+ set(self.rope_parameters) - {"sliding_attention", "full_attention"}
120
+ or attention_types - self.rope_parameters.keys()
121
+ ):
122
+ raise ValueError("rope_parameters must define each attention block type")
123
+ for rope in self.rope_parameters.values():
124
+ if (
125
+ not isinstance(rope, dict)
126
+ or rope.get("rope_type") != "default"
127
+ or rope.get("rope_theta", 0) <= 0
128
+ ):
129
+ raise ValueError(
130
+ "Dory requires default RoPE with a positive rope_theta"
131
+ )
132
+ fraction = rope.get("partial_rotary_factor", 1.0)
133
+ rotary_dim = int(self.head_dim * fraction)
134
+ if not 0 < fraction <= 1 or rotary_dim <= 0 or rotary_dim % 2:
135
+ raise ValueError(
136
+ "Rotary dimensions must be positive, even, and <= head_dim"
137
+ )
dory_plugin.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ def register():
2
+ from vllm import ModelRegistry
3
+ ModelRegistry.register_model('DoryForCausalLM', 'vllm_dory:DoryForCausalLM')
generation_config.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 1,
4
+ "do_sample": true,
5
+ "eos_token_id": [
6
+ 2,
7
+ 11
8
+ ],
9
+ "pad_token_id": 11,
10
+ "top_p": 0.95,
11
+ "temperature": 1.0,
12
+ "transformers_version": "4.57.6"
13
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2e0daeb6402db33c80385828cd559453ed6af107f1e3c2800d144a55ad59aff3
3
+ size 1412480
pyproject.toml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+ [project]
5
+ name = "dory-inference"
6
+ version = "0.1.0"
7
+ [project.entry-points."vllm.general_plugins"]
8
+ dory = "dory_plugin:register"
9
+ [tool.setuptools]
10
+ py-modules = ["dory_plugin", "vllm_dory", "configuration_dory"]
special_tokens_map.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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": "<|im_end|>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<|im_end|>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "unk_token": {
24
+ "content": "<unk>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ }
30
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:623c34567aebb18582765289fbe23d901c62704d6518d71866e0e58db892b5b7
3
+ size 17077484
tokenizer_config.json ADDED
The diff for this file is too large to render. See raw diff
 
vllm_dory.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+ """Dory: normalized latent recurrent transformer."""
4
+
5
+ import math
6
+ from collections.abc import Iterable
7
+
8
+ import torch
9
+ import torch.nn.functional as F
10
+ from torch import nn
11
+
12
+ from vllm.compilation.decorators import support_torch_compile
13
+ from vllm.config import VllmConfig
14
+ from vllm.distributed import (get_tensor_model_parallel_world_size, get_tensor_model_parallel_rank, tensor_model_parallel_all_reduce)
15
+ from vllm.model_executor.layers.attention import Attention
16
+ from vllm.model_executor.layers.linear import (
17
+ ColumnParallelLinear,
18
+ MergedColumnParallelLinear,
19
+ QKVParallelLinear,
20
+ RowParallelLinear,
21
+ )
22
+ from vllm.model_executor.layers.logits_processor import LogitsProcessor
23
+ from vllm.model_executor.layers.rotary_embedding import get_rope
24
+ from vllm.model_executor.layers.vocab_parallel_embedding import (
25
+ ParallelLMHead,
26
+ VocabParallelEmbedding,
27
+ )
28
+ from vllm.model_executor.model_loader.weight_utils import default_weight_loader
29
+ from vllm.model_executor.parameter import PerTensorScaleParameter
30
+ from vllm.sequence import IntermediateTensors
31
+
32
+ from vllm.model_executor.models.utils import maybe_prefix
33
+
34
+ EPS = 1e-6
35
+
36
+ def partition_norm(x):
37
+ total = tensor_model_parallel_all_reduce(x.float().square().sum(dim=-1, keepdim=True))
38
+ return (x.float() * torch.rsqrt(total + EPS)).to(x.dtype)
39
+
40
+ def load_vector(param, weight):
41
+ rank = get_tensor_model_parallel_rank()
42
+ param.data.copy_(weight.narrow(0, rank * param.numel(), param.numel()))
43
+
44
+
45
+
46
+ def justnorm(x: torch.Tensor, dim: int = -1) -> torch.Tensor:
47
+ """NGPT normalization: x * rsqrt(sum(x^2) + eps), fp32 accumulation."""
48
+ xf = x.float()
49
+ y = xf * torch.rsqrt(xf.pow(2).sum(dim=dim, keepdim=True) + EPS)
50
+ return y.to(x.dtype)
51
+
52
+
53
+ def slerp_norm(a: torch.Tensor, b: torch.Tensor, lr: torch.Tensor) -> torch.Tensor:
54
+ ya, yb = justnorm(a).float(), justnorm(b).float()
55
+ return justnorm(ya + lr.float() * (yb - ya)).to(a.dtype)
56
+
57
+
58
+ def slerp_alpha(a, b, alpha, alpha_scale):
59
+ return slerp_norm(a, b, (alpha.float() * alpha_scale).abs())
60
+
61
+
62
+ class DoryAttention(nn.Module):
63
+ """GQA attention with nGPT qk-norm, output gate, and fngpt justnorm."""
64
+
65
+ def __init__(
66
+ self, config, layer_idx, cache_config, quant_config, prefix, num_loops=1
67
+ ):
68
+ super().__init__()
69
+ self.hidden_size = config.hidden_size
70
+ self.num_heads = config.num_attention_heads // get_tensor_model_parallel_world_size()
71
+ self.num_kv_heads = max(1, config.num_key_value_heads // get_tensor_model_parallel_world_size())
72
+ self.head_dim = config.head_dim
73
+ self.q_size = self.num_heads * self.head_dim
74
+ self.kv_size = self.num_kv_heads * self.head_dim
75
+ std = config.initializer_range
76
+
77
+ self.qkv_proj = QKVParallelLinear(
78
+ self.hidden_size,
79
+ self.head_dim,
80
+ config.num_attention_heads,
81
+ config.num_key_value_heads,
82
+ bias=False,
83
+ quant_config=quant_config,
84
+ prefix=f"{prefix}.qkv_proj",
85
+ )
86
+ self.g_proj = ColumnParallelLinear(
87
+ self.hidden_size,
88
+ config.num_attention_heads * self.head_dim,
89
+ bias=False,
90
+ quant_config=quant_config,
91
+ prefix=f"{prefix}.g_proj",
92
+ )
93
+ self.o_proj = RowParallelLinear(
94
+ config.num_attention_heads * self.head_dim,
95
+ self.hidden_size,
96
+ bias=False,
97
+ quant_config=quant_config,
98
+ prefix=f"{prefix}.o_proj",
99
+ )
100
+
101
+ self.sqk = nn.Parameter(torch.empty(self.q_size))
102
+ self.s_gate = nn.Parameter(torch.empty(self.q_size))
103
+ self.sqk.weight_loader = self.s_gate.weight_loader = load_vector
104
+ self._sqk_factor = self.head_dim**0.5 / std
105
+ g0 = config.attention_output_gate_logit_scale_init
106
+ if g0 is None:
107
+ g0 = config.hidden_size**0.5
108
+ self._s_gate_factor = g0**0.5 / std
109
+
110
+ layer_type = config.layer_types[layer_idx]
111
+ self.rotary_emb = get_rope(
112
+ self.head_dim,
113
+ max_position=config.max_position_embeddings,
114
+ rope_parameters=config.rope_parameters[layer_type],
115
+ is_neox_style=True,
116
+ )
117
+
118
+ self.per_loop_kv = config.recurrent_kv_cache_mode == "per_loop"
119
+ # Match LoopCoder's virtual layer indices for independent loop caches.
120
+ # Projection prefixes keep the physical layer index to share weights.
121
+ self.attn = nn.ModuleList()
122
+ for loop_idx in range(num_loops if self.per_loop_kv else 1):
123
+ unique_layer_idx = loop_idx * config.num_hidden_layers + layer_idx
124
+ unique_prefix = prefix.replace(
125
+ f".layers.{layer_idx}.", f".layers.{unique_layer_idx}."
126
+ )
127
+ self.attn.append(
128
+ Attention(
129
+ self.num_heads,
130
+ self.head_dim,
131
+ scale=1.0 / math.sqrt(self.head_dim),
132
+ num_kv_heads=self.num_kv_heads,
133
+ cache_config=cache_config,
134
+ quant_config=quant_config,
135
+ per_layer_sliding_window=(
136
+ config.sliding_window
137
+ if layer_type == "sliding_attention"
138
+ else None
139
+ ),
140
+ prefix=f"{unique_prefix}.attn",
141
+ )
142
+ )
143
+
144
+ def forward(self, positions, hidden_states, loop_idx=0):
145
+ qkv, _ = self.qkv_proj(hidden_states)
146
+ q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
147
+ gate, _ = self.g_proj(hidden_states)
148
+
149
+ q, k = self.rotary_emb(positions, q, k)
150
+
151
+ # nGPT qk-norm AFTER rope: q scaled by (sqk*f)^2 post-justnorm, k plain justnorm
152
+ t = q.shape[0]
153
+ q = q.view(t, self.num_heads, self.head_dim)
154
+ sqk = (self.sqk.float() * self._sqk_factor).view(
155
+ 1, self.num_heads, self.head_dim
156
+ )
157
+ q = (sqk.square() * justnorm(q).float()).to(q.dtype).view(t, self.q_size)
158
+ k = k.view(t, self.num_kv_heads, self.head_dim)
159
+ k = justnorm(k).view(t, self.kv_size)
160
+
161
+ # In last-loop mode every loop writes this step's KV to the same cache,
162
+ # overwriting the previous loop's. Loop i thus attends to loop-i KV for
163
+ # this step's tokens and last-loop KV for earlier tokens.
164
+ out = self.attn[loop_idx if self.per_loop_kv else 0](q, k, v)
165
+
166
+ # output gate (sigmoid, pre-o_proj), then fngpt justnorm over np*hn
167
+ sg = (self.s_gate.float() * self._s_gate_factor).square()
168
+ out = (out.float() * torch.sigmoid(gate.float() * sg)).to(out.dtype)
169
+ out = partition_norm(out)
170
+ out, _ = self.o_proj(out)
171
+ return out
172
+
173
+
174
+ class DoryMLP(nn.Module):
175
+ """SwiGLU with nGPT suv scaling and fngpt justnorm."""
176
+
177
+ def __init__(self, config, quant_config, prefix):
178
+ super().__init__()
179
+ self.ffn = config.intermediate_size // get_tensor_model_parallel_world_size()
180
+ self.gate_up_proj = MergedColumnParallelLinear(
181
+ config.hidden_size,
182
+ [config.intermediate_size] * 2,
183
+ bias=False,
184
+ quant_config=quant_config,
185
+ prefix=f"{prefix}.gate_up_proj",
186
+ )
187
+ self.down_proj = RowParallelLinear(
188
+ config.intermediate_size,
189
+ config.hidden_size,
190
+ bias=False,
191
+ quant_config=quant_config,
192
+ prefix=f"{prefix}.down_proj",
193
+ )
194
+ self.suv_gate = nn.Parameter(torch.empty(self.ffn))
195
+ self.suv_up = nn.Parameter(torch.empty(self.ffn))
196
+ self.suv_gate.weight_loader = self.suv_up.weight_loader = load_vector
197
+ self._suv_factor = config.hidden_size**0.5
198
+
199
+ def forward(self, hidden_states):
200
+ m, _ = self.gate_up_proj(hidden_states)
201
+ g, u = m.chunk(2, dim=-1)
202
+ g = (g.float() * (self.suv_gate.float() * self._suv_factor)).to(g.dtype)
203
+ u = (u.float() * (self.suv_up.float() * self._suv_factor)).to(u.dtype)
204
+ m = (F.silu(g.float()) * u.float()).to(m.dtype)
205
+ m = partition_norm(m)
206
+ out, _ = self.down_proj(m)
207
+ return out
208
+
209
+
210
+ class DoryDecoderLayer(nn.Module):
211
+ """One physical layer: a single sublayer (attention OR mlp) + slerp residual."""
212
+
213
+ def __init__(
214
+ self, config, layer_idx, cache_config, quant_config, prefix, num_loops=1
215
+ ):
216
+ super().__init__()
217
+ self.is_attention = config.layer_types[layer_idx] != "mlp"
218
+ self._alpha_scale = config.ngpt_alpha_init / config.initializer_range
219
+ if self.is_attention:
220
+ self.mixer = DoryAttention(
221
+ config,
222
+ layer_idx,
223
+ cache_config,
224
+ quant_config,
225
+ f"{prefix}.mixer",
226
+ num_loops=num_loops,
227
+ )
228
+ self.attn_alpha = nn.Parameter(torch.empty(config.hidden_size))
229
+ else:
230
+ self.mixer = DoryMLP(config, quant_config, f"{prefix}.mixer")
231
+ self.mlp_alpha = nn.Parameter(torch.empty(config.hidden_size))
232
+
233
+ def forward(self, positions, hidden_states, loop_idx=0):
234
+ residual = hidden_states
235
+ if self.is_attention:
236
+ out = self.mixer(positions, hidden_states, loop_idx=loop_idx)
237
+ return slerp_alpha(residual, out, self.attn_alpha, self._alpha_scale)
238
+ out = self.mixer(hidden_states)
239
+ return slerp_alpha(residual, out, self.mlp_alpha, self._alpha_scale)
240
+
241
+
242
+ @support_torch_compile
243
+ class DoryBackbone(nn.Module):
244
+ def __init__(self, config, cache_config, quant_config, prefix):
245
+ super().__init__()
246
+ self.config = config
247
+ self.num_loops = config.n_recurrent_loops
248
+ n_in = config.n_input_layers
249
+ n_rec = config.n_recurrent_layers
250
+ self.embeddings = VocabParallelEmbedding(config.vocab_size, config.hidden_size)
251
+ self.layers = nn.ModuleList(
252
+ [
253
+ DoryDecoderLayer(
254
+ config,
255
+ i,
256
+ cache_config,
257
+ quant_config,
258
+ f"{prefix}.layers.{i}",
259
+ num_loops=self.num_loops if n_in <= i < n_in + n_rec else 1,
260
+ )
261
+ for i in range(config.num_hidden_layers)
262
+ ]
263
+ )
264
+
265
+ def forward(
266
+ self,
267
+ input_ids: torch.Tensor | None,
268
+ positions: torch.Tensor,
269
+ inputs_embeds: torch.Tensor | None = None,
270
+ ) -> torch.Tensor:
271
+ h = inputs_embeds if inputs_embeds is not None else self.embeddings(input_ids)
272
+ c = self.config
273
+ n_in, n_rec = c.n_input_layers, c.n_recurrent_layers
274
+
275
+ for layer in self.layers[:n_in]:
276
+ h = layer(positions, h)
277
+ input_h = h
278
+
279
+ state = input_h
280
+ for i in range(self.num_loops):
281
+ combined = justnorm(state + input_h)
282
+ h = combined
283
+ for layer in self.layers[n_in : n_in + n_rec]:
284
+ h = layer(positions, h, loop_idx=i)
285
+ state = justnorm(h)
286
+
287
+ h = state
288
+ for layer in self.layers[n_in + n_rec :]:
289
+ h = layer(positions, h)
290
+ return h
291
+
292
+
293
+ class DoryForCausalLM(nn.Module):
294
+ packed_modules_mapping = {
295
+ "qkv_proj": ["q_proj", "k_proj", "v_proj"],
296
+ "gate_up_proj": ["gate_proj", "up_proj"],
297
+ }
298
+
299
+ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
300
+ super().__init__()
301
+ config = vllm_config.model_config.hf_config
302
+ self.config = config
303
+ # hf_overrides can change architecture fields after config initialization.
304
+ config.validate()
305
+ self.backbone = DoryBackbone(
306
+ config,
307
+ vllm_config.cache_config,
308
+ vllm_config.quant_config,
309
+ prefix=maybe_prefix(prefix, "backbone"),
310
+ )
311
+ self.lm_head = ParallelLMHead(
312
+ config.vocab_size,
313
+ config.hidden_size,
314
+ bias=False,
315
+ prefix=maybe_prefix(prefix, "lm_head"),
316
+ )
317
+ self.lm_head.logit_scale = nn.Parameter(torch.empty(config.vocab_size))
318
+ self.logits_processor = LogitsProcessor(config.vocab_size)
319
+
320
+ def embed_input_ids(self, input_ids):
321
+ return self.backbone.embeddings(input_ids)
322
+
323
+ def forward(
324
+ self,
325
+ input_ids: torch.Tensor | None,
326
+ positions: torch.Tensor,
327
+ intermediate_tensors: IntermediateTensors | None = None,
328
+ inputs_embeds: torch.Tensor | None = None,
329
+ ):
330
+ return self.backbone(input_ids, positions, inputs_embeds=inputs_embeds)
331
+
332
+ def compute_logits(self, hidden_states: torch.Tensor) -> torch.Tensor | None:
333
+ logits = self.logits_processor(self.lm_head, hidden_states)
334
+ if logits is not None:
335
+ logits = logits.float() * (
336
+ self.lm_head.logit_scale.float() / self.config.initializer_range
337
+ )
338
+ return logits
339
+
340
+ def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
341
+ stacked = [
342
+ # (target, artifact shard name, shard id)
343
+ ("qkv_proj", "q_proj", "q"),
344
+ ("qkv_proj", "k_proj", "k"),
345
+ ("qkv_proj", "v_proj", "v"),
346
+ ("gate_up_proj", "gate_proj", 0),
347
+ ("gate_up_proj", "up_proj", 1),
348
+ ]
349
+ params = dict(self.named_parameters())
350
+ loaded: set[str] = set()
351
+ for name, w in weights:
352
+ mapped = False
353
+ for target, shard_name, shard_id in stacked:
354
+ if f".{shard_name}." not in name:
355
+ continue
356
+ pname = name.replace(f".{shard_name}.", f".{target}.")
357
+ param = params[pname]
358
+ if target == "qkv_proj":
359
+ heads = (
360
+ self.config.num_attention_heads
361
+ if shard_id == "q"
362
+ else self.config.num_key_value_heads
363
+ )
364
+ rows = heads * self.config.head_dim
365
+ else:
366
+ rows = self.config.intermediate_size
367
+ if isinstance(param, PerTensorScaleParameter):
368
+ shape = () if w.ndim == 0 else (1,)
369
+ else:
370
+ # Preserve packed input columns and per-block scale columns.
371
+ shape = (rows, *param.shape[1:])
372
+ self._check_weight_shape(name, w, shape)
373
+ param.weight_loader(param, w, shard_id)
374
+ loaded.add(pname) # report the MODEL param name, not the artifact name
375
+ mapped = True
376
+ break
377
+ if mapped:
378
+ continue
379
+
380
+ param = params[name]
381
+ shape = (
382
+ (self.config.vocab_size, self.config.hidden_size)
383
+ if name in ("backbone.embeddings.weight", "lm_head.weight")
384
+ else tuple(param.shape)
385
+ )
386
+ if isinstance(param, PerTensorScaleParameter) and w.ndim == 0:
387
+ shape = ()
388
+ if name.endswith((".sqk", ".s_gate")):
389
+ shape = (self.config.num_attention_heads * self.config.head_dim,)
390
+ elif name.endswith((".suv_gate", ".suv_up")):
391
+ shape = (self.config.intermediate_size,)
392
+ elif name.endswith(".g_proj.weight"):
393
+ shape = (self.config.num_attention_heads * self.config.head_dim, self.config.hidden_size)
394
+ elif name.endswith(".o_proj.weight"):
395
+ shape = (self.config.hidden_size, self.config.num_attention_heads * self.config.head_dim)
396
+ elif name.endswith(".down_proj.weight"):
397
+ shape = (self.config.hidden_size, self.config.intermediate_size)
398
+ self._check_weight_shape(name, w, shape)
399
+ getattr(param, "weight_loader", default_weight_loader)(param, w)
400
+ loaded.add(name)
401
+ return loaded
402
+
403
+ @staticmethod
404
+ def _check_weight_shape(name, weight, expected):
405
+ # TP loaders may narrow oversized tensors; reject incompatible exports.
406
+ if tuple(weight.shape) != expected:
407
+ raise ValueError(
408
+ f"Dory weight {name}: expected shape {expected}, "
409
+ f"got {tuple(weight.shape)}"
410
+ )