mlx-bun 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +362 -0
  3. package/THIRD_PARTY_LICENSES.md +41 -0
  4. package/bin/mlx-bun.mjs +32 -0
  5. package/docs/curve-designer.html +303 -0
  6. package/docs/design/adapters-end-to-end.md +201 -0
  7. package/docs/design/compat-cli-surface-design.md +227 -0
  8. package/docs/design/docs-reorg-plan.md +152 -0
  9. package/docs/design/hlg-sampling.md +340 -0
  10. package/docs/design/memory-system.md +339 -0
  11. package/docs/design/optimization_plan.md +344 -0
  12. package/docs/design/parallel-slots.md +515 -0
  13. package/docs/design/runtime-isolation.md +247 -0
  14. package/docs/design/segmented-backward-training.md +508 -0
  15. package/docs/investigations/chunk-finetune-experiment.md +84 -0
  16. package/docs/investigations/curve-bisector-routing.md +123 -0
  17. package/docs/investigations/curve-runs/bisector-route.json +98 -0
  18. package/docs/investigations/curve-runs/bisector-trace.json +1393 -0
  19. package/docs/investigations/curve-runs/curve-terrain.json +1179 -0
  20. package/docs/investigations/curve-runs/curve-terrain.svg +42 -0
  21. package/docs/investigations/curve-terrain.html +105 -0
  22. package/docs/investigations/expert-offload-single-user-moe.md +292 -0
  23. package/docs/investigations/hlg-ab.html +34 -0
  24. package/docs/investigations/hlg-explorer.html +238 -0
  25. package/docs/investigations/hlg-figs/cliff.svg +1 -0
  26. package/docs/investigations/hlg-figs/cross.svg +1 -0
  27. package/docs/investigations/hlg-figs/edges.svg +1 -0
  28. package/docs/investigations/hlg-figs/k20-grids.svg +1 -0
  29. package/docs/investigations/hlg-figs/k20-peaks.svg +1 -0
  30. package/docs/investigations/hlg-figs/lw-curve.svg +1 -0
  31. package/docs/investigations/hlg-figs/terrain.svg +1 -0
  32. package/docs/investigations/hlg-report.html +262 -0
  33. package/docs/investigations/hlg-runs/hlg-ab.json +149 -0
  34. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +87 -0
  35. package/docs/investigations/hlg-runs/hlg-blind.json +107 -0
  36. package/docs/investigations/hlg-runs/hlg-cliff.json +197 -0
  37. package/docs/investigations/hlg-runs/hlg-cross.json +505 -0
  38. package/docs/investigations/hlg-runs/hlg-edge.json +388 -0
  39. package/docs/investigations/hlg-runs/hlg-eval1.json +25 -0
  40. package/docs/investigations/hlg-runs/hlg-frontier.json +86 -0
  41. package/docs/investigations/hlg-runs/hlg-grid.json +242 -0
  42. package/docs/investigations/hlg-runs/hlg-grid2.json +343 -0
  43. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +110 -0
  44. package/docs/investigations/hlg-runs/hlg-map.json +383 -0
  45. package/docs/investigations/hlg-runs/run0-original.log +159 -0
  46. package/docs/investigations/hlg-runs/runA-recommended.log +131 -0
  47. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +26 -0
  48. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +18 -0
  49. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +25 -0
  50. package/docs/investigations/hlg-runs/runAD-ab-samples.log +8 -0
  51. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +51 -0
  52. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +10 -0
  53. package/docs/investigations/hlg-runs/runAG-eval-config2.log +16 -0
  54. package/docs/investigations/hlg-runs/runB-gain-variants.log +192 -0
  55. package/docs/investigations/hlg-runs/runC-pivots.log +162 -0
  56. package/docs/investigations/hlg-runs/runD-oetf.log +132 -0
  57. package/docs/investigations/hlg-runs/runE-eotf.log +162 -0
  58. package/docs/investigations/hlg-runs/runF-shaper-working.log +86 -0
  59. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +101 -0
  60. package/docs/investigations/hlg-runs/runH-wsweep.log +176 -0
  61. package/docs/investigations/hlg-runs/runI-asweep.log +176 -0
  62. package/docs/investigations/hlg-runs/runJ-knobmap.log +49 -0
  63. package/docs/investigations/hlg-runs/runK-frontier.log +19 -0
  64. package/docs/investigations/hlg-runs/runL-widemap.log +65 -0
  65. package/docs/investigations/hlg-runs/runM-frontier-emb.log +15 -0
  66. package/docs/investigations/hlg-runs/runN-verify.log +116 -0
  67. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +15 -0
  68. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +15 -0
  69. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +15 -0
  70. package/docs/investigations/hlg-runs/runR-blind-transcript.log +79 -0
  71. package/docs/investigations/hlg-runs/runS-cross-coherence.log +33 -0
  72. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +33 -0
  73. package/docs/investigations/hlg-runs/runU-cross-12b.log +33 -0
  74. package/docs/investigations/hlg-runs/runV-lw-e4b.log +22 -0
  75. package/docs/investigations/hlg-runs/runW-lw-12b.log +22 -0
  76. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +22 -0
  77. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +26 -0
  78. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +26 -0
  79. package/docs/investigations/hlg-sampling-investigation.md +970 -0
  80. package/docs/investigations/lab-build-journal.md +157 -0
  81. package/docs/investigations/pi-builtin-investigation.md +308 -0
  82. package/docs/investigations/starter-model-port-handoff.md +323 -0
  83. package/docs/planning/IDEAS.md +26 -0
  84. package/docs/planning/PRODUCT_ROADMAP.md +426 -0
  85. package/docs/planning/ResearchTopics.md +119 -0
  86. package/docs/planning/chunk-task-roadmap.md +77 -0
  87. package/docs/planning/journal.md +155 -0
  88. package/docs/reference/distribution.md +121 -0
  89. package/docs/reference/embedding.md +168 -0
  90. package/docs/reference/library-api.md +153 -0
  91. package/docs/reference/server-api.md +224 -0
  92. package/docs/reference/server-config.md +243 -0
  93. package/docs/segmented-backward-handoff.md +148 -0
  94. package/package.json +68 -0
  95. package/src/anthropic.ts +491 -0
  96. package/src/chat-template.ts +186 -0
  97. package/src/cli.ts +1075 -0
  98. package/src/config.ts +229 -0
  99. package/src/curve-sampler.ts +122 -0
  100. package/src/dataset/generators.ts +1087 -0
  101. package/src/dataset/index.ts +12 -0
  102. package/src/dataset/job.ts +81 -0
  103. package/src/dataset/llm.ts +71 -0
  104. package/src/dataset/registry.ts +528 -0
  105. package/src/download.ts +283 -0
  106. package/src/eval/README.md +86 -0
  107. package/src/eval/kl-prompts.ts +29 -0
  108. package/src/eval/kl.ts +294 -0
  109. package/src/eval/quality-db.ts +92 -0
  110. package/src/eval/runner.ts +102 -0
  111. package/src/eval/score.ts +49 -0
  112. package/src/eval/tasks/bfcl.ts +500 -0
  113. package/src/eval/tasks/gsm8k.ts +85 -0
  114. package/src/eval/tasks/hashhop.ts +109 -0
  115. package/src/eval/tasks/humaneval.ts +252 -0
  116. package/src/eval/tasks/ifeval.ts +354 -0
  117. package/src/eval/tasks/mmlu.ts +145 -0
  118. package/src/evaldb.ts +199 -0
  119. package/src/expert-offload-build.ts +77 -0
  120. package/src/expert-offload.ts +61 -0
  121. package/src/expert-trace.ts +67 -0
  122. package/src/fit.ts +254 -0
  123. package/src/generate.ts +451 -0
  124. package/src/harness-pi.ts +177 -0
  125. package/src/hf-push.ts +628 -0
  126. package/src/index.ts +22 -0
  127. package/src/jobs/db.ts +139 -0
  128. package/src/jobs/index.ts +29 -0
  129. package/src/jobs/job-entry.ts +106 -0
  130. package/src/jobs/runner.ts +304 -0
  131. package/src/jobs/sse.ts +114 -0
  132. package/src/jobs/types.ts +58 -0
  133. package/src/kv-store.ts +185 -0
  134. package/src/lora.ts +314 -0
  135. package/src/md-modules.d.ts +7 -0
  136. package/src/mlx/array.ts +237 -0
  137. package/src/mlx/autograd.ts +267 -0
  138. package/src/mlx/checkpoint.ts +116 -0
  139. package/src/mlx/compile.ts +158 -0
  140. package/src/mlx/custom-vjp.ts +140 -0
  141. package/src/mlx/ffi.ts +433 -0
  142. package/src/mlx/metal-kernel.ts +130 -0
  143. package/src/mlx/ops.ts +707 -0
  144. package/src/mmap.ts +90 -0
  145. package/src/model/batched-mask.ts +204 -0
  146. package/src/model/batched-rotating.ts +300 -0
  147. package/src/model/compiled-decode.ts +681 -0
  148. package/src/model/factory.ts +27 -0
  149. package/src/model/fingerprint.ts +33 -0
  150. package/src/model/flash-attention.ts +674 -0
  151. package/src/model/fused-decode-kernel.ts +305 -0
  152. package/src/model/fused-geglu-kernel.ts +87 -0
  153. package/src/model/gemma4-base.ts +1616 -0
  154. package/src/model/gemma4.ts +1012 -0
  155. package/src/model/generated/gemma4-12b.ts +526 -0
  156. package/src/model/generated/gemma4-26b.ts +500 -0
  157. package/src/model/generated/gemma4-e4b.ts +757 -0
  158. package/src/model/generated/index.ts +18 -0
  159. package/src/model/minicpm5.ts +278 -0
  160. package/src/model/qwen3-delta.ts +224 -0
  161. package/src/model/qwen3_5.ts +429 -0
  162. package/src/model/support.ts +46 -0
  163. package/src/native-pack.ts +152 -0
  164. package/src/pi-provider.ts +95 -0
  165. package/src/pi-terminal.ts +264 -0
  166. package/src/pi-web.ts +924 -0
  167. package/src/preflight.ts +123 -0
  168. package/src/prompt-cache.ts +113 -0
  169. package/src/quantize/allocator.ts +627 -0
  170. package/src/quantize/calibration.ts +180 -0
  171. package/src/quantize/config-writer.ts +132 -0
  172. package/src/quantize/index.ts +57 -0
  173. package/src/quantize/job.ts +136 -0
  174. package/src/quantize/quantizer.ts +462 -0
  175. package/src/quantize/safetensors-writer.ts +171 -0
  176. package/src/quantize/sensitivity.ts +234 -0
  177. package/src/registry.ts +336 -0
  178. package/src/responses.ts +774 -0
  179. package/src/safetensors.ts +158 -0
  180. package/src/sampler.ts +517 -0
  181. package/src/serve/batch-scheduler.ts +362 -0
  182. package/src/serve/generation-gateway.ts +160 -0
  183. package/src/server.ts +1891 -0
  184. package/src/spec/drafter.ts +261 -0
  185. package/src/spec/generate.ts +221 -0
  186. package/src/status-page.html +497 -0
  187. package/src/tokenizer.ts +38 -0
  188. package/src/tool-call.ts +242 -0
  189. package/src/train/dataset.ts +461 -0
  190. package/src/train/export.ts +32 -0
  191. package/src/train/forward.ts +229 -0
  192. package/src/train/index.ts +43 -0
  193. package/src/train/job.ts +148 -0
  194. package/src/train/lora-params.ts +194 -0
  195. package/src/train/loss.ts +342 -0
  196. package/src/train/merge.ts +195 -0
  197. package/src/train/optimizer.ts +176 -0
  198. package/src/train/rank.ts +101 -0
  199. package/src/train/segmented.ts +520 -0
  200. package/src/train/trainer.ts +600 -0
  201. package/src/tui.ts +161 -0
  202. package/src/vision/embedder.ts +168 -0
  203. package/src/vision/preprocess.ts +247 -0
  204. package/src/vision/prompt.ts +158 -0
  205. package/src/vision/siglip.ts +599 -0
  206. package/src/web/app.html +2471 -0
  207. package/src/web/skills/web-research/SKILL.md +44 -0
  208. package/src/web/skills.ts +59 -0
  209. package/src/web-tools.ts +426 -0
  210. package/src/weights.ts +91 -0
