volvoxai 0.1.0 → 0.2.0
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 +346 -43
- package/bin/volvox.js +9 -3
- package/dist/0.2.0/volvoxai.full.js +28607 -0
- package/dist/0.2.0/volvoxai.full.min.js +8975 -0
- package/dist/0.2.0/volvoxai.full.wasm +0 -0
- package/dist/0.2.0/volvoxai.js +18380 -0
- package/dist/0.2.0/volvoxai.min.js +6061 -0
- package/dist/0.2.0/volvoxai.wasm +0 -0
- package/dist/0.2.0/volvoxai.wasm.js +10337 -0
- package/dist/0.2.0/volvoxai.wasm.min.js +2 -0
- package/package.json +26 -12
- package/dist/v0.1.0/volvoxai.js +0 -4664
- package/dist/v0.1.0/volvoxai.min.js +0 -1848
- package/dist/v0.1.0/volvoxai.wasm +0 -0
- package/dist/volvoxai.js +0 -4664
- package/dist/volvoxai.min.js +0 -1848
- package/dist/volvoxai.wasm +0 -0
- package/docs/README.md +0 -22
- package/docs/browser-runtime.md +0 -87
- package/docs/efficientdet_tflite_vs_volvoxai.md +0 -445
- package/docs/microkernel_optimization_guide.md +0 -153
- package/docs/model-format.md +0 -108
- package/docs/models.md +0 -103
- package/docs/native-runtime.md +0 -189
- package/docs/operation_list.md +0 -232
- package/docs/operator_fusion_patterns.md +0 -58
- package/docs/quickstart.md +0 -115
- package/docs/roadmap.md +0 -19
- package/docs/testing.md +0 -97
- package/docs/textbook/01-foundations.md +0 -233
- package/docs/textbook/02-tinystories-language-model.md +0 -300
- package/docs/textbook/03-efficientdet-vision-model.md +0 -281
- package/docs/textbook/04-precision-and-quantization.md +0 -208
- package/docs/textbook/05-inside-the-engine.md +0 -155
- package/docs/textbook/06-native-engine-architecture.md +0 -338
- package/docs/textbook/07-glossary-and-next-steps.md +0 -258
- package/docs/textbook/README.md +0 -85
- package/docs/textbook/ko/01-foundations.md +0 -231
- package/docs/textbook/ko/02-tinystories-language-model.md +0 -300
- package/docs/textbook/ko/03-efficientdet-vision-model.md +0 -277
- package/docs/textbook/ko/04-precision-and-quantization.md +0 -206
- package/docs/textbook/ko/05-inside-the-engine.md +0 -154
- package/docs/textbook/ko/06-native-engine-architecture.md +0 -333
- package/docs/textbook/ko/07-glossary-and-next-steps.md +0 -253
- package/docs/textbook/ko/README.md +0 -83
- package/docs/xnnpack_optimization_guide.md +0 -197
- package/js/CPUEngine.js +0 -241
- package/js/Graph.js +0 -49
- package/js/GraphExecutor.js +0 -1020
- package/js/GraphLoader.js +0 -282
- package/js/ShaderLibrary.js +0 -236
- package/js/Tensor.js +0 -25
- package/js/Tokenizer.js +0 -266
- package/js/VolvoxAI.js +0 -130
- package/js/WasmEngine.js +0 -378
- package/js/WebNNEngine.js +0 -169
- package/js/index.js +0 -11
- package/js/ops/add.js +0 -31
- package/js/ops/argMax.js +0 -33
- package/js/ops/averagePool2D.js +0 -38
- package/js/ops/batchNorm2D.js +0 -28
- package/js/ops/cast.js +0 -19
- package/js/ops/clip.js +0 -15
- package/js/ops/concat2.js +0 -18
- package/js/ops/conv1D.js +0 -35
- package/js/ops/conv2D.js +0 -70
- package/js/ops/convTranspose2D.js +0 -45
- package/js/ops/crossAttention.js +0 -69
- package/js/ops/crossSDPA.js +0 -41
- package/js/ops/dequantizeLinear.js +0 -9
- package/js/ops/div.js +0 -15
- package/js/ops/embedding.js +0 -14
- package/js/ops/expand.js +0 -24
- package/js/ops/gELU.js +0 -9
- package/js/ops/gather.js +0 -51
- package/js/ops/gatherElements.js +0 -33
- package/js/ops/globalAveragePool.js +0 -21
- package/js/ops/hardSigmoid.js +0 -12
- package/js/ops/hardSwish.js +0 -12
- package/js/ops/interp1D.js +0 -25
- package/js/ops/layerNorm.js +0 -25
- package/js/ops/leakyReLU.js +0 -10
- package/js/ops/logSoftmax.js +0 -15
- package/js/ops/matMul.js +0 -35
- package/js/ops/maxPool2D.js +0 -36
- package/js/ops/meanHeight.js +0 -17
- package/js/ops/mul.js +0 -31
- package/js/ops/nonMaxSuppression.js +0 -72
- package/js/ops/pReLU.js +0 -11
- package/js/ops/pad.js +0 -35
- package/js/ops/profileX.js +0 -22
- package/js/ops/profileY.js +0 -22
- package/js/ops/rMSNorm.js +0 -14
- package/js/ops/reLU.js +0 -8
- package/js/ops/reduceMean.js +0 -17
- package/js/ops/reduceSum.js +0 -19
- package/js/ops/reshape.js +0 -6
- package/js/ops/resize.js +0 -44
- package/js/ops/sDPA.js +0 -44
- package/js/ops/siLU.js +0 -8
- package/js/ops/sigmoid.js +0 -6
- package/js/ops/slice.js +0 -36
- package/js/ops/softmax.js +0 -18
- package/js/ops/spatialSoftargmaxY.js +0 -28
- package/js/ops/split.js +0 -24
- package/js/ops/sub.js +0 -11
- package/js/ops/tanh.js +0 -7
- package/js/ops/transpose.js +0 -34
- package/js/ops/upsample2x.js +0 -23
- package/js/ops/where.js +0 -15
- package/shaders/add.wgsl +0 -13
- package/shaders/add3Relu.wgsl +0 -23
- package/shaders/addRelu.wgsl +0 -22
- package/shaders/averagePool2D.wgsl +0 -24
- package/shaders/batchNorm2D.wgsl +0 -21
- package/shaders/binaryBroadcast.wgsl +0 -34
- package/shaders/broadcastBinary.wgsl +0 -26
- package/shaders/clip.wgsl +0 -10
- package/shaders/concat2.wgsl +0 -16
- package/shaders/concatCopy.wgsl +0 -10
- package/shaders/concatSigmoidCopy.wgsl +0 -16
- package/shaders/conv1D.wgsl +0 -37
- package/shaders/conv2D.wgsl +0 -80
- package/shaders/conv2DDepthwise4.wgsl +0 -74
- package/shaders/conv2DDepthwise8.wgsl +0 -66
- package/shaders/conv2DPointwise16.wgsl +0 -67
- package/shaders/conv2DPointwise16Tile.wgsl +0 -86
- package/shaders/conv2DPointwise8.wgsl +0 -85
- package/shaders/conv2DPointwise8Vec2.wgsl +0 -70
- package/shaders/conv2DPointwise8Vec4.wgsl +0 -65
- package/shaders/conv2DRegularC3Out16.wgsl +0 -75
- package/shaders/convTranspose2D.wgsl +0 -33
- package/shaders/copy.wgsl +0 -13
- package/shaders/crossAttention.wgsl +0 -140
- package/shaders/crossAttentionF32.wgsl +0 -98
- package/shaders/crossSDPA.wgsl +0 -74
- package/shaders/dequantizeLinear.wgsl +0 -14
- package/shaders/div.wgsl +0 -34
- package/shaders/elementwise.wgsl +0 -13
- package/shaders/embedding.wgsl +0 -22
- package/shaders/expand.wgsl +0 -18
- package/shaders/gELU.wgsl +0 -13
- package/shaders/gather.wgsl +0 -17
- package/shaders/generalTranspose.wgsl +0 -19
- package/shaders/globalAveragePool.wgsl +0 -19
- package/shaders/hardSigmoid.wgsl +0 -13
- package/shaders/hardSwish.wgsl +0 -13
- package/shaders/interp1D.wgsl +0 -28
- package/shaders/layerNorm.wgsl +0 -33
- package/shaders/leakyReLU.wgsl +0 -11
- package/shaders/linearF32.wgsl +0 -33
- package/shaders/linearF32RowMajor.wgsl +0 -24
- package/shaders/linearInt8.wgsl +0 -42
- package/shaders/logSoftmax.wgsl +0 -22
- package/shaders/maxPool2D.wgsl +0 -37
- package/shaders/meanHeight.wgsl +0 -18
- package/shaders/mul.wgsl +0 -32
- package/shaders/nonMaxSuppression.wgsl +0 -92
- package/shaders/pReLU.wgsl +0 -14
- package/shaders/pad.wgsl +0 -19
- package/shaders/profileX.wgsl +0 -28
- package/shaders/profileY.wgsl +0 -28
- package/shaders/quantizeLinear.wgsl +0 -69
- package/shaders/rMSNorm.wgsl +0 -21
- package/shaders/reLU.wgsl +0 -13
- package/shaders/reduce.wgsl +0 -17
- package/shaders/resize.wgsl +0 -52
- package/shaders/sDPA.wgsl +0 -71
- package/shaders/siLU.wgsl +0 -13
- package/shaders/sigmoid.wgsl +0 -13
- package/shaders/slice.wgsl +0 -26
- package/shaders/softmax.wgsl +0 -23
- package/shaders/spatialSoftargmaxY.wgsl +0 -32
- package/shaders/split.wgsl +0 -15
- package/shaders/sub.wgsl +0 -34
- package/shaders/tanh.wgsl +0 -13
- package/shaders/upsample2x.wgsl +0 -24
- package/shaders/where.wgsl +0 -12
- package/volvoxai.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,31 +1,50 @@
|
|
|
1
1
|
# VolvoxAI
|
|
2
2
|
|
|
3
|
-
**A zero-dependency, bare-metal deep learning
|
|
4
|
-
Node.js, and native Windows/Linux/macOS/Android targets.**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
or
|
|
10
|
-
|
|
11
|
-
The
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
**A zero-dependency, bare-metal deep learning engine for the
|
|
4
|
+
browser, Node.js, and native Windows/Linux/macOS/Android targets.**
|
|
5
|
+
|
|
6
|
+
> 🧭 **New here — want to *understand* how AI actually works, not just use a library?**
|
|
7
|
+
> This repo doubles as a from-scratch **textbook** built on its own real code. Pick your path:
|
|
8
|
+
>
|
|
9
|
+
> - 🌱 **Just curious what AI really is?** → [Start the **Idea track**](docs/textbook/README.md) — plain words, analogies, **no code or math required**. A motivated 11-year-old can follow it.
|
|
10
|
+
> - 🔧 **Can code a little and want to see it run?** → [The **Build track**](docs/textbook/README.md) — the same ideas in graphs, JavaScript, and operators.
|
|
11
|
+
> - 🔬 **A developer who wants the engine?** → [The **Deep track**](docs/textbook/README.md) + [ARCHITECTURE.md](ARCHITECTURE.md) — quantization, native, optimization, and training internals.
|
|
12
|
+
>
|
|
13
|
+
> One book, three depths. Everything below this line is the **product / release reference** for people who just want to install and ship.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
VolvoxAI runs and trains neural-network graphs without shipping a full ML
|
|
18
|
+
runtime. Load a small Volvox blueprint plus safetensors weights, or use the full
|
|
19
|
+
entry to create an empty model, initialize its parameters, and build it entirely
|
|
20
|
+
through the API.
|
|
21
|
+
The resulting graph can run through WebNN, WebGPU, WASM SIMD, pure JS, or a
|
|
22
|
+
freestanding native C binary.
|
|
23
|
+
|
|
24
|
+
The project is built for small, inspectable model packages, constrained web
|
|
25
|
+
apps, extensions, local tools, and edge devices where heavyweight runtimes such
|
|
26
|
+
as ONNX Runtime Web or TensorFlow.js are too large or too opaque. Training is an
|
|
27
|
+
explicit path: inference does not allocate gradients, optimizer state, or
|
|
28
|
+
backward pipelines. The inference bundle has no training dependency; the full
|
|
29
|
+
bundle adds training as a separate public entry.
|
|
14
30
|
|
|
15
31
|
## Highlights
|
|
16
32
|
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
-
|
|
33
|
+
- Runs in browsers, Node.js, and native applications through WebNN, WebGPU,
|
|
34
|
+
WASM, JavaScript CPU, native CPU, Vulkan, OpenGL, and Metal.
|
|
35
|
+
- Compact current Linux x86-64 artifacts: 360 KiB WASM-only JS, 683 KiB
|
|
36
|
+
multi-backend inference JS, 174 KiB inference WASM, and 936 KiB native
|
|
37
|
+
inference; full training builds remain about 1–1.4 MiB.
|
|
38
|
+
- No external ML runtime: models use inspectable `config.json` graphs and
|
|
39
|
+
safetensors weights.
|
|
40
|
+
- Clean inference/training separation: inference builds contain no autograd,
|
|
41
|
+
optimizer state, backward shaders, or public training symbols.
|
|
42
|
+
- Built-in model construction, training, LoRA, checkpointing, PTQ, and portable
|
|
43
|
+
W8A8 execution.
|
|
44
|
+
- Extensible browser and native backend APIs with embedded native shaders and
|
|
45
|
+
portable CPU fallback.
|
|
46
|
+
- Includes EfficientDet, TinyStories, multimodal examples, and a three-level
|
|
47
|
+
textbook.
|
|
29
48
|
|
|
30
49
|
## Install
|
|
31
50
|
|
|
@@ -37,27 +56,44 @@ For local development from this repository:
|
|
|
37
56
|
|
|
38
57
|
```bash
|
|
39
58
|
npm install
|
|
59
|
+
npm run typecheck
|
|
40
60
|
npm run build:all
|
|
41
61
|
```
|
|
42
62
|
|
|
43
|
-
The
|
|
63
|
+
The TypeScript sources are checked before esbuild emits the six fixed-name
|
|
64
|
+
JavaScript bundles; the build preserves an existing WASM sidecar. For version
|
|
65
|
+
0.2.0, the complete browser release consists of:
|
|
44
66
|
|
|
45
67
|
```text
|
|
46
|
-
dist/volvoxai.js
|
|
47
|
-
dist/volvoxai.min.js
|
|
68
|
+
dist/0.2.0/volvoxai.js # readable inference
|
|
69
|
+
dist/0.2.0/volvoxai.min.js # minified inference
|
|
70
|
+
dist/0.2.0/volvoxai.full.js # readable inference + training
|
|
71
|
+
dist/0.2.0/volvoxai.full.min.js # minified inference + training
|
|
72
|
+
dist/0.2.0/volvoxai.wasm.js # readable WASM-only inference + training/PTQ
|
|
73
|
+
dist/0.2.0/volvoxai.wasm.min.js # minified WASM-only inference + training/PTQ
|
|
74
|
+
dist/0.2.0/volvoxai.wasm # forward kernels used by the WASM backend
|
|
75
|
+
dist/0.2.0/volvoxai.full.wasm # forward kernels plus C training/PTQ ABIs
|
|
48
76
|
```
|
|
49
77
|
|
|
50
|
-
|
|
51
|
-
|
|
78
|
+
`volvoxai.wasm` deliberately exports no training symbol. `volvoxai.full.wasm`
|
|
79
|
+
keeps every forward export and adds C loss, backward, gradient utility, SGD, and
|
|
80
|
+
AdamW operators plus generic PTQ observation, affine quantization, weight
|
|
81
|
+
packing, and bias packing. Quantized LoRA synchronization is one higher-level
|
|
82
|
+
use of those reusable kernels. From a clean checkout, the reproducible Docker
|
|
83
|
+
build creates all eight files:
|
|
52
84
|
|
|
53
85
|
```bash
|
|
54
86
|
make build_web
|
|
55
87
|
```
|
|
56
88
|
|
|
89
|
+
The npm `prepack` check rejects a missing sidecar or stale extra artifact.
|
|
90
|
+
`npm run build:all` bundles JavaScript but cannot compile C/WASM from a clean
|
|
91
|
+
checkout; use `make build_web` before `npm pack` or `npm publish`.
|
|
92
|
+
|
|
57
93
|
## Browser Usage
|
|
58
94
|
|
|
59
95
|
```javascript
|
|
60
|
-
import { VolvoxAI } from './volvoxai.js';
|
|
96
|
+
import { VolvoxAI } from './dist/0.2.0/volvoxai.js';
|
|
61
97
|
|
|
62
98
|
const engine = await VolvoxAI.init(); // auto: WebNN, WebGPU, WASM, CPU
|
|
63
99
|
const graph = await engine.loadGraph('./models/my-model/model.safetensors');
|
|
@@ -70,19 +106,232 @@ const inputs = {
|
|
|
70
106
|
const output = await executor.execute(inputs);
|
|
71
107
|
```
|
|
72
108
|
|
|
109
|
+
Every input referenced by a blueprint node must be declared in `config.inputs`,
|
|
110
|
+
loaded as a named weight, or produced by an earlier node. The loader does not
|
|
111
|
+
invent a default image input or shape for an undeclared name.
|
|
112
|
+
|
|
73
113
|
On WebGPU, `execute()` currently returns a `GPUBuffer` for the final node's first
|
|
74
|
-
output.
|
|
114
|
+
output. The executor owns GPU buffers; core `Tensor` objects contain portable
|
|
115
|
+
descriptors and optional CPU storage, not device handles. WASM and CPU return a
|
|
116
|
+
map keyed by `graph.outputNames`. All four browser engines share the versioned
|
|
117
|
+
backend lifecycle, named registration hook, and decode-session facade described
|
|
118
|
+
in [Browser and Node runtime](docs/browser-runtime.md#javascript-backend-contract).
|
|
119
|
+
|
|
120
|
+
### WASM-only Chrome extensions, training, and PTQ
|
|
121
|
+
|
|
122
|
+
For a Manifest V3 extension that needs no CPU, WebNN, WebGPU, or shader code,
|
|
123
|
+
ship exactly one JavaScript variant, the full WASM sidecar, and the model:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
vendor/volvoxai.wasm.min.js
|
|
127
|
+
vendor/volvoxai.full.wasm
|
|
128
|
+
model/config.json
|
|
129
|
+
model/model.safetensors
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`volvoxai.wasm.min.js` names the only selectable backend, not a forward-only
|
|
133
|
+
capability set. It uses `volvoxai.full.wasm` because updating LoRA A/B still
|
|
134
|
+
requires backward propagation through the surrounding graph. The ordinary
|
|
135
|
+
`volvoxai.wasm` sidecar remains forward-only for the standard inference entry.
|
|
136
|
+
The `./wasm` and `./wasm/min` package subpaths are browser-only and deliberately
|
|
137
|
+
omit Node's filesystem loader; Node applications should use `.` or `./full`
|
|
138
|
+
and select the WASM backend.
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
import { VolvoxAI } from './vendor/volvoxai.wasm.min.js';
|
|
142
|
+
|
|
143
|
+
const runtime = await VolvoxAI.init(
|
|
144
|
+
'wasm',
|
|
145
|
+
chrome.runtime.getURL('vendor/volvoxai.full.wasm'),
|
|
146
|
+
);
|
|
147
|
+
const graph = await runtime.loadGraph(
|
|
148
|
+
chrome.runtime.getURL('model/model.safetensors'),
|
|
149
|
+
);
|
|
150
|
+
const executor = await runtime.compile(graph);
|
|
151
|
+
|
|
152
|
+
const step = await runtime.trainLoRAStep(graph, {
|
|
153
|
+
inputs: teacherForcedInputs,
|
|
154
|
+
logitsTensor: 'logits',
|
|
155
|
+
targets: correctedTokenIds,
|
|
156
|
+
trainableTensors: ['decoder.lora_a', 'decoder.lora_b'],
|
|
157
|
+
updateMode: 'adamw',
|
|
158
|
+
optimizer: { learningRate: 1e-4 },
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Applied updates refresh packed WASM weights, so this executor observes A/B.
|
|
162
|
+
const corrected = await executor.execute(nextInputs);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The same runtime exposes the existing stateless C PTQ implementation as a
|
|
166
|
+
generic typed toolkit, independent of LoRA:
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
const ptq = await runtime.createPTQ();
|
|
170
|
+
try {
|
|
171
|
+
const observer = ptq.createObserver();
|
|
172
|
+
observer.observe(calibrationValues); // Float32Array; repeat for more samples
|
|
173
|
+
|
|
174
|
+
const parameters = observer.parameters({
|
|
175
|
+
dtype: 'int8',
|
|
176
|
+
scheme: 'symmetric',
|
|
177
|
+
});
|
|
178
|
+
const activation = ptq.quantize(values, parameters);
|
|
179
|
+
const weight = ptq.packWeight(weightValues, [outputSize, inputSize], { axis: 0 });
|
|
180
|
+
const bias = ptq.packBias(biasValues, parameters.scale, weight.scales);
|
|
181
|
+
} finally {
|
|
182
|
+
ptq.dispose();
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
These calls run in a private scratch WASM instance and return caller-owned
|
|
187
|
+
typed arrays. They do not rewrite a graph or choose how an application stores
|
|
188
|
+
or deploys the result. Reuse one toolkit across related operations and call
|
|
189
|
+
`dispose()` when finished so its isolated WASM memory can be garbage-collected.
|
|
190
|
+
Developers may use it for calibration, conversion, custom model builders, or
|
|
191
|
+
their own update workflow. Browser safetensors and graph/package authoring
|
|
192
|
+
remain JavaScript orchestration rather than C file I/O.
|
|
193
|
+
|
|
194
|
+
The model must represent LoRA A/B as explicit initialized F32 graph weights and
|
|
195
|
+
wire them through its low-rank MatMul/Add branch. Listing only those names in
|
|
196
|
+
`trainableTensors` freezes the base model. A corrected answer string is
|
|
197
|
+
application policy: tokenize it and construct teacher-forced model inputs,
|
|
198
|
+
target token IDs, and any loss mask before calling `trainLoRAStep()`.
|
|
199
|
+
Immutable staged adapter snapshots are deployment/routing objects, not
|
|
200
|
+
autograd parameters; checkpoint or export the updated explicit graph factors
|
|
201
|
+
after training.
|
|
202
|
+
|
|
203
|
+
To retain an existing W8A8 inference topology, use a separate supported F32
|
|
204
|
+
training graph as the persistent master and bind its A/B factors to the I8
|
|
205
|
+
factor weights already present in the inference graph:
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
const trainer = await runtime.createQuantizedLoRATrainer(
|
|
209
|
+
f32TrainingGraph,
|
|
210
|
+
w8InferenceGraph,
|
|
211
|
+
{
|
|
212
|
+
bindings: [
|
|
213
|
+
{ master: 'decoder.lora_a', target: 'decoder.lora_a.i8', transpose: true },
|
|
214
|
+
{ master: 'decoder.lora_b', target: 'decoder.lora_b.i8', transpose: true },
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
// Use this once only when starting from a W8 snapshot without an F32
|
|
221
|
+
// checkpoint. Do not dequantize again after training begins.
|
|
222
|
+
await trainer.initializeMastersFromQuantized();
|
|
223
|
+
|
|
224
|
+
await trainer.trainStep({
|
|
225
|
+
inputs: teacherForcedInputs,
|
|
226
|
+
logitsTensor: 'logits',
|
|
227
|
+
targets: correctedTokenIds,
|
|
228
|
+
trainableTensors: ['decoder.lora_a', 'decoder.lora_b'],
|
|
229
|
+
updateMode: 'adamw',
|
|
230
|
+
optimizer: { learningRate: 1e-4 },
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const corrected = await trainer.engine.execute(nextQuantizedInputs);
|
|
234
|
+
} finally {
|
|
235
|
+
await trainer.dispose();
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The C conversion helper transposes the builder's IN_OUT factors into canonical
|
|
240
|
+
OUT_IN I8 weights and recomputes symmetric axis-0 scales. The JavaScript trainer
|
|
241
|
+
stages every converted factor before atomically updating the graph, then
|
|
242
|
+
refreshes the WASM raw bytes, scale metadata, and packed Q8 caches without
|
|
243
|
+
changing nodes or activation descriptors. Version 0.2.0 requires I8 targets
|
|
244
|
+
with zero points of zero and all-zero I32 LoRA biases. Persist the F32
|
|
245
|
+
checkpoint and optimizer state as the resumable authority; the W8 graph is an
|
|
246
|
+
inference snapshot. After restoring an F32 checkpoint, call `trainer.sync()`
|
|
247
|
+
instead of `initializeMastersFromQuantized()`.
|
|
248
|
+
|
|
249
|
+
This is F32-master LoRA requantization, not QAT or backward support for a deep
|
|
250
|
+
W8A8 graph. `QLinear`/`QGemm` are still rejected by strict WASM training, so
|
|
251
|
+
the separate training graph must provide the supported F32 backward path. The
|
|
252
|
+
inference graph must already contain its quantized LoRA branch; this API does
|
|
253
|
+
not rewrite graph topology.
|
|
254
|
+
|
|
255
|
+
The extension must package all executable code locally and enable WebAssembly
|
|
256
|
+
for extension pages. Use an ES-module service worker and this CSP:
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"manifest_version": 3,
|
|
261
|
+
"background": { "service_worker": "service-worker.js", "type": "module" },
|
|
262
|
+
"content_security_policy": {
|
|
263
|
+
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The WASM-only release bundle contains no dynamic `import()`, which Chrome
|
|
269
|
+
extension service workers do not support. `web_accessible_resources` is not
|
|
270
|
+
needed when only extension-owned pages/workers fetch the packaged model and
|
|
271
|
+
sidecar; declare the narrow resources explicitly if a normal web page must
|
|
272
|
+
fetch them. See [Browser and Node runtime](docs/browser-runtime.md#wasm-only-manifest-v3-extensions)
|
|
273
|
+
for complete packaging notes.
|
|
274
|
+
|
|
275
|
+
## Training from APIs
|
|
276
|
+
|
|
277
|
+
Use the full entry when calling training, checkpoint, or gradient-accumulation
|
|
278
|
+
APIs:
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
import { VolvoxAI } from './dist/0.2.0/volvoxai.full.js';
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
In this module, the familiar `VolvoxAI`, `Graph`, and `ModelBuilder` exports are
|
|
285
|
+
the training-capable variants; the explicit `TrainingVolvoxAI`,
|
|
286
|
+
`TrainingGraph`, and `TrainingModelBuilder` names are also available.
|
|
287
|
+
Initializers, optimizer state, and training-only builder helpers are deliberately
|
|
288
|
+
absent from the inference entry.
|
|
289
|
+
|
|
290
|
+
Models can start from an empty graph and initialized weights; no PyTorch export
|
|
291
|
+
or seed safetensors file is required. The JavaScript builder provides generic
|
|
292
|
+
GroupNorm, MoE and routed bottleneck adapters, deterministic Dropout, and
|
|
293
|
+
explicit trainable-tensor selection. The repository's
|
|
294
|
+
`examples/seq2seq_training/Seq2SeqBuilder.js` composes those primitives into an
|
|
295
|
+
encoder-decoder with multimodal source features and teacher forcing; that
|
|
296
|
+
model-family policy is not exported by either package entry.
|
|
297
|
+
|
|
298
|
+
`trainStep()` accepts either the legacy single cross-entropy target or a
|
|
299
|
+
`losses` list with independent logits, targets, weights, masks, and normalizers.
|
|
300
|
+
Repeated logits tensors are allowed and their gradients add. Accumulation has
|
|
301
|
+
reset/flush controls, and `maxGradNorm` clips one global norm over all trainable
|
|
302
|
+
tensors. JavaScript CPU and WebGPU regenerate the same SDPA/CrossSDPA
|
|
303
|
+
attention-dropout mask in forward and backward; inference never applies it.
|
|
304
|
+
|
|
305
|
+
For an explicit C-backed browser training path, initialize the full entry with
|
|
306
|
+
the full sidecar and set `backend: "wasm"`. It is strict: its current portable
|
|
307
|
+
contracts are listed in [the operation status reference](docs/operation_list.md).
|
|
308
|
+
Unsupported or non-canonical layouts are rejected before any model state
|
|
309
|
+
changes, including ambiguous square linear layouts.
|
|
310
|
+
|
|
311
|
+
Native CPU, Vulkan, OpenGL compute, and Metal support deterministic standalone
|
|
312
|
+
Dropout training while keeping inference as an identity. Their SDPA/CrossSDPA
|
|
313
|
+
training paths also implement after-softmax attention-probability dropout and
|
|
314
|
+
regenerate the mask during backward; unsupported GPU layouts fall back to the
|
|
315
|
+
matching complete native CPU path. See
|
|
316
|
+
[model construction, routing, and training](docs/model_builder_training.md) and
|
|
317
|
+
the [operation matrix](docs/operation_list.md) for exact backend limits.
|
|
75
318
|
|
|
76
319
|
## Native Usage
|
|
77
320
|
|
|
78
321
|
```bash
|
|
79
322
|
make build_native
|
|
80
323
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
324
|
+
# inference-only executable
|
|
325
|
+
./native/volvoxai --help
|
|
326
|
+
|
|
327
|
+
# inference + training executable
|
|
328
|
+
./native/volvoxai-full --help
|
|
84
329
|
```
|
|
85
330
|
|
|
331
|
+
The fixed release executables stay model-agnostic: both expose `run`, and only
|
|
332
|
+
`volvoxai-full` additionally exposes `train`. They do not choose vocabulary
|
|
333
|
+
files, decode images, or implement generation and task postprocessing.
|
|
334
|
+
|
|
86
335
|
Generic tensor execution:
|
|
87
336
|
|
|
88
337
|
```bash
|
|
@@ -90,9 +339,47 @@ Generic tensor execution:
|
|
|
90
339
|
--input tokens=models/tinystories_1m/tokens.i32 \
|
|
91
340
|
--input positions=models/tinystories_1m/positions.i32 \
|
|
92
341
|
--output logits=out.f32 \
|
|
93
|
-
--
|
|
342
|
+
--row 4
|
|
94
343
|
```
|
|
95
344
|
|
|
345
|
+
Raw input and output filenames must end in the declared storage dtype suffix:
|
|
346
|
+
`.f32`, `.f16`, `.i32`, `.i8`, or `.u8`. Row output is currently F32-only.
|
|
347
|
+
|
|
348
|
+
Generic cross-entropy training is available only in the full executable:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
./native/volvoxai-full train models/my_model \
|
|
352
|
+
--input input=batch.f32 \
|
|
353
|
+
--targets targets.i32 \
|
|
354
|
+
--logits logits \
|
|
355
|
+
--trainable classifier.weight \
|
|
356
|
+
--trainable classifier.bias \
|
|
357
|
+
--steps 10 \
|
|
358
|
+
--learning-rate 0.001 \
|
|
359
|
+
--output-weights trained.safetensors \
|
|
360
|
+
--output-optimizer optimizer.safetensors
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Use `--input-optimizer` to resume saved optimizer state. Run
|
|
364
|
+
`./native/volvoxai-full train --help` for all optimizer and backend options.
|
|
365
|
+
|
|
366
|
+
Model-facing native task wrappers are an opt-in example:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
make -C examples native_task_cli
|
|
370
|
+
|
|
371
|
+
examples/target/bin/volvoxai-tasks generate models/tinystories_1m \
|
|
372
|
+
--prompt "Once upon a time, Lily" \
|
|
373
|
+
--max-new 50
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
That example owns image decoding, vocabulary-file selection, generation loops,
|
|
377
|
+
and the `generate`, `classify`, `detect`, `ctc`, `seq2seq`, and `chat` commands.
|
|
378
|
+
|
|
379
|
+
Native executables do not need a shader directory. For shader development,
|
|
380
|
+
point `VOLVOXAI_SHADER_DIR` at a generated directory containing `spv/`,
|
|
381
|
+
`glsl/`, `gles/`, and `metal/`; VolvoxAI logs once when that override is used.
|
|
382
|
+
|
|
96
383
|
## Example Models
|
|
97
384
|
|
|
98
385
|
Model weights are not committed. Regenerate the example packages from public
|
|
@@ -109,21 +396,37 @@ See [docs/models.md](docs/models.md) for export details.
|
|
|
109
396
|
## Repository Layout
|
|
110
397
|
|
|
111
398
|
```text
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
examples/
|
|
117
|
-
|
|
118
|
-
|
|
399
|
+
ts/core/ TypeScript inference graph/data objects and model-agnostic orchestration
|
|
400
|
+
ts/ops/ TypeScript operators plus graph validation and normalization
|
|
401
|
+
ts/backends/ TypeScript CPU, WASM, WebGPU, and WebNN execution/device resources
|
|
402
|
+
ts/training/ TypeScript training graphs/builders, autograd, optimizers, checkpoints
|
|
403
|
+
examples/ Model-specific applications and reference integrations
|
|
404
|
+
shaders/inference/ Forward WGSL sources
|
|
405
|
+
shaders/training/ Backward and training WGSL sources
|
|
406
|
+
native/include/ Public C APIs
|
|
407
|
+
native/src/shader_store.* Lazy embedded-shader asset loader
|
|
408
|
+
native/src/runtime/ Model state, graph, memory, and execution
|
|
409
|
+
native/src/kernels/ Portable and optimized CPU/WASM kernels
|
|
410
|
+
native/src/backends/ Vulkan, OpenGL, Metal, and NNAPI integrations
|
|
411
|
+
native/src/training/ Training-specific orchestration
|
|
412
|
+
native/cli/ Fixed model-agnostic command-line applications
|
|
413
|
+
native/tests/ Native tests
|
|
414
|
+
runtime/ Rust service wrapper around the C engine
|
|
119
415
|
```
|
|
120
416
|
|
|
417
|
+
See [ARCHITECTURE.md](ARCHITECTURE.md) for dependency and build-composition
|
|
418
|
+
rules.
|
|
419
|
+
|
|
121
420
|
## Documentation
|
|
122
421
|
|
|
123
422
|
- [Quickstart](docs/quickstart.md)
|
|
124
423
|
- [Browser and Node runtime](docs/browser-runtime.md)
|
|
125
424
|
- [Native runtime](docs/native-runtime.md)
|
|
425
|
+
- [Custom backend SDK](docs/backend-sdk.md)
|
|
126
426
|
- [Model format](docs/model-format.md)
|
|
427
|
+
- [W8A8 safetensors companion scales](docs/w8a8-safetensors.md)
|
|
428
|
+
- [Post-training quantization](docs/quantization.md)
|
|
429
|
+
- [Model construction, routing, and training](docs/model_builder_training.md)
|
|
127
430
|
- [Models and exporters](docs/models.md)
|
|
128
431
|
- [Operation support matrix](docs/operation_list.md)
|
|
129
432
|
- [Testing and validation](docs/testing.md)
|
|
@@ -135,8 +438,8 @@ docs/ Detailed documentation
|
|
|
135
438
|
|
|
136
439
|
VolvoxAI can run real browser and native inference paths, but it is still early.
|
|
137
440
|
Known gaps include WebGPU multi-output readback, broader WebNN coverage, additional
|
|
138
|
-
native/WebGPU shaders for a few fallback ops, browser-side generation helpers,
|
|
139
|
-
formal CI wiring for the existing smoke tests.
|
|
441
|
+
native/WebGPU shaders for a few fallback ops, browser-side generation helpers,
|
|
442
|
+
and formal CI wiring for the existing smoke tests.
|
|
140
443
|
|
|
141
444
|
See [docs/roadmap.md](docs/roadmap.md) for the detailed list.
|
|
142
445
|
|
package/bin/volvox.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
|
-
import { VolvoxAI } from '../js/index.js';
|
|
5
4
|
import fs from 'fs';
|
|
6
5
|
import path from 'path';
|
|
7
6
|
import { fileURLToPath } from 'url';
|
|
8
7
|
|
|
8
|
+
const packageVersion = JSON.parse(
|
|
9
|
+
fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
|
|
10
|
+
).version;
|
|
11
|
+
const { VolvoxAI } = await import(
|
|
12
|
+
new URL(`../dist/${packageVersion}/volvoxai.js`, import.meta.url)
|
|
13
|
+
);
|
|
14
|
+
|
|
9
15
|
const program = new Command();
|
|
10
16
|
|
|
11
17
|
program
|
|
12
18
|
.name('volvox')
|
|
13
19
|
.description('Volvox AI CLI for running local inference')
|
|
14
|
-
.version(
|
|
20
|
+
.version(packageVersion);
|
|
15
21
|
|
|
16
22
|
program
|
|
17
23
|
.command('run')
|
|
@@ -23,7 +29,7 @@ program
|
|
|
23
29
|
installFileFetchShim();
|
|
24
30
|
console.log(`[Volvox CLI] Initializing Engine (Backend: ${options.backend})...`);
|
|
25
31
|
const cliDir = path.dirname(fileURLToPath(import.meta.url));
|
|
26
|
-
const wasmPath = path.resolve(cliDir, '..', 'volvoxai.wasm');
|
|
32
|
+
const wasmPath = path.resolve(cliDir, '..', 'dist', packageVersion, 'volvoxai.wasm');
|
|
27
33
|
const engine = await VolvoxAI.init(options.backend, wasmPath);
|
|
28
34
|
|
|
29
35
|
console.log(`[Volvox CLI] Loading Model: ${options.model}`);
|