@seanhogg/builderforce-memory-engine 2026.7.14 → 2026.9.27

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 (186) hide show
  1. package/README.md +14 -0
  2. package/dist/bench/adaptation.d.ts +57 -0
  3. package/dist/bench/adaptation.d.ts.map +1 -0
  4. package/dist/bench/adaptation.js +167 -0
  5. package/dist/bench/adaptation.js.map +1 -0
  6. package/dist/bench/harness.d.ts +2 -0
  7. package/dist/bench/harness.d.ts.map +1 -1
  8. package/dist/bench/harness.js +1 -1
  9. package/dist/bench/harness.js.map +1 -1
  10. package/dist/bench/index.d.ts +5 -3
  11. package/dist/bench/index.d.ts.map +1 -1
  12. package/dist/bench/index.js +4 -2
  13. package/dist/bench/index.js.map +1 -1
  14. package/dist/bench/types.d.ts +88 -0
  15. package/dist/bench/types.d.ts.map +1 -1
  16. package/dist/evermind/adapt.d.ts +40 -0
  17. package/dist/evermind/adapt.d.ts.map +1 -0
  18. package/dist/evermind/adapt.js +25 -0
  19. package/dist/evermind/adapt.js.map +1 -0
  20. package/dist/evermind/delta_wire.d.ts +43 -0
  21. package/dist/evermind/delta_wire.d.ts.map +1 -0
  22. package/dist/evermind/delta_wire.js +94 -0
  23. package/dist/evermind/delta_wire.js.map +1 -0
  24. package/dist/evermind/eval.d.ts +31 -0
  25. package/dist/evermind/eval.d.ts.map +1 -0
  26. package/dist/evermind/eval.js +36 -0
  27. package/dist/evermind/eval.js.map +1 -0
  28. package/dist/evermind/index.d.ts +16 -0
  29. package/dist/evermind/index.d.ts.map +1 -0
  30. package/dist/evermind/index.js +11 -0
  31. package/dist/evermind/index.js.map +1 -0
  32. package/dist/evermind/merge.d.ts +21 -0
  33. package/dist/evermind/merge.d.ts.map +1 -0
  34. package/dist/evermind/merge.js +79 -0
  35. package/dist/evermind/merge.js.map +1 -0
  36. package/dist/{moe/moe_package.d.ts → evermind/package.d.ts} +55 -5
  37. package/dist/evermind/package.d.ts.map +1 -0
  38. package/dist/{moe/moe_package.js → evermind/package.js} +118 -19
  39. package/dist/evermind/package.js.map +1 -0
  40. package/dist/import/foreign/adapter.d.ts +59 -0
  41. package/dist/import/foreign/adapter.d.ts.map +1 -0
  42. package/dist/import/foreign/adapter.js +76 -0
  43. package/dist/import/foreign/adapter.js.map +1 -0
  44. package/dist/import/foreign/apply.d.ts +23 -0
  45. package/dist/import/foreign/apply.d.ts.map +1 -0
  46. package/dist/import/foreign/apply.js +43 -0
  47. package/dist/import/foreign/apply.js.map +1 -0
  48. package/dist/import/foreign/codestral_mamba.d.ts +57 -0
  49. package/dist/import/foreign/codestral_mamba.d.ts.map +1 -0
  50. package/dist/import/foreign/codestral_mamba.js +174 -0
  51. package/dist/import/foreign/codestral_mamba.js.map +1 -0
  52. package/dist/import/foreign/falcon_mamba.d.ts +51 -0
  53. package/dist/import/foreign/falcon_mamba.d.ts.map +1 -0
  54. package/dist/import/foreign/falcon_mamba.js +131 -0
  55. package/dist/import/foreign/falcon_mamba.js.map +1 -0
  56. package/dist/import/foreign/index.d.ts +21 -0
  57. package/dist/import/foreign/index.d.ts.map +1 -0
  58. package/dist/import/foreign/index.js +18 -0
  59. package/dist/import/foreign/index.js.map +1 -0
  60. package/dist/import/foreign/plan.d.ts +122 -0
  61. package/dist/import/foreign/plan.d.ts.map +1 -0
  62. package/dist/import/foreign/plan.js +171 -0
  63. package/dist/import/foreign/plan.js.map +1 -0
  64. package/dist/import/foreign/registry.d.ts +35 -0
  65. package/dist/import/foreign/registry.d.ts.map +1 -0
  66. package/dist/import/foreign/registry.js +89 -0
  67. package/dist/import/foreign/registry.js.map +1 -0
  68. package/dist/import/index.d.ts +7 -0
  69. package/dist/import/index.d.ts.map +1 -1
  70. package/dist/import/index.js +7 -0
  71. package/dist/import/index.js.map +1 -1
  72. package/dist/index.d.ts +25 -12
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +21 -9
  75. package/dist/index.js.map +1 -1
  76. package/dist/kernels/selective_scan.d.ts.map +1 -1
  77. package/dist/kernels/selective_scan.js +15 -9
  78. package/dist/kernels/selective_scan.js.map +1 -1
  79. package/dist/kernels/slice.d.ts +26 -0
  80. package/dist/kernels/slice.d.ts.map +1 -0
  81. package/dist/kernels/slice.js +52 -0
  82. package/dist/kernels/slice.js.map +1 -0
  83. package/dist/kernels/weight_update.d.ts.map +1 -1
  84. package/dist/kernels/weight_update.js +30 -4
  85. package/dist/kernels/weight_update.js.map +1 -1
  86. package/dist/lm/evermind_lm.d.ts +110 -1
  87. package/dist/lm/evermind_lm.d.ts.map +1 -1
  88. package/dist/lm/evermind_lm.js +220 -35
  89. package/dist/lm/evermind_lm.js.map +1 -1
  90. package/dist/lm/index.d.ts +4 -2
  91. package/dist/lm/index.d.ts.map +1 -1
  92. package/dist/lm/index.js +3 -1
  93. package/dist/lm/index.js.map +1 -1
  94. package/dist/lm/text_embedder.d.ts +55 -0
  95. package/dist/lm/text_embedder.d.ts.map +1 -0
  96. package/dist/lm/text_embedder.js +62 -0
  97. package/dist/lm/text_embedder.js.map +1 -0
  98. package/dist/model/attention_block.d.ts.map +1 -1
  99. package/dist/model/attention_block.js +9 -5
  100. package/dist/model/attention_block.js.map +1 -1
  101. package/dist/model/mamba1_block.d.ts.map +1 -1
  102. package/dist/model/mamba1_block.js +28 -12
  103. package/dist/model/mamba1_block.js.map +1 -1
  104. package/dist/model/mamba2_block.d.ts.map +1 -1
  105. package/dist/model/mamba2_block.js +14 -9
  106. package/dist/model/mamba2_block.js.map +1 -1
  107. package/dist/model/mamba3_block.d.ts.map +1 -1
  108. package/dist/model/mamba3_block.js +14 -9
  109. package/dist/model/mamba3_block.js.map +1 -1
  110. package/dist/moe/index.d.ts +0 -2
  111. package/dist/moe/index.d.ts.map +1 -1
  112. package/dist/moe/index.js +0 -1
  113. package/dist/moe/index.js.map +1 -1
  114. package/dist/optim/adamw.d.ts +32 -0
  115. package/dist/optim/adamw.d.ts.map +1 -1
  116. package/dist/optim/adamw.js +34 -0
  117. package/dist/optim/adamw.js.map +1 -1
  118. package/dist/tokenizer/bpe.d.ts +28 -0
  119. package/dist/tokenizer/bpe.d.ts.map +1 -1
  120. package/dist/tokenizer/bpe.js +47 -0
  121. package/dist/tokenizer/bpe.js.map +1 -1
  122. package/dist/training/cpu_ops.d.ts +44 -0
  123. package/dist/training/cpu_ops.d.ts.map +1 -0
  124. package/dist/training/cpu_ops.js +111 -0
  125. package/dist/training/cpu_ops.js.map +1 -0
  126. package/dist/training/mamba1_cpu.d.ts +109 -0
  127. package/dist/training/mamba1_cpu.d.ts.map +1 -0
  128. package/dist/training/mamba1_cpu.js +316 -0
  129. package/dist/training/mamba1_cpu.js.map +1 -0
  130. package/dist/training/model_cpu.d.ts +100 -0
  131. package/dist/training/model_cpu.d.ts.map +1 -0
  132. package/dist/training/model_cpu.js +252 -0
  133. package/dist/training/model_cpu.js.map +1 -0
  134. package/dist/training/trainer.d.ts +156 -16
  135. package/dist/training/trainer.d.ts.map +1 -1
  136. package/dist/training/trainer.js +327 -101
  137. package/dist/training/trainer.js.map +1 -1
  138. package/dist/utils/base64.d.ts +12 -0
  139. package/dist/utils/base64.d.ts.map +1 -0
  140. package/dist/utils/base64.js +27 -0
  141. package/dist/utils/base64.js.map +1 -0
  142. package/package.json +3 -1
  143. package/src/bench/adaptation.ts +180 -0
  144. package/src/bench/harness.ts +1 -1
  145. package/src/bench/index.ts +13 -2
  146. package/src/bench/types.ts +93 -0
  147. package/src/evermind/adapt.ts +61 -0
  148. package/src/evermind/delta_wire.ts +114 -0
  149. package/src/evermind/eval.ts +62 -0
  150. package/src/evermind/index.ts +33 -0
  151. package/src/evermind/merge.ts +106 -0
  152. package/src/{moe/moe_package.ts → evermind/package.ts} +148 -17
  153. package/src/import/foreign/adapter.ts +106 -0
  154. package/src/import/foreign/apply.ts +54 -0
  155. package/src/import/foreign/codestral_mamba.ts +224 -0
  156. package/src/import/foreign/falcon_mamba.ts +173 -0
  157. package/src/import/foreign/index.ts +37 -0
  158. package/src/import/foreign/plan.ts +294 -0
  159. package/src/import/foreign/registry.ts +126 -0
  160. package/src/import/index.ts +30 -0
  161. package/src/index.ts +98 -13
  162. package/src/kernels/selective_scan.ts +15 -9
  163. package/src/kernels/slice.ts +64 -0
  164. package/src/kernels/weight_update.ts +30 -4
  165. package/src/lm/evermind_lm.ts +244 -34
  166. package/src/lm/index.ts +6 -2
  167. package/src/lm/text_embedder.ts +84 -0
  168. package/src/model/attention_block.ts +9 -5
  169. package/src/model/mamba1_block.ts +28 -12
  170. package/src/model/mamba2_block.ts +14 -9
  171. package/src/model/mamba3_block.ts +14 -9
  172. package/src/moe/index.ts +0 -9
  173. package/src/optim/adamw.ts +60 -0
  174. package/src/tokenizer/bpe.ts +55 -0
  175. package/src/training/cpu_ops.ts +127 -0
  176. package/src/training/mamba1_cpu.ts +421 -0
  177. package/src/training/model_cpu.ts +360 -0
  178. package/src/training/trainer.ts +397 -154
  179. package/src/utils/base64.ts +28 -0
  180. package/dist/model/mamba_block.d.ts +0 -64
  181. package/dist/model/mamba_block.d.ts.map +0 -1
  182. package/dist/model/mamba_block.js +0 -303
  183. package/dist/model/mamba_block.js.map +0 -1
  184. package/dist/moe/moe_package.d.ts.map +0 -1
  185. package/dist/moe/moe_package.js.map +0 -1
  186. package/src/model/mamba_block.ts +0 -401