@@ -0,0 +1,500 @@
1
+ // GENERATED by scripts/gen-model.ts — DO NOT EDIT (regenerate instead):
2
+ // bun scripts/gen-model.ts <model-dir> gemma4-26b
3
+ // source: models--mlx-community--gemma-4-26B-A4B-it-OptiQ-4bit/snapshots/dbfd2a779b038b267bb20ff95dad717f42e4de16
4
+ // fingerprint: c9dd67ed5a525231
5
+ //
6
+ // Branch-resolved, unrolled forward pass for this architecture
7
+ // (docs/design/optimization_plan.md Phase C). Bit-exactness vs the monolith is the
8
+ // generator's gate: tests/generated-parity.test.ts. The cache-signature
9
+ // guard falls back to the monolith for anything this file wasn't
10
+ // generated for (bf16 compat runs, vision bidir prefill).
11
+
12
+ import { MlxArray } from "../../mlx/array";
13
+ import * as ops from "../../mlx/ops";
14
+ import {
15
+ disposing,
16
+ fusedSdpaRuntimeOk,
17
+ KVCache,
18
+ QuantizedKVCache,
19
+ quantizedSdpaTiled,
20
+ quantizedSdpaUnfused,
21
+ RotatingKVCache,
22
+ RotatingQuantizedKVCache,
23
+ type Cache,
24
+ type Mask,
25
+ type SharedKv,
26
+ } from "../gemma4-base";
27
+ import { Gemma4Model, type DecoderLayer } from "../gemma4";
28
+
29
+ export const FINGERPRINT = "c9dd67ed5a525231";
30
+
31
+ /** Forward passes served by the generated fast path (vs monolith
32
+ * fallback) — the parity gate asserts the fast path actually ran. */
33
+ export let generatedForwardUses = 0;
34
+
35
+ function disposeSharedKv(s: SharedKv): void {
36
+ if (s.kind === "plain") {
37
+ s.keys.dispose();
38
+ s.values.dispose();
39
+ } else {
40
+ for (const t of [s.keys, s.values])
41
+ for (const a of [t.packed, t.scales, t.biases]) a.dispose();
42
+ }
43
+ }
44
+
45
+ function donorSlidQuantG64B8VMoeScal(layer: DecoderLayer, x: MlxArray, mask: Mask, cache: RotatingQuantizedKVCache): MlxArray {
46
+ const a = layer.attn;
47
+ const [B, L] = x.shape as [number, number, number];
48
+ let h = layer.inputNorm.forward(x);
49
+ let q = a.qProj.forward(h);
50
+ q = disposing(q, ops.reshape(q, [B, L, a.nHeads, a.headDim]));
51
+ q = disposing(q, a.qNorm.forward(q));
52
+ const offset = cache.offset;
53
+ let k = a.kProj!.forward(h);
54
+ k = disposing(k, ops.reshape(k, [B, L, a.nKvHeads, a.headDim]));
55
+ let v = a.vProj!.forward(h);
56
+ v = disposing(v, ops.reshape(v, [B, L, a.nKvHeads, a.headDim]));
57
+ const kNormed = a.kNorm!.forward(k);
58
+ const kT = ops.transposeAxes(kNormed, [0, 2, 1, 3]);
59
+ kNormed.dispose();
60
+ const kRoped = a.rope(kT, cache.ropeOffsetArr ?? offset);
61
+ kT.dispose();
62
+ const vNormed = a.vNorm!.forward(v);
63
+ const vT = ops.transposeAxes(vNormed, [0, 2, 1, 3]);
64
+ vNormed.dispose();
65
+ v.dispose();
66
+ k.dispose();
67
+ const [kq, vq] = cache.updateAndFetchQuantized(kRoped, vT);
68
+ kRoped.dispose();
69
+ vT.dispose();
70
+ q = disposing(q, ops.transposeAxes(q, [0, 2, 1, 3]));
71
+ q = disposing(q, a.rope(q, cache.ropeOffsetArr ?? offset));
72
+ // dispatch-site constants: bits=8 group_size=64 nRep=2 head_dim=256
73
+ const attn = (L > 1 || process.env.MLX_BUN_FUSED_DECODE === "1") && fusedSdpaRuntimeOk(q, mask)
74
+ ? quantizedSdpaTiled(q, kq, vq, 1.0, mask, 64, 8)
75
+ : quantizedSdpaUnfused(q, kq, vq, 1.0, mask, 64, 8);
76
+ q.dispose();
77
+ const attnT = ops.transposeAxes(attn, [0, 2, 1, 3]);
78
+ attn.dispose();
79
+ const merged = ops.reshape(attnT, [B, L, -1]);
80
+ attnT.dispose();
81
+ const out = a.oProj.forward(merged);
82
+ merged.dispose();
83
+ h.dispose();
84
+ h = out;
85
+ h = disposing(h, layer.postAttnNorm.forward(h));
86
+ h = disposing(h, ops.add(x, h));
87
+ const residual = h;
88
+ let h1 = layer.preFfNorm.forward(h);
89
+ h1 = disposing(h1, layer.mlp.forward(h1));
90
+ h1 = disposing(h1, layer.postFfNorm1!.forward(h1));
91
+ const { indices, weights: topKWeights } = layer.router!.forward(h);
92
+ let h2 = layer.preFfNorm2!.forward(h);
93
+ h2 = disposing(h2, layer.experts!.forward(h2, indices, topKWeights));
94
+ h2 = disposing(h2, layer.postFfNorm2!.forward(h2));
95
+ indices.dispose();
96
+ topKWeights.dispose();
97
+ let f = ops.add(h1, h2);
98
+ h1.dispose();
99
+ h2.dispose();
100
+ f = disposing(f, layer.postFfNorm.forward(f));
101
+ h = ops.add(residual, f);
102
+ residual.dispose();
103
+ f.dispose();
104
+ h = disposing(h, ops.mul(h, layer.layerScalar!));
105
+ for (const t of [kq, vq]) for (const c of [t.packed, t.scales, t.biases]) c.dispose();
106
+ return h;
107
+ }
108
+
109
+ function donorSlidQuantG64B4VMoeScal(layer: DecoderLayer, x: MlxArray, mask: Mask, cache: RotatingQuantizedKVCache): MlxArray {
110
+ const a = layer.attn;
111
+ const [B, L] = x.shape as [number, number, number];
112
+ let h = layer.inputNorm.forward(x);
113
+ let q = a.qProj.forward(h);
114
+ q = disposing(q, ops.reshape(q, [B, L, a.nHeads, a.headDim]));
115
+ q = disposing(q, a.qNorm.forward(q));
116
+ const offset = cache.offset;
117
+ let k = a.kProj!.forward(h);
118
+ k = disposing(k, ops.reshape(k, [B, L, a.nKvHeads, a.headDim]));
119
+ let v = a.vProj!.forward(h);
120
+ v = disposing(v, ops.reshape(v, [B, L, a.nKvHeads, a.headDim]));
121
+ const kNormed = a.kNorm!.forward(k);
122
+ const kT = ops.transposeAxes(kNormed, [0, 2, 1, 3]);
123
+ kNormed.dispose();
124
+ const kRoped = a.rope(kT, cache.ropeOffsetArr ?? offset);
125
+ kT.dispose();
126
+ const vNormed = a.vNorm!.forward(v);
127
+ const vT = ops.transposeAxes(vNormed, [0, 2, 1, 3]);
128
+ vNormed.dispose();
129
+ v.dispose();
130
+ k.dispose();
131
+ const [kq, vq] = cache.updateAndFetchQuantized(kRoped, vT);
132
+ kRoped.dispose();
133
+ vT.dispose();
134
+ q = disposing(q, ops.transposeAxes(q, [0, 2, 1, 3]));
135
+ q = disposing(q, a.rope(q, cache.ropeOffsetArr ?? offset));
136
+ // dispatch-site constants: bits=4 group_size=64 nRep=2 head_dim=256
137
+ const attn = (L > 1 || process.env.MLX_BUN_FUSED_DECODE === "1") && fusedSdpaRuntimeOk(q, mask)
138
+ ? quantizedSdpaTiled(q, kq, vq, 1.0, mask, 64, 4)
139
+ : quantizedSdpaUnfused(q, kq, vq, 1.0, mask, 64, 4);
140
+ q.dispose();
141
+ const attnT = ops.transposeAxes(attn, [0, 2, 1, 3]);
142
+ attn.dispose();
143
+ const merged = ops.reshape(attnT, [B, L, -1]);
144
+ attnT.dispose();
145
+ const out = a.oProj.forward(merged);
146
+ merged.dispose();
147
+ h.dispose();
148
+ h = out;
149
+ h = disposing(h, layer.postAttnNorm.forward(h));
150
+ h = disposing(h, ops.add(x, h));
151
+ const residual = h;
152
+ let h1 = layer.preFfNorm.forward(h);
153
+ h1 = disposing(h1, layer.mlp.forward(h1));
154
+ h1 = disposing(h1, layer.postFfNorm1!.forward(h1));
155
+ const { indices, weights: topKWeights } = layer.router!.forward(h);
156
+ let h2 = layer.preFfNorm2!.forward(h);
157
+ h2 = disposing(h2, layer.experts!.forward(h2, indices, topKWeights));
158
+ h2 = disposing(h2, layer.postFfNorm2!.forward(h2));
159
+ indices.dispose();
160
+ topKWeights.dispose();
161
+ let f = ops.add(h1, h2);
162
+ h1.dispose();
163
+ h2.dispose();
164
+ f = disposing(f, layer.postFfNorm.forward(f));
165
+ h = ops.add(residual, f);
166
+ residual.dispose();
167
+ f.dispose();
168
+ h = disposing(h, ops.mul(h, layer.layerScalar!));
169
+ for (const t of [kq, vq]) for (const c of [t.packed, t.scales, t.biases]) c.dispose();
170
+ return h;
171
+ }
172
+
173
+ function donorFullQuantG64B8KeqVMoeScal(layer: DecoderLayer, x: MlxArray, mask: Mask, cache: QuantizedKVCache): MlxArray {
174
+ const a = layer.attn;
175
+ const [B, L] = x.shape as [number, number, number];
176
+ let h = layer.inputNorm.forward(x);
177
+ let q = a.qProj.forward(h);
178
+ q = disposing(q, ops.reshape(q, [B, L, a.nHeads, a.headDim]));
179
+ q = disposing(q, a.qNorm.forward(q));
180
+ const offset = cache.offset;
181
+ let k = a.kProj!.forward(h);
182
+ k = disposing(k, ops.reshape(k, [B, L, a.nKvHeads, a.headDim]));
183
+ const kNormed = a.kNorm!.forward(k);
184
+ const kT = ops.transposeAxes(kNormed, [0, 2, 1, 3]);
185
+ kNormed.dispose();
186
+ const kRoped = a.rope(kT, cache.ropeOffsetArr ?? offset);
187
+ kT.dispose();
188
+ const vNormed = a.vNorm!.forward(k);
189
+ const vT = ops.transposeAxes(vNormed, [0, 2, 1, 3]);
190
+ vNormed.dispose();
191
+ k.dispose();
192
+ const [kq, vq] = cache.updateAndFetchQuantized(kRoped, vT);
193
+ kRoped.dispose();
194
+ vT.dispose();
195
+ q = disposing(q, ops.transposeAxes(q, [0, 2, 1, 3]));
196
+ q = disposing(q, a.rope(q, cache.ropeOffsetArr ?? offset));
197
+ // dispatch-site constants: bits=8 group_size=64 nRep=8 head_dim=512
198
+ const attn = (L > 1 || process.env.MLX_BUN_FUSED_DECODE === "1") && fusedSdpaRuntimeOk(q, mask)
199
+ ? quantizedSdpaTiled(q, kq, vq, 1.0, mask, 64, 8)
200
+ : quantizedSdpaUnfused(q, kq, vq, 1.0, mask, 64, 8);
201
+ q.dispose();
202
+ const attnT = ops.transposeAxes(attn, [0, 2, 1, 3]);
203
+ attn.dispose();
204
+ const merged = ops.reshape(attnT, [B, L, -1]);
205
+ attnT.dispose();
206
+ const out = a.oProj.forward(merged);
207
+ merged.dispose();
208
+ h.dispose();
209
+ h = out;
210
+ h = disposing(h, layer.postAttnNorm.forward(h));
211
+ h = disposing(h, ops.add(x, h));
212
+ const residual = h;
213
+ let h1 = layer.preFfNorm.forward(h);
214
+ h1 = disposing(h1, layer.mlp.forward(h1));
215
+ h1 = disposing(h1, layer.postFfNorm1!.forward(h1));
216
+ const { indices, weights: topKWeights } = layer.router!.forward(h);
217
+ let h2 = layer.preFfNorm2!.forward(h);
218
+ h2 = disposing(h2, layer.experts!.forward(h2, indices, topKWeights));
219
+ h2 = disposing(h2, layer.postFfNorm2!.forward(h2));
220
+ indices.dispose();
221
+ topKWeights.dispose();
222
+ let f = ops.add(h1, h2);
223
+ h1.dispose();
224
+ h2.dispose();
225
+ f = disposing(f, layer.postFfNorm.forward(f));
226
+ h = ops.add(residual, f);
227
+ residual.dispose();
228
+ f.dispose();
229
+ h = disposing(h, ops.mul(h, layer.layerScalar!));
230
+ for (const t of [kq, vq]) for (const c of [t.packed, t.scales, t.biases]) c.dispose();
231
+ return h;
232
+ }
233
+
234
+ function donorFullQuantG64B4KeqVMoeScal(layer: DecoderLayer, x: MlxArray, mask: Mask, cache: QuantizedKVCache): MlxArray {
235
+ const a = layer.attn;
236
+ const [B, L] = x.shape as [number, number, number];
237
+ let h = layer.inputNorm.forward(x);
238
+ let q = a.qProj.forward(h);
239
+ q = disposing(q, ops.reshape(q, [B, L, a.nHeads, a.headDim]));
240
+ q = disposing(q, a.qNorm.forward(q));
241
+ const offset = cache.offset;
242
+ let k = a.kProj!.forward(h);
243
+ k = disposing(k, ops.reshape(k, [B, L, a.nKvHeads, a.headDim]));
244
+ const kNormed = a.kNorm!.forward(k);
245
+ const kT = ops.transposeAxes(kNormed, [0, 2, 1, 3]);
246
+ kNormed.dispose();
247
+ const kRoped = a.rope(kT, cache.ropeOffsetArr ?? offset);
248
+ kT.dispose();
249
+ const vNormed = a.vNorm!.forward(k);
250
+ const vT = ops.transposeAxes(vNormed, [0, 2, 1, 3]);
251
+ vNormed.dispose();
252
+ k.dispose();
253
+ const [kq, vq] = cache.updateAndFetchQuantized(kRoped, vT);
254
+ kRoped.dispose();
255
+ vT.dispose();
256
+ q = disposing(q, ops.transposeAxes(q, [0, 2, 1, 3]));
257
+ q = disposing(q, a.rope(q, cache.ropeOffsetArr ?? offset));
258
+ // dispatch-site constants: bits=4 group_size=64 nRep=8 head_dim=512
259
+ const attn = (L > 1 || process.env.MLX_BUN_FUSED_DECODE === "1") && fusedSdpaRuntimeOk(q, mask)
260
+ ? quantizedSdpaTiled(q, kq, vq, 1.0, mask, 64, 4)
261
+ : quantizedSdpaUnfused(q, kq, vq, 1.0, mask, 64, 4);
262
+ q.dispose();
263
+ const attnT = ops.transposeAxes(attn, [0, 2, 1, 3]);
264
+ attn.dispose();
265
+ const merged = ops.reshape(attnT, [B, L, -1]);
266
+ attnT.dispose();
267
+ const out = a.oProj.forward(merged);
268
+ merged.dispose();
269
+ h.dispose();
270
+ h = out;
271
+ h = disposing(h, layer.postAttnNorm.forward(h));
272
+ h = disposing(h, ops.add(x, h));
273
+ const residual = h;
274
+ let h1 = layer.preFfNorm.forward(h);
275
+ h1 = disposing(h1, layer.mlp.forward(h1));
276
+ h1 = disposing(h1, layer.postFfNorm1!.forward(h1));
277
+ const { indices, weights: topKWeights } = layer.router!.forward(h);
278
+ let h2 = layer.preFfNorm2!.forward(h);
279
+ h2 = disposing(h2, layer.experts!.forward(h2, indices, topKWeights));
280
+ h2 = disposing(h2, layer.postFfNorm2!.forward(h2));
281
+ indices.dispose();
282
+ topKWeights.dispose();
283
+ let f = ops.add(h1, h2);
284
+ h1.dispose();
285
+ h2.dispose();
286
+ f = disposing(f, layer.postFfNorm.forward(f));
287
+ h = ops.add(residual, f);
288
+ residual.dispose();
289
+ f.dispose();
290
+ h = disposing(h, ops.mul(h, layer.layerScalar!));
291
+ for (const t of [kq, vq]) for (const c of [t.packed, t.scales, t.biases]) c.dispose();
292
+ return h;
293
+ }
294
+
295
+ export class GeneratedGemma4 extends Gemma4Model {
296
+ /** Per-layer cache classes must match what this file was generated
297
+ * for; anything else runs the monolith path. */
298
+ #matches(cache: Cache[]): boolean {
299
+ return (
300
+ cache.length === 30 &&
301
+ cache[0] instanceof RotatingQuantizedKVCache &&
302
+ cache[0].bits === 8 &&
303
+ cache[0].groupSize === 64 &&
304
+ cache[1] instanceof RotatingQuantizedKVCache &&
305
+ cache[1].bits === 4 &&
306
+ cache[1].groupSize === 64 &&
307
+ cache[2] instanceof RotatingQuantizedKVCache &&
308
+ cache[2].bits === 4 &&
309
+ cache[2].groupSize === 64 &&
310
+ cache[3] instanceof RotatingQuantizedKVCache &&
311
+ cache[3].bits === 8 &&
312
+ cache[3].groupSize === 64 &&
313
+ cache[4] instanceof RotatingQuantizedKVCache &&
314
+ cache[4].bits === 8 &&
315
+ cache[4].groupSize === 64 &&
316
+ cache[5] instanceof QuantizedKVCache &&
317
+ cache[5].bits === 8 &&
318
+ cache[5].groupSize === 64 &&
319
+ cache[6] instanceof RotatingQuantizedKVCache &&
320
+ cache[6].bits === 4 &&
321
+ cache[6].groupSize === 64 &&
322
+ cache[7] instanceof RotatingQuantizedKVCache &&
323
+ cache[7].bits === 4 &&
324
+ cache[7].groupSize === 64 &&
325
+ cache[8] instanceof RotatingQuantizedKVCache &&
326
+ cache[8].bits === 8 &&
327
+ cache[8].groupSize === 64 &&
328
+ cache[9] instanceof RotatingQuantizedKVCache &&
329
+ cache[9].bits === 8 &&
330
+ cache[9].groupSize === 64 &&
331
+ cache[10] instanceof RotatingQuantizedKVCache &&
332
+ cache[10].bits === 4 &&
333
+ cache[10].groupSize === 64 &&
334
+ cache[11] instanceof QuantizedKVCache &&
335
+ cache[11].bits === 8 &&
336
+ cache[11].groupSize === 64 &&
337
+ cache[12] instanceof RotatingQuantizedKVCache &&
338
+ cache[12].bits === 8 &&
339
+ cache[12].groupSize === 64 &&
340
+ cache[13] instanceof RotatingQuantizedKVCache &&
341
+ cache[13].bits === 4 &&
342
+ cache[13].groupSize === 64 &&
343
+ cache[14] instanceof RotatingQuantizedKVCache &&
344
+ cache[14].bits === 4 &&
345
+ cache[14].groupSize === 64 &&
346
+ cache[15] instanceof RotatingQuantizedKVCache &&
347
+ cache[15].bits === 4 &&
348
+ cache[15].groupSize === 64 &&
349
+ cache[16] instanceof RotatingQuantizedKVCache &&
350
+ cache[16].bits === 4 &&
351
+ cache[16].groupSize === 64 &&
352
+ cache[17] instanceof QuantizedKVCache &&
353
+ cache[17].bits === 4 &&
354
+ cache[17].groupSize === 64 &&
355
+ cache[18] instanceof RotatingQuantizedKVCache &&
356
+ cache[18].bits === 4 &&
357
+ cache[18].groupSize === 64 &&
358
+ cache[19] instanceof RotatingQuantizedKVCache &&
359
+ cache[19].bits === 4 &&
360
+ cache[19].groupSize === 64 &&
361
+ cache[20] instanceof RotatingQuantizedKVCache &&
362
+ cache[20].bits === 4 &&
363
+ cache[20].groupSize === 64 &&
364
+ cache[21] instanceof RotatingQuantizedKVCache &&
365
+ cache[21].bits === 4 &&
366
+ cache[21].groupSize === 64 &&
367
+ cache[22] instanceof RotatingQuantizedKVCache &&
368
+ cache[22].bits === 4 &&
369
+ cache[22].groupSize === 64 &&
370
+ cache[23] instanceof QuantizedKVCache &&
371
+ cache[23].bits === 4 &&
372
+ cache[23].groupSize === 64 &&
373
+ cache[24] instanceof RotatingQuantizedKVCache &&
374
+ cache[24].bits === 4 &&
375
+ cache[24].groupSize === 64 &&
376
+ cache[25] instanceof RotatingQuantizedKVCache &&
377
+ cache[25].bits === 4 &&
378
+ cache[25].groupSize === 64 &&
379
+ cache[26] instanceof RotatingQuantizedKVCache &&
380
+ cache[26].bits === 4 &&
381
+ cache[26].groupSize === 64 &&
382
+ cache[27] instanceof RotatingQuantizedKVCache &&
383
+ cache[27].bits === 4 &&
384
+ cache[27].groupSize === 64 &&
385
+ cache[28] instanceof RotatingQuantizedKVCache &&
386
+ cache[28].bits === 4 &&
387
+ cache[28].groupSize === 64 &&
388
+ cache[29] instanceof QuantizedKVCache &&
389
+ cache[29].bits === 4 &&
390
+ cache[29].groupSize === 64
391
+ );
392
+ }
393
+
394
+ protected override forwardLayers(
395
+ h0: MlxArray, cache: Cache[], bidir: MlxArray | null, ids: MlxArray | null,
396
+ ): MlxArray {
397
+ if (bidir !== null || !this.#matches(cache))
398
+ return super.forwardLayers(h0, cache, bidir, ids);
399
+ generatedForwardUses++;
400
+ const L = h0.shape[1]!;
401
+ const maskS = cache[0]!.makeMask(L, this.windowSize);
402
+ const maskF = cache[5]!.makeMask(L, null);
403
+ let h = h0;
404
+ let next: MlxArray;
405
+ next = donorSlidQuantG64B8VMoeScal(this.layers[0]!, h, maskS, cache[0] as RotatingQuantizedKVCache);
406
+ h.dispose();
407
+ h = next;
408
+ next = donorSlidQuantG64B4VMoeScal(this.layers[1]!, h, maskS, cache[1] as RotatingQuantizedKVCache);
409
+ h.dispose();
410
+ h = next;
411
+ next = donorSlidQuantG64B4VMoeScal(this.layers[2]!, h, maskS, cache[2] as RotatingQuantizedKVCache);
412
+ h.dispose();
413
+ h = next;
414
+ next = donorSlidQuantG64B8VMoeScal(this.layers[3]!, h, maskS, cache[3] as RotatingQuantizedKVCache);
415
+ h.dispose();
416
+ h = next;
417
+ next = donorSlidQuantG64B8VMoeScal(this.layers[4]!, h, maskS, cache[4] as RotatingQuantizedKVCache);
418
+ h.dispose();
419
+ h = next;
420
+ next = donorFullQuantG64B8KeqVMoeScal(this.layers[5]!, h, maskF, cache[5] as QuantizedKVCache);
421
+ h.dispose();
422
+ h = next;
423
+ next = donorSlidQuantG64B4VMoeScal(this.layers[6]!, h, maskS, cache[6] as RotatingQuantizedKVCache);
424
+ h.dispose();
425
+ h = next;
426
+ next = donorSlidQuantG64B4VMoeScal(this.layers[7]!, h, maskS, cache[7] as RotatingQuantizedKVCache);
427
+ h.dispose();
428
+ h = next;
429
+ next = donorSlidQuantG64B8VMoeScal(this.layers[8]!, h, maskS, cache[8] as RotatingQuantizedKVCache);
430
+ h.dispose();
431
+ h = next;
432
+ next = donorSlidQuantG64B8VMoeScal(this.layers[9]!, h, maskS, cache[9] as RotatingQuantizedKVCache);
433
+ h.dispose();
434
+ h = next;
435
+ next = donorSlidQuantG64B4VMoeScal(this.layers[10]!, h, maskS, cache[10] as RotatingQuantizedKVCache);
436
+ h.dispose();
437
+ h = next;
438
+ next = donorFullQuantG64B8KeqVMoeScal(this.layers[11]!, h, maskF, cache[11] as QuantizedKVCache);
439
+ h.dispose();
440
+ h = next;
441
+ next = donorSlidQuantG64B8VMoeScal(this.layers[12]!, h, maskS, cache[12] as RotatingQuantizedKVCache);
442
+ h.dispose();
443
+ h = next;
444
+ next = donorSlidQuantG64B4VMoeScal(this.layers[13]!, h, maskS, cache[13] as RotatingQuantizedKVCache);
445
+ h.dispose();
446
+ h = next;
447
+ next = donorSlidQuantG64B4VMoeScal(this.layers[14]!, h, maskS, cache[14] as RotatingQuantizedKVCache);
448
+ h.dispose();
449
+ h = next;
450
+ next = donorSlidQuantG64B4VMoeScal(this.layers[15]!, h, maskS, cache[15] as RotatingQuantizedKVCache);
451
+ h.dispose();
452
+ h = next;
453
+ next = donorSlidQuantG64B4VMoeScal(this.layers[16]!, h, maskS, cache[16] as RotatingQuantizedKVCache);
454
+ h.dispose();
455
+ h = next;
456
+ next = donorFullQuantG64B4KeqVMoeScal(this.layers[17]!, h, maskF, cache[17] as QuantizedKVCache);
457
+ h.dispose();
458
+ h = next;
459
+ next = donorSlidQuantG64B4VMoeScal(this.layers[18]!, h, maskS, cache[18] as RotatingQuantizedKVCache);
460
+ h.dispose();
461
+ h = next;
462
+ next = donorSlidQuantG64B4VMoeScal(this.layers[19]!, h, maskS, cache[19] as RotatingQuantizedKVCache);
463
+ h.dispose();
464
+ h = next;
465
+ next = donorSlidQuantG64B4VMoeScal(this.layers[20]!, h, maskS, cache[20] as RotatingQuantizedKVCache);
466
+ h.dispose();
467
+ h = next;
468
+ next = donorSlidQuantG64B4VMoeScal(this.layers[21]!, h, maskS, cache[21] as RotatingQuantizedKVCache);
469
+ h.dispose();
470
+ h = next;
471
+ next = donorSlidQuantG64B4VMoeScal(this.layers[22]!, h, maskS, cache[22] as RotatingQuantizedKVCache);
472
+ h.dispose();
473
+ h = next;
474
+ next = donorFullQuantG64B4KeqVMoeScal(this.layers[23]!, h, maskF, cache[23] as QuantizedKVCache);
475
+ h.dispose();
476
+ h = next;
477
+ next = donorSlidQuantG64B4VMoeScal(this.layers[24]!, h, maskS, cache[24] as RotatingQuantizedKVCache);
478
+ h.dispose();
479
+ h = next;
480
+ next = donorSlidQuantG64B4VMoeScal(this.layers[25]!, h, maskS, cache[25] as RotatingQuantizedKVCache);
481
+ h.dispose();
482
+ h = next;
483
+ next = donorSlidQuantG64B4VMoeScal(this.layers[26]!, h, maskS, cache[26] as RotatingQuantizedKVCache);
484
+ h.dispose();
485
+ h = next;
486
+ next = donorSlidQuantG64B4VMoeScal(this.layers[27]!, h, maskS, cache[27] as RotatingQuantizedKVCache);
487
+ h.dispose();
488
+ h = next;
489
+ next = donorSlidQuantG64B4VMoeScal(this.layers[28]!, h, maskS, cache[28] as RotatingQuantizedKVCache);
490
+ h.dispose();
491
+ h = next;
492
+ next = donorFullQuantG64B4KeqVMoeScal(this.layers[29]!, h, maskF, cache[29] as QuantizedKVCache);
493
+ h.dispose();
494
+ h = next;
495
+
496
+ maskS.arr?.dispose();
497
+ maskF.arr?.dispose();
498
+ return disposing(h, this.finalNorm.forward(h));
499
+ }
500
+ }