@seanhogg/builderforce-memory-engine 2026.7.14 → 2026.9.28
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 +25 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -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 +110 -1
- package/dist/lm/evermind_lm.d.ts.map +1 -1
- package/dist/lm/evermind_lm.js +220 -35
- package/dist/lm/evermind_lm.js.map +1 -1
- package/dist/lm/index.d.ts +4 -2
- package/dist/lm/index.d.ts.map +1 -1
- package/dist/lm/index.js +3 -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 +32 -0
- package/dist/optim/adamw.d.ts.map +1 -1
- package/dist/optim/adamw.js +34 -0
- 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/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/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 +32 -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 +94 -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 +244 -34
- package/src/lm/index.ts +6 -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 +60 -0
- package/src/tokenizer/bpe.ts +55 -0
- package/src/training/cpu_ops.ts +127 -0
- package/src/training/mamba1_cpu.ts +421 -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,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* model_cpu.ts — the exact CPU forward + backward for a whole
|
|
3
|
+
* {@link HybridMambaModel}: token embedding → layer stack → final RMSNorm →
|
|
4
|
+
* tied LM head → cross-entropy.
|
|
5
|
+
*
|
|
6
|
+
* This is the gradient engine {@link MambaTrainer} uses. Before it existed the
|
|
7
|
+
* trainer handed the SAME `dLogits` buffer to AdamW for every parameter, so no
|
|
8
|
+
* parameter ever received its own gradient — `learn()` was safe but inert. Now
|
|
9
|
+
* the backward pass is real, and `tests/backprop.test.ts` proves it against
|
|
10
|
+
* finite differences without needing a GPU.
|
|
11
|
+
*
|
|
12
|
+
* Parameter names match {@link HybridMambaModel.parameters} exactly
|
|
13
|
+
* (`embedding`, `layer{i}.{name}`, `final_norm`), which is how the trainer
|
|
14
|
+
* pairs each parameter with its OWN gradient.
|
|
15
|
+
*/
|
|
16
|
+
import { type Mamba1CpuWeights, type Mamba1CpuGrads } from './mamba1_cpu.js';
|
|
17
|
+
/** Layer types the CPU gradient engine can differentiate today. */
|
|
18
|
+
export declare const CPU_GRADIENT_LAYER_TYPES: readonly ["mamba1"];
|
|
19
|
+
export type CpuGradientLayerType = (typeof CPU_GRADIENT_LAYER_TYPES)[number];
|
|
20
|
+
export interface CpuModelDims {
|
|
21
|
+
vocabSize: number;
|
|
22
|
+
dModel: number;
|
|
23
|
+
dState: number;
|
|
24
|
+
dConv: number;
|
|
25
|
+
dInner: number;
|
|
26
|
+
dtRank: number;
|
|
27
|
+
numLayers: number;
|
|
28
|
+
}
|
|
29
|
+
/** Every tensor the CPU model reads, mirrored out of the GPU buffers. */
|
|
30
|
+
export interface CpuModelWeights {
|
|
31
|
+
embedding: Float32Array;
|
|
32
|
+
finalNorm: Float32Array;
|
|
33
|
+
lmHeadBias: Float32Array;
|
|
34
|
+
layers: Mamba1CpuWeights[];
|
|
35
|
+
}
|
|
36
|
+
export interface CpuModelGrads {
|
|
37
|
+
embedding: Float32Array;
|
|
38
|
+
finalNorm: Float32Array;
|
|
39
|
+
lmHeadBias: Float32Array;
|
|
40
|
+
layers: Mamba1CpuGrads[];
|
|
41
|
+
}
|
|
42
|
+
/** Knobs on one backward pass. */
|
|
43
|
+
export interface CpuBackwardOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Recompute each layer's activations during the backward pass instead of
|
|
46
|
+
* retaining every layer's cache from the forward. Trades one extra forward per
|
|
47
|
+
* layer for O(1) instead of O(layers) retained activations; the gradients are
|
|
48
|
+
* numerically identical (`tests/peft_trainer.test.ts` asserts bit equality).
|
|
49
|
+
*/
|
|
50
|
+
activationCheckpointing?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** Loss + the gradient of every parameter, keyed by `parameters()` name. */
|
|
53
|
+
export interface CpuBackwardResult {
|
|
54
|
+
loss: number;
|
|
55
|
+
grads: Map<string, Float32Array>;
|
|
56
|
+
}
|
|
57
|
+
export declare function zeroCpuModelGrads(dims: CpuModelDims): CpuModelGrads;
|
|
58
|
+
/** Flatten a {@link CpuModelGrads} into the `parameters()` naming the optimizer uses. */
|
|
59
|
+
export declare function toNamedGrads(g: CpuModelGrads): Map<string, Float32Array>;
|
|
60
|
+
/** The model's tensors keyed the same way — the inverse of {@link cpuWeightsFromNamed}. */
|
|
61
|
+
export declare function namedWeights(w: CpuModelWeights): Map<string, Float32Array>;
|
|
62
|
+
/**
|
|
63
|
+
* Assemble a {@link CpuModelWeights} from tensors keyed by `parameters()` name —
|
|
64
|
+
* how {@link MambaTrainer} mirrors the GPU buffers into the gradient engine.
|
|
65
|
+
* Throws on a missing or wrongly-sized tensor rather than training on garbage.
|
|
66
|
+
*/
|
|
67
|
+
export declare function cpuWeightsFromNamed(named: Map<string, Float32Array>, dims: CpuModelDims): CpuModelWeights;
|
|
68
|
+
/** Logits only — the CPU mirror of `HybridMambaModel.forward`. */
|
|
69
|
+
export declare function cpuModelForward(tokenIds: ArrayLike<number>, w: CpuModelWeights, dims: CpuModelDims, batch: number, seqLen: number): Float32Array;
|
|
70
|
+
/** Mean next-token cross-entropy over the sequence — the trainer's loss. */
|
|
71
|
+
export declare function cpuModelLoss(tokenIds: ArrayLike<number>, targets: ArrayLike<number>, w: CpuModelWeights, dims: CpuModelDims, batch: number, seqLen: number): number;
|
|
72
|
+
/**
|
|
73
|
+
* Forward + backward. Returns the mean cross-entropy loss and the gradient of
|
|
74
|
+
* EVERY parameter, keyed by its `parameters()` name.
|
|
75
|
+
*
|
|
76
|
+
* The loss is averaged over the `batch * seqLen` predicted positions, so the
|
|
77
|
+
* gradients are the gradients of that mean — the quantity the trainer reports.
|
|
78
|
+
*/
|
|
79
|
+
export declare function cpuModelBackward(tokenIds: ArrayLike<number>, targets: ArrayLike<number>, w: CpuModelWeights, dims: CpuModelDims, batch: number, seqLen: number, opts?: CpuBackwardOptions): CpuBackwardResult;
|
|
80
|
+
/**
|
|
81
|
+
* The 2-D shape of a parameter, or `null` when it is a vector (bias / norm gain
|
|
82
|
+
* / `D_vec`).
|
|
83
|
+
*
|
|
84
|
+
* Low-rank adaptation only means anything over a matrix, so this is the single
|
|
85
|
+
* place that says which parameters an adapter can cover — and it derives the
|
|
86
|
+
* shapes from `dims` rather than restating the block's layout, so it cannot
|
|
87
|
+
* drift from {@link cpuWeightsFromNamed}.
|
|
88
|
+
*/
|
|
89
|
+
export declare function paramMatrixShape(name: string, dims: CpuModelDims): [rows: number, cols: number] | null;
|
|
90
|
+
/**
|
|
91
|
+
* Parameters a low-rank adapter covers by default: the four projections inside
|
|
92
|
+
* each block.
|
|
93
|
+
*
|
|
94
|
+
* Deliberately NOT the token embedding (by far the largest tensor, and tied to
|
|
95
|
+
* the output head — adapting it low-rank changes the head too) and NOT `A_log`
|
|
96
|
+
* (the state-transition decay, which WSLA freezes precisely because drifting it
|
|
97
|
+
* destabilises the SSM).
|
|
98
|
+
*/
|
|
99
|
+
export declare const DEFAULT_LORA_TARGETS: readonly ["wInProj", "wXProj", "wDtProj", "wOutProj"];
|
|
100
|
+
//# sourceMappingURL=model_cpu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_cpu.d.ts","sourceRoot":"","sources":["../../src/training/model_cpu.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* model_cpu.ts — the exact CPU forward + backward for a whole
|
|
3
|
+
* {@link HybridMambaModel}: token embedding → layer stack → final RMSNorm →
|
|
4
|
+
* tied LM head → cross-entropy.
|
|
5
|
+
*
|
|
6
|
+
* This is the gradient engine {@link MambaTrainer} uses. Before it existed the
|
|
7
|
+
* trainer handed the SAME `dLogits` buffer to AdamW for every parameter, so no
|
|
8
|
+
* parameter ever received its own gradient — `learn()` was safe but inert. Now
|
|
9
|
+
* the backward pass is real, and `tests/backprop.test.ts` proves it against
|
|
10
|
+
* finite differences without needing a GPU.
|
|
11
|
+
*
|
|
12
|
+
* Parameter names match {@link HybridMambaModel.parameters} exactly
|
|
13
|
+
* (`embedding`, `layer{i}.{name}`, `final_norm`), which is how the trainer
|
|
14
|
+
* pairs each parameter with its OWN gradient.
|
|
15
|
+
*/
|
|
16
|
+
import { linearForward, rmsNormForward, rmsNormBackward, RMSNORM_EPS, } from './cpu_ops.js';
|
|
17
|
+
import { mamba1CpuForward, mamba1CpuBackward, zeroMamba1Grads, MAMBA1_PARAM_NAMES, } from './mamba1_cpu.js';
|
|
18
|
+
import { crossEntropyLoss, crossEntropyGrad } from './autograd.js';
|
|
19
|
+
/** Layer types the CPU gradient engine can differentiate today. */
|
|
20
|
+
export const CPU_GRADIENT_LAYER_TYPES = ['mamba1'];
|
|
21
|
+
export function zeroCpuModelGrads(dims) {
|
|
22
|
+
const blockDims = {
|
|
23
|
+
dModel: dims.dModel, dState: dims.dState, dConv: dims.dConv,
|
|
24
|
+
dInner: dims.dInner, dtRank: dims.dtRank, batch: 1, seqLen: 1,
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
embedding: new Float32Array(dims.vocabSize * dims.dModel),
|
|
28
|
+
finalNorm: new Float32Array(dims.dModel),
|
|
29
|
+
lmHeadBias: new Float32Array(dims.vocabSize),
|
|
30
|
+
layers: Array.from({ length: dims.numLayers }, () => zeroMamba1Grads(blockDims)),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Flatten a {@link CpuModelGrads} into the `parameters()` naming the optimizer uses. */
|
|
34
|
+
export function toNamedGrads(g) {
|
|
35
|
+
const out = new Map();
|
|
36
|
+
out.set('embedding', g.embedding);
|
|
37
|
+
for (let i = 0; i < g.layers.length; i++) {
|
|
38
|
+
const lg = g.layers[i];
|
|
39
|
+
for (const name of MAMBA1_PARAM_NAMES)
|
|
40
|
+
out.set(`layer${i}.${name}`, lg[name]);
|
|
41
|
+
}
|
|
42
|
+
out.set('final_norm', g.finalNorm);
|
|
43
|
+
out.set('lm_head_bias', g.lmHeadBias);
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
/** The model's tensors keyed the same way — the inverse of {@link cpuWeightsFromNamed}. */
|
|
47
|
+
export function namedWeights(w) {
|
|
48
|
+
const out = new Map();
|
|
49
|
+
out.set('embedding', w.embedding);
|
|
50
|
+
for (let i = 0; i < w.layers.length; i++) {
|
|
51
|
+
const lw = w.layers[i];
|
|
52
|
+
for (const name of MAMBA1_PARAM_NAMES)
|
|
53
|
+
out.set(`layer${i}.${name}`, lw[name]);
|
|
54
|
+
}
|
|
55
|
+
out.set('final_norm', w.finalNorm);
|
|
56
|
+
out.set('lm_head_bias', w.lmHeadBias);
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Assemble a {@link CpuModelWeights} from tensors keyed by `parameters()` name —
|
|
61
|
+
* how {@link MambaTrainer} mirrors the GPU buffers into the gradient engine.
|
|
62
|
+
* Throws on a missing or wrongly-sized tensor rather than training on garbage.
|
|
63
|
+
*/
|
|
64
|
+
export function cpuWeightsFromNamed(named, dims) {
|
|
65
|
+
const take = (key, expected) => {
|
|
66
|
+
const t = named.get(key);
|
|
67
|
+
if (!t)
|
|
68
|
+
throw new Error(`cpuWeightsFromNamed: missing tensor "${key}"`);
|
|
69
|
+
if (t.length !== expected) {
|
|
70
|
+
throw new Error(`cpuWeightsFromNamed: "${key}" has ${t.length} elements, expected ${expected}`);
|
|
71
|
+
}
|
|
72
|
+
return t;
|
|
73
|
+
};
|
|
74
|
+
const { dModel, dState: N, dConv: K, dInner: D, dtRank: R } = dims;
|
|
75
|
+
const sizes = {
|
|
76
|
+
wInProj: 2 * D * dModel, bInProj: 2 * D, wConv: D * K, bConv: D,
|
|
77
|
+
wXProj: (R + 2 * N) * D, bXProj: R + 2 * N, wDtProj: D * R, bDtProj: D,
|
|
78
|
+
A_log: D * N, D_vec: D, wOutProj: dModel * D, bOutProj: dModel, normWeight: dModel,
|
|
79
|
+
};
|
|
80
|
+
const layers = [];
|
|
81
|
+
for (let i = 0; i < dims.numLayers; i++) {
|
|
82
|
+
const lw = {};
|
|
83
|
+
for (const name of MAMBA1_PARAM_NAMES)
|
|
84
|
+
lw[name] = take(`layer${i}.${name}`, sizes[name]);
|
|
85
|
+
layers.push(lw);
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
embedding: take('embedding', dims.vocabSize * dModel),
|
|
89
|
+
finalNorm: take('final_norm', dModel),
|
|
90
|
+
lmHeadBias: take('lm_head_bias', dims.vocabSize),
|
|
91
|
+
layers,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function forwardInternal(tokenIds, w, dims, batch, seqLen,
|
|
95
|
+
/** Drop each layer's activation cache after use — see {@link CpuBackwardOptions}. */
|
|
96
|
+
checkpointed = false) {
|
|
97
|
+
const { vocabSize, dModel } = dims;
|
|
98
|
+
const M = batch * seqLen;
|
|
99
|
+
// Token embedding lookup.
|
|
100
|
+
let hidden = new Float32Array(M * dModel);
|
|
101
|
+
for (let r = 0; r < M; r++) {
|
|
102
|
+
const id = tokenIds[r];
|
|
103
|
+
if (id < 0 || id >= vocabSize)
|
|
104
|
+
throw new Error(`token id ${id} out of range [0, ${vocabSize})`);
|
|
105
|
+
hidden.set(w.embedding.subarray(id * dModel, (id + 1) * dModel), r * dModel);
|
|
106
|
+
}
|
|
107
|
+
const blockDims = {
|
|
108
|
+
dModel, dState: dims.dState, dConv: dims.dConv,
|
|
109
|
+
dInner: dims.dInner, dtRank: dims.dtRank, batch, seqLen,
|
|
110
|
+
};
|
|
111
|
+
const hiddenIn = [];
|
|
112
|
+
const layerCaches = [];
|
|
113
|
+
for (let i = 0; i < dims.numLayers; i++) {
|
|
114
|
+
hiddenIn.push(hidden);
|
|
115
|
+
const { output, cache } = mamba1CpuForward(hidden, w.layers[i], blockDims);
|
|
116
|
+
// Under activation checkpointing only the layer INPUTS are retained; each
|
|
117
|
+
// layer's cache is recomputed from its input when its backward runs. Memory
|
|
118
|
+
// drops from O(layers) caches to one, at the cost of a second forward per
|
|
119
|
+
// layer — gradients are numerically identical either way.
|
|
120
|
+
if (!checkpointed)
|
|
121
|
+
layerCaches.push(cache);
|
|
122
|
+
hidden = output;
|
|
123
|
+
}
|
|
124
|
+
// Final RMSNorm.
|
|
125
|
+
const normOut = new Float32Array(M * dModel);
|
|
126
|
+
const normInv = new Float32Array(M);
|
|
127
|
+
rmsNormForward(hidden, w.finalNorm, M, dModel, normOut, normInv, RMSNORM_EPS);
|
|
128
|
+
// Tied LM head: logits = normOut @ embedding^T + lmHeadBias.
|
|
129
|
+
const logits = new Float32Array(M * vocabSize);
|
|
130
|
+
linearForward(normOut, w.embedding, w.lmHeadBias, M, dModel, vocabSize, logits);
|
|
131
|
+
return { hiddenIn, layer: layerCaches, lastHidden: hidden, normOut, normInv, logits };
|
|
132
|
+
}
|
|
133
|
+
/** Logits only — the CPU mirror of `HybridMambaModel.forward`. */
|
|
134
|
+
export function cpuModelForward(tokenIds, w, dims, batch, seqLen) {
|
|
135
|
+
return forwardInternal(tokenIds, w, dims, batch, seqLen).logits;
|
|
136
|
+
}
|
|
137
|
+
/** Mean next-token cross-entropy over the sequence — the trainer's loss. */
|
|
138
|
+
export function cpuModelLoss(tokenIds, targets, w, dims, batch, seqLen) {
|
|
139
|
+
const logits = cpuModelForward(tokenIds, w, dims, batch, seqLen);
|
|
140
|
+
const M = batch * seqLen;
|
|
141
|
+
const V = dims.vocabSize;
|
|
142
|
+
let total = 0;
|
|
143
|
+
for (let r = 0; r < M; r++) {
|
|
144
|
+
total += crossEntropyLoss(logits.subarray(r * V, (r + 1) * V), targets[r]);
|
|
145
|
+
}
|
|
146
|
+
return total / M;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Forward + backward. Returns the mean cross-entropy loss and the gradient of
|
|
150
|
+
* EVERY parameter, keyed by its `parameters()` name.
|
|
151
|
+
*
|
|
152
|
+
* The loss is averaged over the `batch * seqLen` predicted positions, so the
|
|
153
|
+
* gradients are the gradients of that mean — the quantity the trainer reports.
|
|
154
|
+
*/
|
|
155
|
+
export function cpuModelBackward(tokenIds, targets, w, dims, batch, seqLen, opts = {}) {
|
|
156
|
+
const { vocabSize: V, dModel } = dims;
|
|
157
|
+
const M = batch * seqLen;
|
|
158
|
+
const checkpointed = opts.activationCheckpointing ?? false;
|
|
159
|
+
const cache = forwardInternal(tokenIds, w, dims, batch, seqLen, checkpointed);
|
|
160
|
+
const g = zeroCpuModelGrads(dims);
|
|
161
|
+
// Cross-entropy over every position, averaged.
|
|
162
|
+
let total = 0;
|
|
163
|
+
const dLogits = new Float32Array(M * V);
|
|
164
|
+
for (let r = 0; r < M; r++) {
|
|
165
|
+
const slice = cache.logits.subarray(r * V, (r + 1) * V);
|
|
166
|
+
const target = targets[r];
|
|
167
|
+
total += crossEntropyLoss(slice, target);
|
|
168
|
+
const gr = crossEntropyGrad(slice, target);
|
|
169
|
+
for (let v = 0; v < V; v++)
|
|
170
|
+
dLogits[r * V + v] = gr[v] / M;
|
|
171
|
+
}
|
|
172
|
+
const loss = total / M;
|
|
173
|
+
// LM head (tied): logits = normOut @ embedding^T + bias.
|
|
174
|
+
// dNormOut = dLogits @ embedding ; dEmbedding += dLogits^T @ normOut.
|
|
175
|
+
const dNormOut = new Float32Array(M * dModel);
|
|
176
|
+
for (let r = 0; r < M; r++) {
|
|
177
|
+
const lo = r * V;
|
|
178
|
+
const no = r * dModel;
|
|
179
|
+
for (let v = 0; v < V; v++) {
|
|
180
|
+
const gl = dLogits[lo + v];
|
|
181
|
+
if (gl === 0)
|
|
182
|
+
continue;
|
|
183
|
+
g.lmHeadBias[v] = g.lmHeadBias[v] + gl;
|
|
184
|
+
const eo = v * dModel;
|
|
185
|
+
for (let i = 0; i < dModel; i++) {
|
|
186
|
+
dNormOut[no + i] = dNormOut[no + i] + gl * w.embedding[eo + i];
|
|
187
|
+
g.embedding[eo + i] = g.embedding[eo + i] + gl * cache.normOut[no + i];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Final RMSNorm.
|
|
192
|
+
const dLastHidden = new Float32Array(M * dModel);
|
|
193
|
+
rmsNormBackward(dNormOut, cache.lastHidden, w.finalNorm, cache.normInv, M, dModel, dLastHidden, g.finalNorm, RMSNORM_EPS);
|
|
194
|
+
// Layer stack, in reverse.
|
|
195
|
+
const blockDims = {
|
|
196
|
+
dModel, dState: dims.dState, dConv: dims.dConv,
|
|
197
|
+
dInner: dims.dInner, dtRank: dims.dtRank, batch, seqLen,
|
|
198
|
+
};
|
|
199
|
+
let d = dLastHidden;
|
|
200
|
+
for (let i = dims.numLayers - 1; i >= 0; i--) {
|
|
201
|
+
const layerCache = checkpointed
|
|
202
|
+
? mamba1CpuForward(cache.hiddenIn[i], w.layers[i], blockDims).cache
|
|
203
|
+
: cache.layer[i];
|
|
204
|
+
d = mamba1CpuBackward(d, w.layers[i], layerCache, blockDims, g.layers[i]);
|
|
205
|
+
}
|
|
206
|
+
// Token embedding — the SAME table the LM head reads, so this accumulates
|
|
207
|
+
// on top of the head's contribution (the tie is why both terms are needed).
|
|
208
|
+
for (let r = 0; r < M; r++) {
|
|
209
|
+
const id = tokenIds[r];
|
|
210
|
+
const eo = id * dModel;
|
|
211
|
+
const ho = r * dModel;
|
|
212
|
+
for (let i = 0; i < dModel; i++)
|
|
213
|
+
g.embedding[eo + i] = g.embedding[eo + i] + d[ho + i];
|
|
214
|
+
}
|
|
215
|
+
return { loss, grads: toNamedGrads(g) };
|
|
216
|
+
}
|
|
217
|
+
// ── Parameter shapes (for PEFT) ──────────────────────────────────────────────
|
|
218
|
+
/**
|
|
219
|
+
* The 2-D shape of a parameter, or `null` when it is a vector (bias / norm gain
|
|
220
|
+
* / `D_vec`).
|
|
221
|
+
*
|
|
222
|
+
* Low-rank adaptation only means anything over a matrix, so this is the single
|
|
223
|
+
* place that says which parameters an adapter can cover — and it derives the
|
|
224
|
+
* shapes from `dims` rather than restating the block's layout, so it cannot
|
|
225
|
+
* drift from {@link cpuWeightsFromNamed}.
|
|
226
|
+
*/
|
|
227
|
+
export function paramMatrixShape(name, dims) {
|
|
228
|
+
const { dModel, dState: N, dConv: K, dInner: D, dtRank: R } = dims;
|
|
229
|
+
if (name === 'embedding')
|
|
230
|
+
return [dims.vocabSize, dModel];
|
|
231
|
+
const local = name.startsWith('layer') ? name.slice(name.indexOf('.') + 1) : name;
|
|
232
|
+
switch (local) {
|
|
233
|
+
case 'wInProj': return [2 * D, dModel];
|
|
234
|
+
case 'wConv': return [D, K];
|
|
235
|
+
case 'wXProj': return [R + 2 * N, D];
|
|
236
|
+
case 'wDtProj': return [D, R];
|
|
237
|
+
case 'A_log': return [D, N];
|
|
238
|
+
case 'wOutProj': return [dModel, D];
|
|
239
|
+
default: return null; // bInProj, bConv, bXProj, bDtProj, D_vec, bOutProj, normWeight, final_norm, lm_head_bias
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Parameters a low-rank adapter covers by default: the four projections inside
|
|
244
|
+
* each block.
|
|
245
|
+
*
|
|
246
|
+
* Deliberately NOT the token embedding (by far the largest tensor, and tied to
|
|
247
|
+
* the output head — adapting it low-rank changes the head too) and NOT `A_log`
|
|
248
|
+
* (the state-transition decay, which WSLA freezes precisely because drifting it
|
|
249
|
+
* destabilises the SSM).
|
|
250
|
+
*/
|
|
251
|
+
export const DEFAULT_LORA_TARGETS = ['wInProj', 'wXProj', 'wDtProj', 'wOutProj'];
|
|
252
|
+
//# sourceMappingURL=model_cpu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_cpu.js","sourceRoot":"","sources":["../../src/training/model_cpu.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* trainer.ts – MambaTrainer class
|
|
3
|
+
*
|
|
4
|
+
* REAL backpropagation. Until 2026-08 `_trainStep` handed the SAME `dLogits`
|
|
5
|
+
* buffer to AdamW for every parameter, so no parameter ever received its own
|
|
6
|
+
* gradient: `learn()` was SAFE (WSLA freezes the backbone, the trust region
|
|
7
|
+
* bounds every step, the NaN guard blocks a poisoned weight, and the session
|
|
8
|
+
* rolls back a regression) but INERT. It now runs a genuine backward pass —
|
|
9
|
+
* `cpuModelBackward` in `model_cpu.ts` — and each parameter is stepped with its
|
|
10
|
+
* OWN gradient.
|
|
11
|
+
*
|
|
12
|
+
* Where the maths runs, and why:
|
|
13
|
+
* • the backward pass is the CPU reference (`cpu_ops.ts` + `mamba1_cpu.ts`),
|
|
14
|
+
* a line-for-line mirror of the WGSL forward kernels. It is exact and it is
|
|
15
|
+
* PROVEN — `tests/backprop.test.ts` checks every parameter gradient against
|
|
16
|
+
* finite differences of the real loss, with no GPU involved;
|
|
17
|
+
* • the optimiser is {@link adamwUpdateInPlace}, the CPU mirror of
|
|
18
|
+
* `WEIGHT_UPDATE_WGSL`'s `adamw_update`, keeping the trust region and the
|
|
19
|
+
* NaN guard the safety story depends on;
|
|
20
|
+
* • the model's GPU buffers are written back after every optimiser step, so
|
|
21
|
+
* inference (which IS GPU) always serves the trained weights.
|
|
22
|
+
*
|
|
23
|
+
* The residual is a WGSL backward pass so training itself runs on the GPU. The
|
|
24
|
+
* backward kernels exist (`SELECTIVE_SCAN_BACKWARD_WGSL`, `SSD_BACKWARD_WGSL`,
|
|
25
|
+
* `CONV1D_BACKWARD_WGSL`, `LINEAR_BACKWARD_WGSL`, `ACTIVATIONS_BACKWARD_WGSL`)
|
|
26
|
+
* but wiring them cannot be validated numerically without a WebGPU device, and
|
|
27
|
+
* an unvalidated GPU backward is worse than a slower exact one.
|
|
3
28
|
*/
|
|
29
|
+
import { type ShardSpec } from '../optim/adamw.js';
|
|
30
|
+
import { LoRAAdapter, type LoRAConfig } from './lora.js';
|
|
31
|
+
import { type CpuModelDims } from './model_cpu.js';
|
|
4
32
|
import { HybridMambaModel, MambaModel } from '../model/mamba_model.js';
|
|
5
33
|
import { BPETokenizer } from '../tokenizer/bpe.js';
|
|
6
34
|
export interface TrainOptions {
|
|
7
35
|
learningRate?: number;
|
|
8
36
|
epochs?: number;
|
|
37
|
+
/** Sequences trained together per optimiser step. Chunks of equal length are
|
|
38
|
+
* grouped into batches of this size; a ragged tail trains on its own. */
|
|
9
39
|
batchSize?: number;
|
|
10
40
|
seqLen?: number;
|
|
11
41
|
maxGradNorm?: number;
|
|
@@ -17,11 +47,48 @@ export interface TrainOptions {
|
|
|
17
47
|
/** Trust region: max |Δθ| per optimizer step. 0 disables. Defaults to
|
|
18
48
|
* {@link WSLA_MAX_DELTA} in WSLA (write-through) mode, else 0 (full training). */
|
|
19
49
|
maxDelta?: number;
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
50
|
+
/**
|
|
51
|
+
* @deprecated The pre-clip gradient L2 norm is now computed exactly on the way
|
|
52
|
+
* through the optimiser and is ALWAYS reported — it no longer costs a GPU
|
|
53
|
+
* readback, so there is nothing to opt into. Accepted for API compatibility.
|
|
54
|
+
*/
|
|
24
55
|
trackGradNorm?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Train LOW-RANK ADAPTERS over the block projections instead of the weights
|
|
58
|
+
* themselves (see {@link LoRAAdapter}). The base weights are frozen; only A and
|
|
59
|
+
* B train, so an adapt costs a fraction of the optimiser state and the result is
|
|
60
|
+
* a small, mergeable delta rather than a whole checkpoint.
|
|
61
|
+
*
|
|
62
|
+
* `targets` selects which parameters get an adapter, by their unqualified name
|
|
63
|
+
* (`wInProj`, `wXProj`, `wDtProj`, `wOutProj`, `wConv`, `A_log`, `embedding`);
|
|
64
|
+
* omit for {@link DEFAULT_LORA_TARGETS}. A rank larger than a target's smaller
|
|
65
|
+
* dimension is clamped to it rather than throwing — the small projections
|
|
66
|
+
* (`wDtProj` is `dInner x dtRank`) would otherwise reject a sensible global rank.
|
|
67
|
+
*/
|
|
68
|
+
lora?: LoRAConfig & {
|
|
69
|
+
targets?: readonly string[];
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Batches to accumulate gradients over before one optimiser step. Default 1.
|
|
73
|
+
* The effective batch size is `batchSize * gradientAccumulation` at the memory
|
|
74
|
+
* cost of `batchSize` — the standard way to train at a batch size the host
|
|
75
|
+
* cannot hold at once.
|
|
76
|
+
*/
|
|
77
|
+
gradientAccumulation?: number;
|
|
78
|
+
/**
|
|
79
|
+
* Shard the optimiser state (the Adam moments — 2x the parameter bytes, the
|
|
80
|
+
* dominant cost of a full fine-tune). This instance then OWNS only parameters
|
|
81
|
+
* where `index % count === index`, and allocates moments for those alone. Run
|
|
82
|
+
* `count` trainers over the same model and the union of their steps equals one
|
|
83
|
+
* unsharded step. Same contract as {@link ShardSpec} on {@link AdamW}.
|
|
84
|
+
*/
|
|
85
|
+
shard?: ShardSpec;
|
|
86
|
+
/**
|
|
87
|
+
* Recompute each layer's activations in the backward pass instead of retaining
|
|
88
|
+
* all of them. Gradients are identical; peak memory drops from O(layers)
|
|
89
|
+
* activation caches to one, at the cost of a second forward per layer.
|
|
90
|
+
*/
|
|
91
|
+
activationCheckpointing?: boolean;
|
|
25
92
|
onEpochEnd?: ((epoch: number, loss: number, gradNorm?: number) => void) | null;
|
|
26
93
|
}
|
|
27
94
|
/**
|
|
@@ -32,6 +99,18 @@ export interface TrainOptions {
|
|
|
32
99
|
* non-WSLA mode) for unbounded steps.
|
|
33
100
|
*/
|
|
34
101
|
export declare const WSLA_MAX_DELTA = 0.05;
|
|
102
|
+
/** One training example: a token window and its next-token targets. */
|
|
103
|
+
interface TrainChunk {
|
|
104
|
+
inputs: number[];
|
|
105
|
+
targets: number[];
|
|
106
|
+
}
|
|
107
|
+
/** A batch of equal-length chunks trained in one optimiser step. */
|
|
108
|
+
interface TrainBatch {
|
|
109
|
+
inputs: number[];
|
|
110
|
+
targets: number[];
|
|
111
|
+
batch: number;
|
|
112
|
+
seqLen: number;
|
|
113
|
+
}
|
|
35
114
|
export declare class MambaTrainer {
|
|
36
115
|
model: HybridMambaModel;
|
|
37
116
|
tokenizer: BPETokenizer | null;
|
|
@@ -40,29 +119,90 @@ export declare class MambaTrainer {
|
|
|
40
119
|
* Adam moments keyed by parameter NAME (not array index). Name-keying is what
|
|
41
120
|
* lets WSLA toggle safely: a narrow write-through step updates only the
|
|
42
121
|
* `layer{i}.wXProj/bXProj` subset, a full fine-tune updates everything, and
|
|
43
|
-
* both reuse the SAME `m`/`v`
|
|
44
|
-
*
|
|
45
|
-
*
|
|
122
|
+
* both reuse the SAME `m`/`v` per parameter. Index-keyed moments (the old
|
|
123
|
+
* scheme) silently misaligned the moment with the wrong parameter the moment
|
|
124
|
+
* the trainable set changed shape — corrupting the update.
|
|
46
125
|
*/
|
|
47
126
|
private _moments;
|
|
48
127
|
private _step;
|
|
49
|
-
private
|
|
50
|
-
|
|
51
|
-
private
|
|
128
|
+
private readonly _dims;
|
|
129
|
+
/** CPU mirror of every model tensor — the gradient engine's working set. */
|
|
130
|
+
private _mirror;
|
|
131
|
+
private _mirrorByName;
|
|
132
|
+
/** Low-rank adapters by parameter name, when training with `lora`. */
|
|
133
|
+
private _adapters;
|
|
134
|
+
/** Frozen base weights the adapters sit on top of (LoRA only). */
|
|
135
|
+
private _loraBase;
|
|
136
|
+
private _shard;
|
|
52
137
|
constructor(model: HybridMambaModel | MambaModel, tokenizer?: BPETokenizer | null);
|
|
138
|
+
/**
|
|
139
|
+
* The low-rank adapters this trainer is training, by parameter name — empty
|
|
140
|
+
* unless `train({ lora })` was used. Exposed so a caller can serialise just the
|
|
141
|
+
* adapter (a few hundred KB) instead of the whole checkpoint.
|
|
142
|
+
*/
|
|
143
|
+
get adapters(): ReadonlyMap<string, LoRAAdapter>;
|
|
144
|
+
/** Trainable scalar count for the current mode — the LoRA saving, measured. */
|
|
145
|
+
trainableParamCount(): number;
|
|
146
|
+
/** Whether this trainer owns parameter `index` under the active shard. */
|
|
147
|
+
private _owns;
|
|
148
|
+
/**
|
|
149
|
+
* Build (once) an adapter for every LoRA-target parameter, snapshot the frozen
|
|
150
|
+
* base, and return the set. Rank is clamped per parameter to its smaller
|
|
151
|
+
* dimension so one global rank works across projections of very different shape.
|
|
152
|
+
*/
|
|
153
|
+
private _installAdapters;
|
|
154
|
+
/** Write `base + adapter.delta()` into the mirror, so the forward sees the adapted weights. */
|
|
155
|
+
private _materialiseAdapters;
|
|
53
156
|
/** Get-or-create the Adam first/second moments for a parameter, by name. */
|
|
54
157
|
private _momentFor;
|
|
158
|
+
/**
|
|
159
|
+
* Pull every model tensor off the GPU into the CPU mirror. Done once per
|
|
160
|
+
* `train()` call (not per step) so an externally loaded checkpoint or a
|
|
161
|
+
* previous session's weights are picked up, after which the mirror is
|
|
162
|
+
* authoritative and each step writes the updated tensors back.
|
|
163
|
+
*/
|
|
164
|
+
private _syncMirrorFromGpu;
|
|
55
165
|
train(input: string | number[], opts?: TrainOptions): Promise<number[]>;
|
|
166
|
+
/**
|
|
167
|
+
* One optimiser step over one batch: real forward + backward, a global
|
|
168
|
+
* gradient-norm clip over the trainable set, then AdamW per parameter with
|
|
169
|
+
* its OWN gradient, written straight back to the GPU buffer.
|
|
170
|
+
*/
|
|
56
171
|
private _trainStep;
|
|
172
|
+
/**
|
|
173
|
+
* AdamW over the trainable set. Each parameter is paired with its OWN
|
|
174
|
+
* gradient by NAME — the bug this replaces passed one shared `dLogits`
|
|
175
|
+
* buffer to every parameter — and the updated tensor is uploaded to the GPU
|
|
176
|
+
* so inference serves it.
|
|
177
|
+
*/
|
|
57
178
|
private _adamwStep;
|
|
179
|
+
/** Get-or-create moments for a synthetic parameter (a LoRA factor), by name. */
|
|
180
|
+
private _momentNamed;
|
|
58
181
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* already computed it, so this is only a small buffer readback (a GPU sync,
|
|
63
|
-
* hence opt-in). Returns null when not tracking.
|
|
182
|
+
* Bytes of optimiser state (Adam m + v) this trainer holds. Under a shard that
|
|
183
|
+
* is 1/count of the full state; under LoRA it is the adapters' state, not the
|
|
184
|
+
* weights'. The measurable point of both features.
|
|
64
185
|
*/
|
|
65
|
-
|
|
186
|
+
optimizerStateBytes(): number;
|
|
66
187
|
evaluate(input: string | number[]): Promise<number>;
|
|
67
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Derive the gradient engine's dimensions from a model, rejecting layer types
|
|
191
|
+
* the CPU reference cannot differentiate.
|
|
192
|
+
*
|
|
193
|
+
* A hybrid schedule (`jamba`/`zamba`, or any explicit schedule containing
|
|
194
|
+
* `mamba2`/`mamba3`/`attention`) fails LOUDLY here rather than silently training
|
|
195
|
+
* on gradients that do not exist — which is exactly what the old trainer did.
|
|
196
|
+
*/
|
|
197
|
+
export declare function cpuDimsFor(model: HybridMambaModel): CpuModelDims;
|
|
198
|
+
export declare function buildChunks(ids: number[], seqLen: number): TrainChunk[];
|
|
199
|
+
/**
|
|
200
|
+
* Group equal-length chunks into batches of at most `batchSize`.
|
|
201
|
+
*
|
|
202
|
+
* `batchSize` used to be accepted and ignored — every chunk trained alone. The
|
|
203
|
+
* batch dimension the model and the gradient engine both take is real, so it is
|
|
204
|
+
* honoured here; a ragged tail chunk simply trains as its own batch of one.
|
|
205
|
+
*/
|
|
206
|
+
export declare function buildBatches(chunks: TrainChunk[], batchSize: number): TrainBatch[];
|
|
207
|
+
export {};
|
|
68
208
|
//# sourceMappingURL=trainer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trainer.d.ts","sourceRoot":"","sources":["../../src/training/trainer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"trainer.d.ts","sourceRoot":"","sources":["../../src/training/trainer.ts"],"names":[],"mappings":"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"}
|