@@ -0,0 +1,224 @@
1
+ /**
2
+ * import/foreign/codestral_mamba.ts — weight port for Codestral-Mamba
3
+ * (`mistralai/Mamba-Codestral-7B-v0.1`, `Mamba2ForCausalLM`,
4
+ * `model_type: "mamba2"`, Mamba-2 / SSD).
5
+ *
6
+ * Source layout confirmed against the repo's published HF `config.json`, its
7
+ * `model.safetensors.index.json` (579 tensors = 9 per layer × 64 + 3 globals),
8
+ * the header of `consolidated.safetensors`, and
9
+ * `transformers/models/mamba2/modeling_mamba2.py`:
10
+ *
11
+ * backbone.embeddings.weight [vocab, d_model]
12
+ * backbone.layers.{N}.norm.weight [d_model]
13
+ * backbone.layers.{N}.mixer.in_proj.weight [2*d_inner + 2*n_groups*d_state + n_heads, d_model]
14
+ * backbone.layers.{N}.mixer.conv1d.weight [conv_dim, 1, d_conv]
15
+ * backbone.layers.{N}.mixer.conv1d.bias [conv_dim]
16
+ * backbone.layers.{N}.mixer.dt_bias [n_heads]
17
+ * backbone.layers.{N}.mixer.A_log [n_heads]
18
+ * backbone.layers.{N}.mixer.D [n_heads]
19
+ * backbone.layers.{N}.mixer.norm.weight [d_inner]
20
+ * backbone.layers.{N}.mixer.out_proj.weight [d_model, d_inner]
21
+ * backbone.norm_f.weight [d_model]
22
+ * lm_head.weight [vocab, d_model]
23
+ *
24
+ * where `conv_dim = d_inner + 2 * n_groups * d_state`. Mamba-2 has no `x_proj`
25
+ * and no `dt_proj`: B, C and dt all come out of the fused `in_proj`.
26
+ *
27
+ * Three reconciliations against `Mamba2Block`:
28
+ *
29
+ * 1. **`in_proj` row order.** Upstream splits
30
+ * `[gate (d_inner), x|B|C (conv_dim), dt (n_heads)]`; this engine's fused
31
+ * projection is `[x (d_inner), B (n_groups*d_state), C (n_groups*d_state),
32
+ * dt (n_heads)]` — the SAME tail, minus the leading gate rows. So the port
33
+ * is one contiguous row slice starting at `d_inner`, and the gate rows are
34
+ * declared as a discard (see 3).
35
+ * 2. **`A_log` convention.** Upstream uses `A = -exp(A_log)`; `ssd.ts` uses
36
+ * `A = -softplus(A_log)`. The port re-expresses the same `A` as
37
+ * `softplus⁻¹(exp(A_log))` so decay rates are preserved exactly, rather than
38
+ * copying the raw value and silently changing every head's decay.
39
+ * 3. **The gate branch.** `Mamba2Block` has no `z` gate: it RMS-norms the scan
40
+ * output and projects out, where upstream computes
41
+ * `norm(y * silu(z))`. The `d_inner × d_model` gate rows therefore have no
42
+ * target. That is a REAL loss of capability, not a formatting detail, and it
43
+ * is reported as a `PortDiscard` on every layer so a caller sees it.
44
+ *
45
+ * Also mapped without transform: `mixer.norm.weight` → the block's inner
46
+ * `normWeight` (applied ungated here, per 3), `backbone.layers.N.norm.weight` →
47
+ * `preNormWeight`, `conv1d.{weight,bias}` (depthwise, taps reversed) → the fused
48
+ * `[x, B, C]` conv, and `D` / `dt_bias` per head. Linear weights are
49
+ * `[out, in]` row-major on both sides, so no transposes.
50
+ *
51
+ * `tie_word_embeddings: false`, so `lm_head.weight` is a real stored tensor with
52
+ * no target here (`HybridMambaModel` ties its head to the embedding) — it is
53
+ * reported as unmapped.
54
+ */
55
+
56
+ import type { HybridMambaModelConfig, LayerSpec } from "../../model/mamba_model.js";
57
+ import type { PortDiscard, PortPlan, PortRule } from "./plan.js";
58
+ import {
59
+ expandFactor,
60
+ firstInt,
61
+ readInnerSize,
62
+ requireInt,
63
+ type ForeignConfig,
64
+ type ForeignMambaAdapter,
65
+ type PortTarget,
66
+ } from "./adapter.js";
67
+
68
+ const ID = "codestral_mamba";
69
+
70
+ /** `backbone.embeddings` (HF) vs `backbone.embedding` (Mistral-native). */
71
+ const EMBEDDING_NAMES = ["backbone.embeddings.weight", "backbone.embedding.weight"];
72
+
73
+ interface Mamba2Geometry {
74
+ vocabSize: number;
75
+ dModel: number;
76
+ numLayers: number;
77
+ dInner: number;
78
+ dState: number;
79
+ dConv: number;
80
+ nHeads: number;
81
+ nGroups: number;
82
+ chunkLen: number;
83
+ }
84
+
85
+ function rules(a: Mamba2Geometry): PortRule[] {
86
+ const { vocabSize: V, dModel: E, numLayers: L, dInner: D, dState: N, dConv: K, nHeads: H, nGroups: G } = a;
87
+ const convDim = D + 2 * G * N;
88
+ /** Rows this engine keeps out of the fused projection: [x, B, C, dt]. */
89
+ const keptRows = convDim + H;
90
+
91
+ const out: PortRule[] = [
92
+ { target: "embedding", shape: [V, E], from: EMBEDDING_NAMES, op: { kind: "copy" } },
93
+ ];
94
+
95
+ for (let i = 0; i < L; i++) {
96
+ const m = `backbone.layers.${i}.mixer`;
97
+ const t = `layer${i}`;
98
+ out.push(
99
+ {
100
+ target: `${t}.wInProj`,
101
+ shape: [keptRows, E],
102
+ from: [`${m}.in_proj.weight`],
103
+ // Drop the leading gate rows; keep [x, B, C, dt] verbatim.
104
+ op: { kind: "rowSlice", start: D, count: keptRows },
105
+ note: "upstream rows are [gate, x, B, C, dt]; this block has no gate branch",
106
+ },
107
+ {
108
+ target: `${t}.wConv`,
109
+ shape: [convDim, K],
110
+ from: [`${m}.conv1d.weight`],
111
+ op: { kind: "convTaps" },
112
+ note: "depthwise [conv_dim, 1, d_conv] → [conv_dim, d_conv] with the tap axis reversed",
113
+ },
114
+ { target: `${t}.bConv`, shape: [convDim], from: [`${m}.conv1d.bias`], op: { kind: "copy" } },
115
+ {
116
+ target: `${t}.A_log`,
117
+ shape: [H],
118
+ from: [`${m}.A_log`],
119
+ op: { kind: "negExpToSoftplusInv" },
120
+ note: "upstream A = -exp(A_log); this engine's SSD kernel uses A = -softplus(A_log)",
121
+ },
122
+ { target: `${t}.dt_bias`, shape: [H], from: [`${m}.dt_bias`], op: { kind: "copy" } },
123
+ { target: `${t}.D_vec`, shape: [H], from: [`${m}.D`], op: { kind: "copy" } },
124
+ { target: `${t}.wOutProj`, shape: [E, D], from: [`${m}.out_proj.weight`], op: { kind: "copy" } },
125
+ {
126
+ target: `${t}.normWeight`,
127
+ shape: [D],
128
+ from: [`${m}.norm.weight`],
129
+ op: { kind: "copy" },
130
+ note: "upstream this gain belongs to a GATED RMSNorm; applied ungated here",
131
+ },
132
+ {
133
+ target: `${t}.preNormWeight`,
134
+ shape: [E],
135
+ from: [`backbone.layers.${i}.norm.weight`],
136
+ op: { kind: "copy" },
137
+ },
138
+ );
139
+ }
140
+
141
+ out.push({ target: "final_norm", shape: [E], from: ["backbone.norm_f.weight"], op: { kind: "copy" } });
142
+ return out;
143
+ }
144
+
145
+ function discards(a: Mamba2Geometry): PortDiscard[] {
146
+ const out: PortDiscard[] = [];
147
+ for (let i = 0; i < a.numLayers; i++) {
148
+ out.push({
149
+ source: `backbone.layers.${i}.mixer.in_proj.weight`,
150
+ elements: a.dInner * a.dModel,
151
+ reason:
152
+ "the leading d_inner gate (z) rows — Mamba2Block computes norm(y) rather than " +
153
+ "norm(y * silu(z)), so it has no gate branch to receive them",
154
+ });
155
+ }
156
+ return out;
157
+ }
158
+
159
+ export const codestralMambaAdapter: ForeignMambaAdapter = {
160
+ id: ID,
161
+ label: "Codestral-Mamba (Mamba-2 / SSD)",
162
+ modelTypes: ["mamba2"],
163
+ // `MambaCodestralForCausalLM` is not a transformers class — the published
164
+ // config says `Mamba2ForCausalLM` — but it is a common mis-citation, so it is
165
+ // accepted here rather than sending a correct checkpoint down the error path.
166
+ architectures: ["Mamba2ForCausalLM", "MambaCodestralForCausalLM"],
167
+
168
+ describe(config: ForeignConfig): PortTarget {
169
+ const dModel = requireInt(config, "hidden_size");
170
+ const numLayers = requireInt(config, "num_hidden_layers");
171
+ const vocabSize = requireInt(config, "vocab_size");
172
+ const dState = requireInt(config, "state_size");
173
+ const dConv = requireInt(config, "conv_kernel");
174
+ const nHeads = requireInt(config, "num_heads");
175
+ const nGroups = firstInt(config, ["n_groups"]) ?? 1;
176
+ const chunkLen = firstInt(config, ["chunk_size"]) ?? 256;
177
+ const dInner = readInnerSize(config, dModel);
178
+ const expand = expandFactor(dInner, dModel, "Codestral-Mamba");
179
+
180
+ // Upstream's own invariant (`hidden_size * expand == num_heads * head_dim`);
181
+ // Mamba2Block enforces the same divisibility, so check it here where the
182
+ // message can name the config fields that disagree.
183
+ const headDim = firstInt(config, ["head_dim"]);
184
+ if (dInner % nHeads !== 0) {
185
+ throw new Error(
186
+ `import/foreign: Codestral-Mamba d_inner ${dInner} is not divisible by num_heads ${nHeads}`,
187
+ );
188
+ }
189
+ if (headDim !== undefined && headDim * nHeads !== dInner) {
190
+ throw new Error(
191
+ `import/foreign: Codestral-Mamba config is inconsistent — head_dim ${headDim} × ` +
192
+ `num_heads ${nHeads} = ${headDim * nHeads}, but d_inner is ${dInner}`,
193
+ );
194
+ }
195
+
196
+ const layers: LayerSpec[] = Array.from({ length: numLayers }, () => ({ type: "mamba2" as const }));
197
+ const modelConfig: HybridMambaModelConfig = {
198
+ vocabSize,
199
+ dModel,
200
+ numLayers,
201
+ layers,
202
+ dState,
203
+ dConv,
204
+ expand,
205
+ nHeads,
206
+ nGroups,
207
+ chunkLen,
208
+ };
209
+
210
+ const geometry: Mamba2Geometry = {
211
+ vocabSize,
212
+ dModel,
213
+ numLayers,
214
+ dInner,
215
+ dState,
216
+ dConv,
217
+ nHeads,
218
+ nGroups,
219
+ chunkLen,
220
+ };
221
+
222
+ return { modelConfig, plan: { adapter: ID, rules: rules(geometry), discards: discards(geometry) } };
223
+ },
224
+ };
@@ -0,0 +1,173 @@
1
+ /**
2
+ * import/foreign/falcon_mamba.ts — weight port for Falcon-Mamba
3
+ * (`FalconMambaForCausalLM`, `model_type: "falcon_mamba"`, Mamba-1 / S6).
4
+ *
5
+ * Source layout confirmed against `tiiuae/falcon-mamba-7b`'s published
6
+ * `config.json`, `model.safetensors.index.json` (643 tensors = 10 per layer × 64
7
+ * + 3 globals) and the safetensors header of shard 1, plus
8
+ * `transformers/models/falcon_mamba/modeling_falcon_mamba.py`:
9
+ *
10
+ * backbone.embeddings.weight [vocab, d_model]
11
+ * backbone.layers.{N}.norm.weight [d_model]
12
+ * backbone.layers.{N}.mixer.in_proj.weight [2*d_inner, d_model]
13
+ * backbone.layers.{N}.mixer.conv1d.weight [d_inner, 1, d_conv]
14
+ * backbone.layers.{N}.mixer.conv1d.bias [d_inner]
15
+ * backbone.layers.{N}.mixer.x_proj.weight [dt_rank + 2*d_state, d_inner]
16
+ * backbone.layers.{N}.mixer.dt_proj.weight [d_inner, dt_rank]
17
+ * backbone.layers.{N}.mixer.dt_proj.bias [d_inner]
18
+ * backbone.layers.{N}.mixer.A_log [d_inner, d_state]
19
+ * backbone.layers.{N}.mixer.D [d_inner]
20
+ * backbone.layers.{N}.mixer.out_proj.weight [d_model, d_inner]
21
+ * backbone.norm_f.weight [d_model]
22
+ * lm_head.weight [vocab, d_model]
23
+ *
24
+ * Conventions that line up with `Mamba1Block` as-is, so most rules are copies:
25
+ * • `in_proj` rows are `[x, gate]` (`hidden_states, gate = …chunk(2, dim=1)`),
26
+ * and `Mamba1Block.forward` also takes the first half as `x` and the second
27
+ * as the gate `z`.
28
+ * • `x_proj` rows are `[dt, B, C]`, matching the block's split order.
29
+ * • `A = -exp(A_log)` in both — `selective_scan.ts` computes
30
+ * `a_cont = -exp(clamp(a_log, -10, 5))`.
31
+ * • `dt_proj.bias` is added inside `softplus(dt + bias)` upstream; here it is
32
+ * the `dt_proj` linear's bias and the scan applies `softplus` afterwards —
33
+ * algebraically the same value.
34
+ * • Linear weights are `[out, in]` row-major on both sides (no transpose).
35
+ *
36
+ * Fidelity caveats recorded on the plan rather than hidden:
37
+ * • `use_bias: false` upstream, so `in_proj` / `x_proj` / `out_proj` ship no
38
+ * bias; this engine's blocks always own one, and they are filled with zeros
39
+ * (an exact no-op, not an approximation).
40
+ * • Falcon-Mamba RMS-normalises `dt`, `B` and `C` inside the mixer. Those
41
+ * norms are `FalconMambaWeightlessRMSNorm` with `persistent=False` buffers,
42
+ * so they contribute NO tensors to the checkpoint — nothing is dropped from
43
+ * the file — but this engine's S6 scan has no such normalisation step, so a
44
+ * ported model is not numerically identical to the original.
45
+ * • `tie_word_embeddings: false`, so `lm_head.weight` is a real stored tensor.
46
+ * `HybridMambaModel` always ties its LM head to the embedding table, so that
47
+ * tensor has no target and is reported as unmapped.
48
+ */
49
+
50
+ import type { HybridMambaModelConfig } from "../../model/mamba_model.js";
51
+ import type { PortPlan, PortRule } from "./plan.js";
52
+ import {
53
+ expandFactor,
54
+ readInnerSize,
55
+ readTimeStepRank,
56
+ requireInt,
57
+ type ForeignConfig,
58
+ type ForeignMambaAdapter,
59
+ type PortTarget,
60
+ } from "./adapter.js";
61
+
62
+ const ID = "falcon_mamba";
63
+
64
+ /** `backbone.embeddings` (HF) vs `backbone.embedding` (Mamba-SSM native). */
65
+ const EMBEDDING_NAMES = ["backbone.embeddings.weight", "backbone.embedding.weight"];
66
+
67
+ function rules(a: {
68
+ vocabSize: number;
69
+ dModel: number;
70
+ numLayers: number;
71
+ dInner: number;
72
+ dState: number;
73
+ dConv: number;
74
+ dtRank: number;
75
+ }): PortRule[] {
76
+ const { vocabSize: V, dModel: E, numLayers: L, dInner: D, dState: N, dConv: K, dtRank: R } = a;
77
+ const out: PortRule[] = [
78
+ { target: "embedding", shape: [V, E], from: EMBEDDING_NAMES, op: { kind: "copy" } },
79
+ ];
80
+
81
+ for (let i = 0; i < L; i++) {
82
+ const m = `backbone.layers.${i}.mixer`;
83
+ const t = `layer${i}`;
84
+ out.push(
85
+ { target: `${t}.wInProj`, shape: [2 * D, E], from: [`${m}.in_proj.weight`], op: { kind: "copy" } },
86
+ {
87
+ target: `${t}.bInProj`,
88
+ shape: [2 * D],
89
+ from: [],
90
+ op: { kind: "fill", value: 0 },
91
+ note: "Falcon-Mamba sets use_bias=false — in_proj ships no bias; zeros are exact",
92
+ },
93
+ {
94
+ target: `${t}.wConv`,
95
+ shape: [D, K],
96
+ from: [`${m}.conv1d.weight`],
97
+ op: { kind: "convTaps" },
98
+ note: "depthwise [d_inner, 1, d_conv] → [d_inner, d_conv] with the tap axis reversed",
99
+ },
100
+ { target: `${t}.bConv`, shape: [D], from: [`${m}.conv1d.bias`], op: { kind: "copy" } },
101
+ { target: `${t}.wXProj`, shape: [R + 2 * N, D], from: [`${m}.x_proj.weight`], op: { kind: "copy" } },
102
+ {
103
+ target: `${t}.bXProj`,
104
+ shape: [R + 2 * N],
105
+ from: [],
106
+ op: { kind: "fill", value: 0 },
107
+ note: "x_proj is bias-free upstream; zeros are exact",
108
+ },
109
+ { target: `${t}.wDtProj`, shape: [D, R], from: [`${m}.dt_proj.weight`], op: { kind: "copy" } },
110
+ { target: `${t}.bDtProj`, shape: [D], from: [`${m}.dt_proj.bias`], op: { kind: "copy" } },
111
+ { target: `${t}.A_log`, shape: [D, N], from: [`${m}.A_log`], op: { kind: "copy" } },
112
+ { target: `${t}.D_vec`, shape: [D], from: [`${m}.D`], op: { kind: "copy" } },
113
+ { target: `${t}.wOutProj`, shape: [E, D], from: [`${m}.out_proj.weight`], op: { kind: "copy" } },
114
+ {
115
+ target: `${t}.bOutProj`,
116
+ shape: [E],
117
+ from: [],
118
+ op: { kind: "fill", value: 0 },
119
+ note: "out_proj is bias-free upstream; zeros are exact",
120
+ },
121
+ {
122
+ target: `${t}.normWeight`,
123
+ shape: [E],
124
+ from: [`backbone.layers.${i}.norm.weight`],
125
+ op: { kind: "copy" },
126
+ },
127
+ );
128
+ }
129
+
130
+ out.push({ target: "final_norm", shape: [E], from: ["backbone.norm_f.weight"], op: { kind: "copy" } });
131
+ return out;
132
+ }
133
+
134
+ export const falconMambaAdapter: ForeignMambaAdapter = {
135
+ id: ID,
136
+ label: "Falcon-Mamba (Mamba-1 / S6)",
137
+ modelTypes: ["falcon_mamba"],
138
+ architectures: ["FalconMambaForCausalLM"],
139
+
140
+ describe(config: ForeignConfig): PortTarget {
141
+ const dModel = requireInt(config, "hidden_size");
142
+ const numLayers = requireInt(config, "num_hidden_layers");
143
+ const vocabSize = requireInt(config, "vocab_size");
144
+ const dState = requireInt(config, "state_size");
145
+ const dConv = requireInt(config, "conv_kernel");
146
+ const dInner = readInnerSize(config, dModel);
147
+ const expand = expandFactor(dInner, dModel, "Falcon-Mamba");
148
+ const dtRank = readTimeStepRank(config, dModel);
149
+
150
+ const modelConfig: HybridMambaModelConfig = {
151
+ vocabSize,
152
+ dModel,
153
+ numLayers,
154
+ dState,
155
+ dConv,
156
+ expand,
157
+ // Every layer is a Mamba-1 mixer (the model's default schedule), but the
158
+ // dt rank and conv bias are per-block settings the shorthand can't carry.
159
+ defaultMamba1: { dtRank, biasConv: true },
160
+ };
161
+
162
+ const plan: PortPlan = {
163
+ adapter: ID,
164
+ rules: rules({ vocabSize, dModel, numLayers, dInner, dState, dConv, dtRank }),
165
+ // Nothing is partially consumed: every Falcon-Mamba tensor this plan
166
+ // touches is taken whole. `lm_head.weight` is untouched entirely and
167
+ // surfaces through `unmappedSources`.
168
+ discards: [],
169
+ };
170
+
171
+ return { modelConfig, plan };
172
+ },
173
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * import/foreign/index.ts — the foreign-checkpoint weight-port surface.
3
+ *
4
+ * Warm-start this engine's `HybridMambaModel` from a published Mamba checkpoint:
5
+ * pass the checkpoint's `config.json` and its tensors, get back the model config
6
+ * to build plus a name-keyed set of weights, together with an explicit account of
7
+ * anything that did not map cleanly.
8
+ *
9
+ * Supported: Falcon-Mamba (Mamba-1) and Codestral-Mamba (Mamba-2). Transformer
10
+ * checkpoints are NOT portable at any tensor naming — distillation is the only
11
+ * route, and {@link foreignMambaAdapterFor} says so when it rejects one.
12
+ */
13
+
14
+ export {
15
+ FOREIGN_MAMBA_ADAPTERS,
16
+ foreignMambaAdapterFor,
17
+ portForeignMamba,
18
+ portForeignMambaSafetensors,
19
+ } from "./registry.js";
20
+ export type { PortedCheckpoint } from "./registry.js";
21
+
22
+ export { applyPortedWeights } from "./apply.js";
23
+
24
+ export { executePortPlan, normaliseSourceName } from "./plan.js";
25
+ export type {
26
+ PortDiscard,
27
+ PortOp,
28
+ PortPlan,
29
+ PortRule,
30
+ PortedTensors,
31
+ SynthesisedTarget,
32
+ } from "./plan.js";
33
+
34
+ export type { ForeignConfig, ForeignMambaAdapter, PortTarget } from "./adapter.js";
35
+
36
+ export { falconMambaAdapter } from "./falcon_mamba.js";
37
+ export { codestralMambaAdapter } from "./codestral_mamba.js";