@seanhogg/builderforce-memory-engine 2026.7.12 → 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.
- package/README.md +14 -0
- package/dist/bench/adaptation.d.ts +57 -0
- package/dist/bench/adaptation.d.ts.map +1 -0
- package/dist/bench/adaptation.js +167 -0
- package/dist/bench/adaptation.js.map +1 -0
- package/dist/bench/harness.d.ts +2 -0
- package/dist/bench/harness.d.ts.map +1 -1
- package/dist/bench/harness.js +1 -1
- package/dist/bench/harness.js.map +1 -1
- package/dist/bench/index.d.ts +5 -3
- package/dist/bench/index.d.ts.map +1 -1
- package/dist/bench/index.js +4 -2
- package/dist/bench/index.js.map +1 -1
- package/dist/bench/types.d.ts +88 -0
- package/dist/bench/types.d.ts.map +1 -1
- package/dist/evermind/adapt.d.ts +40 -0
- package/dist/evermind/adapt.d.ts.map +1 -0
- package/dist/evermind/adapt.js +25 -0
- package/dist/evermind/adapt.js.map +1 -0
- package/dist/evermind/delta_wire.d.ts +43 -0
- package/dist/evermind/delta_wire.d.ts.map +1 -0
- package/dist/evermind/delta_wire.js +94 -0
- package/dist/evermind/delta_wire.js.map +1 -0
- package/dist/evermind/eval.d.ts +31 -0
- package/dist/evermind/eval.d.ts.map +1 -0
- package/dist/evermind/eval.js +36 -0
- package/dist/evermind/eval.js.map +1 -0
- package/dist/evermind/index.d.ts +16 -0
- package/dist/evermind/index.d.ts.map +1 -0
- package/dist/evermind/index.js +11 -0
- package/dist/evermind/index.js.map +1 -0
- package/dist/evermind/merge.d.ts +21 -0
- package/dist/evermind/merge.d.ts.map +1 -0
- package/dist/evermind/merge.js +79 -0
- package/dist/evermind/merge.js.map +1 -0
- package/dist/{moe/moe_package.d.ts → evermind/package.d.ts} +55 -5
- package/dist/evermind/package.d.ts.map +1 -0
- package/dist/{moe/moe_package.js → evermind/package.js} +118 -19
- package/dist/evermind/package.js.map +1 -0
- package/dist/import/foreign/adapter.d.ts +59 -0
- package/dist/import/foreign/adapter.d.ts.map +1 -0
- package/dist/import/foreign/adapter.js +76 -0
- package/dist/import/foreign/adapter.js.map +1 -0
- package/dist/import/foreign/apply.d.ts +23 -0
- package/dist/import/foreign/apply.d.ts.map +1 -0
- package/dist/import/foreign/apply.js +43 -0
- package/dist/import/foreign/apply.js.map +1 -0
- package/dist/import/foreign/codestral_mamba.d.ts +57 -0
- package/dist/import/foreign/codestral_mamba.d.ts.map +1 -0
- package/dist/import/foreign/codestral_mamba.js +174 -0
- package/dist/import/foreign/codestral_mamba.js.map +1 -0
- package/dist/import/foreign/falcon_mamba.d.ts +51 -0
- package/dist/import/foreign/falcon_mamba.d.ts.map +1 -0
- package/dist/import/foreign/falcon_mamba.js +131 -0
- package/dist/import/foreign/falcon_mamba.js.map +1 -0
- package/dist/import/foreign/index.d.ts +21 -0
- package/dist/import/foreign/index.d.ts.map +1 -0
- package/dist/import/foreign/index.js +18 -0
- package/dist/import/foreign/index.js.map +1 -0
- package/dist/import/foreign/plan.d.ts +122 -0
- package/dist/import/foreign/plan.d.ts.map +1 -0
- package/dist/import/foreign/plan.js +171 -0
- package/dist/import/foreign/plan.js.map +1 -0
- package/dist/import/foreign/registry.d.ts +35 -0
- package/dist/import/foreign/registry.d.ts.map +1 -0
- package/dist/import/foreign/registry.js +89 -0
- package/dist/import/foreign/registry.js.map +1 -0
- package/dist/import/index.d.ts +7 -0
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +7 -0
- package/dist/import/index.js.map +1 -1
- package/dist/index.d.ts +29 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -9
- package/dist/index.js.map +1 -1
- package/dist/kernels/selective_scan.d.ts.map +1 -1
- package/dist/kernels/selective_scan.js +15 -9
- package/dist/kernels/selective_scan.js.map +1 -1
- package/dist/kernels/slice.d.ts +26 -0
- package/dist/kernels/slice.d.ts.map +1 -0
- package/dist/kernels/slice.js +52 -0
- package/dist/kernels/slice.js.map +1 -0
- package/dist/kernels/weight_update.d.ts.map +1 -1
- package/dist/kernels/weight_update.js +30 -4
- package/dist/kernels/weight_update.js.map +1 -1
- package/dist/lm/evermind_lm.d.ts +180 -4
- package/dist/lm/evermind_lm.d.ts.map +1 -1
- package/dist/lm/evermind_lm.js +433 -116
- package/dist/lm/evermind_lm.js.map +1 -1
- package/dist/lm/index.d.ts +8 -2
- package/dist/lm/index.d.ts.map +1 -1
- package/dist/lm/index.js +6 -1
- package/dist/lm/index.js.map +1 -1
- package/dist/lm/text_embedder.d.ts +55 -0
- package/dist/lm/text_embedder.d.ts.map +1 -0
- package/dist/lm/text_embedder.js +62 -0
- package/dist/lm/text_embedder.js.map +1 -0
- package/dist/model/attention_block.d.ts.map +1 -1
- package/dist/model/attention_block.js +9 -5
- package/dist/model/attention_block.js.map +1 -1
- package/dist/model/mamba1_block.d.ts.map +1 -1
- package/dist/model/mamba1_block.js +28 -12
- package/dist/model/mamba1_block.js.map +1 -1
- package/dist/model/mamba2_block.d.ts.map +1 -1
- package/dist/model/mamba2_block.js +14 -9
- package/dist/model/mamba2_block.js.map +1 -1
- package/dist/model/mamba3_block.d.ts.map +1 -1
- package/dist/model/mamba3_block.js +14 -9
- package/dist/model/mamba3_block.js.map +1 -1
- package/dist/moe/index.d.ts +0 -2
- package/dist/moe/index.d.ts.map +1 -1
- package/dist/moe/index.js +0 -1
- package/dist/moe/index.js.map +1 -1
- package/dist/optim/adamw.d.ts +58 -1
- package/dist/optim/adamw.d.ts.map +1 -1
- package/dist/optim/adamw.js +69 -4
- package/dist/optim/adamw.js.map +1 -1
- package/dist/tokenizer/bpe.d.ts +28 -0
- package/dist/tokenizer/bpe.d.ts.map +1 -1
- package/dist/tokenizer/bpe.js +47 -0
- package/dist/tokenizer/bpe.js.map +1 -1
- package/dist/training/cpu_ops.d.ts +44 -0
- package/dist/training/cpu_ops.d.ts.map +1 -0
- package/dist/training/cpu_ops.js +111 -0
- package/dist/training/cpu_ops.js.map +1 -0
- package/dist/training/lora.d.ts +153 -0
- package/dist/training/lora.d.ts.map +1 -0
- package/dist/training/lora.js +324 -0
- package/dist/training/lora.js.map +1 -0
- package/dist/training/mamba1_cpu.d.ts +109 -0
- package/dist/training/mamba1_cpu.d.ts.map +1 -0
- package/dist/training/mamba1_cpu.js +316 -0
- package/dist/training/mamba1_cpu.js.map +1 -0
- package/dist/training/mixed_precision.d.ts +67 -0
- package/dist/training/mixed_precision.d.ts.map +1 -0
- package/dist/training/mixed_precision.js +101 -0
- package/dist/training/mixed_precision.js.map +1 -0
- package/dist/training/model_cpu.d.ts +100 -0
- package/dist/training/model_cpu.d.ts.map +1 -0
- package/dist/training/model_cpu.js +252 -0
- package/dist/training/model_cpu.js.map +1 -0
- package/dist/training/trainer.d.ts +156 -16
- package/dist/training/trainer.d.ts.map +1 -1
- package/dist/training/trainer.js +327 -101
- package/dist/training/trainer.js.map +1 -1
- package/dist/utils/base64.d.ts +12 -0
- package/dist/utils/base64.d.ts.map +1 -0
- package/dist/utils/base64.js +27 -0
- package/dist/utils/base64.js.map +1 -0
- package/package.json +3 -1
- package/src/bench/adaptation.ts +180 -0
- package/src/bench/harness.ts +1 -1
- package/src/bench/index.ts +13 -2
- package/src/bench/types.ts +93 -0
- package/src/evermind/adapt.ts +61 -0
- package/src/evermind/delta_wire.ts +114 -0
- package/src/evermind/eval.ts +62 -0
- package/src/evermind/index.ts +33 -0
- package/src/evermind/merge.ts +106 -0
- package/src/{moe/moe_package.ts → evermind/package.ts} +148 -17
- package/src/import/foreign/adapter.ts +106 -0
- package/src/import/foreign/apply.ts +54 -0
- package/src/import/foreign/codestral_mamba.ts +224 -0
- package/src/import/foreign/falcon_mamba.ts +173 -0
- package/src/import/foreign/index.ts +37 -0
- package/src/import/foreign/plan.ts +294 -0
- package/src/import/foreign/registry.ts +126 -0
- package/src/import/index.ts +30 -0
- package/src/index.ts +104 -13
- package/src/kernels/selective_scan.ts +15 -9
- package/src/kernels/slice.ts +64 -0
- package/src/kernels/weight_update.ts +30 -4
- package/src/lm/evermind_lm.ts +470 -116
- package/src/lm/index.ts +12 -2
- package/src/lm/text_embedder.ts +84 -0
- package/src/model/attention_block.ts +9 -5
- package/src/model/mamba1_block.ts +28 -12
- package/src/model/mamba2_block.ts +14 -9
- package/src/model/mamba3_block.ts +14 -9
- package/src/moe/index.ts +0 -9
- package/src/optim/adamw.ts +115 -7
- package/src/tokenizer/bpe.ts +55 -0
- package/src/training/cpu_ops.ts +127 -0
- package/src/training/lora.ts +365 -0
- package/src/training/mamba1_cpu.ts +421 -0
- package/src/training/mixed_precision.ts +119 -0
- package/src/training/model_cpu.ts +360 -0
- package/src/training/trainer.ts +397 -154
- package/src/utils/base64.ts +28 -0
- package/dist/model/mamba_block.d.ts +0 -64
- package/dist/model/mamba_block.d.ts.map +0 -1
- package/dist/model/mamba_block.js +0 -303
- package/dist/model/mamba_block.js.map +0 -1
- package/dist/moe/moe_package.d.ts.map +0 -1
- package/dist/moe/moe_package.js.map +0 -1
- 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";
|