mlx-bun 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +362 -0
- package/THIRD_PARTY_LICENSES.md +41 -0
- package/bin/mlx-bun.mjs +32 -0
- package/docs/curve-designer.html +303 -0
- package/docs/design/adapters-end-to-end.md +201 -0
- package/docs/design/compat-cli-surface-design.md +227 -0
- package/docs/design/docs-reorg-plan.md +152 -0
- package/docs/design/hlg-sampling.md +340 -0
- package/docs/design/memory-system.md +339 -0
- package/docs/design/optimization_plan.md +344 -0
- package/docs/design/parallel-slots.md +515 -0
- package/docs/design/runtime-isolation.md +247 -0
- package/docs/design/segmented-backward-training.md +508 -0
- package/docs/investigations/chunk-finetune-experiment.md +84 -0
- package/docs/investigations/curve-bisector-routing.md +123 -0
- package/docs/investigations/curve-runs/bisector-route.json +98 -0
- package/docs/investigations/curve-runs/bisector-trace.json +1393 -0
- package/docs/investigations/curve-runs/curve-terrain.json +1179 -0
- package/docs/investigations/curve-runs/curve-terrain.svg +42 -0
- package/docs/investigations/curve-terrain.html +105 -0
- package/docs/investigations/expert-offload-single-user-moe.md +292 -0
- package/docs/investigations/hlg-ab.html +34 -0
- package/docs/investigations/hlg-explorer.html +238 -0
- package/docs/investigations/hlg-figs/cliff.svg +1 -0
- package/docs/investigations/hlg-figs/cross.svg +1 -0
- package/docs/investigations/hlg-figs/edges.svg +1 -0
- package/docs/investigations/hlg-figs/k20-grids.svg +1 -0
- package/docs/investigations/hlg-figs/k20-peaks.svg +1 -0
- package/docs/investigations/hlg-figs/lw-curve.svg +1 -0
- package/docs/investigations/hlg-figs/terrain.svg +1 -0
- package/docs/investigations/hlg-report.html +262 -0
- package/docs/investigations/hlg-runs/hlg-ab.json +149 -0
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +87 -0
- package/docs/investigations/hlg-runs/hlg-blind.json +107 -0
- package/docs/investigations/hlg-runs/hlg-cliff.json +197 -0
- package/docs/investigations/hlg-runs/hlg-cross.json +505 -0
- package/docs/investigations/hlg-runs/hlg-edge.json +388 -0
- package/docs/investigations/hlg-runs/hlg-eval1.json +25 -0
- package/docs/investigations/hlg-runs/hlg-frontier.json +86 -0
- package/docs/investigations/hlg-runs/hlg-grid.json +242 -0
- package/docs/investigations/hlg-runs/hlg-grid2.json +343 -0
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +110 -0
- package/docs/investigations/hlg-runs/hlg-map.json +383 -0
- package/docs/investigations/hlg-runs/run0-original.log +159 -0
- package/docs/investigations/hlg-runs/runA-recommended.log +131 -0
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +26 -0
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +18 -0
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +25 -0
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +8 -0
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +51 -0
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +10 -0
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +16 -0
- package/docs/investigations/hlg-runs/runB-gain-variants.log +192 -0
- package/docs/investigations/hlg-runs/runC-pivots.log +162 -0
- package/docs/investigations/hlg-runs/runD-oetf.log +132 -0
- package/docs/investigations/hlg-runs/runE-eotf.log +162 -0
- package/docs/investigations/hlg-runs/runF-shaper-working.log +86 -0
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +101 -0
- package/docs/investigations/hlg-runs/runH-wsweep.log +176 -0
- package/docs/investigations/hlg-runs/runI-asweep.log +176 -0
- package/docs/investigations/hlg-runs/runJ-knobmap.log +49 -0
- package/docs/investigations/hlg-runs/runK-frontier.log +19 -0
- package/docs/investigations/hlg-runs/runL-widemap.log +65 -0
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +15 -0
- package/docs/investigations/hlg-runs/runN-verify.log +116 -0
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +15 -0
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +15 -0
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +15 -0
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +79 -0
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +33 -0
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +33 -0
- package/docs/investigations/hlg-runs/runU-cross-12b.log +33 -0
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +22 -0
- package/docs/investigations/hlg-runs/runW-lw-12b.log +22 -0
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +22 -0
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +26 -0
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +26 -0
- package/docs/investigations/hlg-sampling-investigation.md +970 -0
- package/docs/investigations/lab-build-journal.md +157 -0
- package/docs/investigations/pi-builtin-investigation.md +308 -0
- package/docs/investigations/starter-model-port-handoff.md +323 -0
- package/docs/planning/IDEAS.md +26 -0
- package/docs/planning/PRODUCT_ROADMAP.md +426 -0
- package/docs/planning/ResearchTopics.md +119 -0
- package/docs/planning/chunk-task-roadmap.md +77 -0
- package/docs/planning/journal.md +155 -0
- package/docs/reference/distribution.md +121 -0
- package/docs/reference/embedding.md +168 -0
- package/docs/reference/library-api.md +153 -0
- package/docs/reference/server-api.md +224 -0
- package/docs/reference/server-config.md +243 -0
- package/docs/segmented-backward-handoff.md +148 -0
- package/package.json +68 -0
- package/src/anthropic.ts +491 -0
- package/src/chat-template.ts +186 -0
- package/src/cli.ts +1075 -0
- package/src/config.ts +229 -0
- package/src/curve-sampler.ts +122 -0
- package/src/dataset/generators.ts +1087 -0
- package/src/dataset/index.ts +12 -0
- package/src/dataset/job.ts +81 -0
- package/src/dataset/llm.ts +71 -0
- package/src/dataset/registry.ts +528 -0
- package/src/download.ts +283 -0
- package/src/eval/README.md +86 -0
- package/src/eval/kl-prompts.ts +29 -0
- package/src/eval/kl.ts +294 -0
- package/src/eval/quality-db.ts +92 -0
- package/src/eval/runner.ts +102 -0
- package/src/eval/score.ts +49 -0
- package/src/eval/tasks/bfcl.ts +500 -0
- package/src/eval/tasks/gsm8k.ts +85 -0
- package/src/eval/tasks/hashhop.ts +109 -0
- package/src/eval/tasks/humaneval.ts +252 -0
- package/src/eval/tasks/ifeval.ts +354 -0
- package/src/eval/tasks/mmlu.ts +145 -0
- package/src/evaldb.ts +199 -0
- package/src/expert-offload-build.ts +77 -0
- package/src/expert-offload.ts +61 -0
- package/src/expert-trace.ts +67 -0
- package/src/fit.ts +254 -0
- package/src/generate.ts +451 -0
- package/src/harness-pi.ts +177 -0
- package/src/hf-push.ts +628 -0
- package/src/index.ts +22 -0
- package/src/jobs/db.ts +139 -0
- package/src/jobs/index.ts +29 -0
- package/src/jobs/job-entry.ts +106 -0
- package/src/jobs/runner.ts +304 -0
- package/src/jobs/sse.ts +114 -0
- package/src/jobs/types.ts +58 -0
- package/src/kv-store.ts +185 -0
- package/src/lora.ts +314 -0
- package/src/md-modules.d.ts +7 -0
- package/src/mlx/array.ts +237 -0
- package/src/mlx/autograd.ts +267 -0
- package/src/mlx/checkpoint.ts +116 -0
- package/src/mlx/compile.ts +158 -0
- package/src/mlx/custom-vjp.ts +140 -0
- package/src/mlx/ffi.ts +433 -0
- package/src/mlx/metal-kernel.ts +130 -0
- package/src/mlx/ops.ts +707 -0
- package/src/mmap.ts +90 -0
- package/src/model/batched-mask.ts +204 -0
- package/src/model/batched-rotating.ts +300 -0
- package/src/model/compiled-decode.ts +681 -0
- package/src/model/factory.ts +27 -0
- package/src/model/fingerprint.ts +33 -0
- package/src/model/flash-attention.ts +674 -0
- package/src/model/fused-decode-kernel.ts +305 -0
- package/src/model/fused-geglu-kernel.ts +87 -0
- package/src/model/gemma4-base.ts +1616 -0
- package/src/model/gemma4.ts +1012 -0
- package/src/model/generated/gemma4-12b.ts +526 -0
- package/src/model/generated/gemma4-26b.ts +500 -0
- package/src/model/generated/gemma4-e4b.ts +757 -0
- package/src/model/generated/index.ts +18 -0
- package/src/model/minicpm5.ts +278 -0
- package/src/model/qwen3-delta.ts +224 -0
- package/src/model/qwen3_5.ts +429 -0
- package/src/model/support.ts +46 -0
- package/src/native-pack.ts +152 -0
- package/src/pi-provider.ts +95 -0
- package/src/pi-terminal.ts +264 -0
- package/src/pi-web.ts +924 -0
- package/src/preflight.ts +123 -0
- package/src/prompt-cache.ts +113 -0
- package/src/quantize/allocator.ts +627 -0
- package/src/quantize/calibration.ts +180 -0
- package/src/quantize/config-writer.ts +132 -0
- package/src/quantize/index.ts +57 -0
- package/src/quantize/job.ts +136 -0
- package/src/quantize/quantizer.ts +462 -0
- package/src/quantize/safetensors-writer.ts +171 -0
- package/src/quantize/sensitivity.ts +234 -0
- package/src/registry.ts +336 -0
- package/src/responses.ts +774 -0
- package/src/safetensors.ts +158 -0
- package/src/sampler.ts +517 -0
- package/src/serve/batch-scheduler.ts +362 -0
- package/src/serve/generation-gateway.ts +160 -0
- package/src/server.ts +1891 -0
- package/src/spec/drafter.ts +261 -0
- package/src/spec/generate.ts +221 -0
- package/src/status-page.html +497 -0
- package/src/tokenizer.ts +38 -0
- package/src/tool-call.ts +242 -0
- package/src/train/dataset.ts +461 -0
- package/src/train/export.ts +32 -0
- package/src/train/forward.ts +229 -0
- package/src/train/index.ts +43 -0
- package/src/train/job.ts +148 -0
- package/src/train/lora-params.ts +194 -0
- package/src/train/loss.ts +342 -0
- package/src/train/merge.ts +195 -0
- package/src/train/optimizer.ts +176 -0
- package/src/train/rank.ts +101 -0
- package/src/train/segmented.ts +520 -0
- package/src/train/trainer.ts +600 -0
- package/src/tui.ts +161 -0
- package/src/vision/embedder.ts +168 -0
- package/src/vision/preprocess.ts +247 -0
- package/src/vision/prompt.ts +158 -0
- package/src/vision/siglip.ts +599 -0
- package/src/web/app.html +2471 -0
- package/src/web/skills/web-research/SKILL.md +44 -0
- package/src/web/skills.ts +59 -0
- package/src/web-tools.ts +426 -0
- package/src/weights.ts +91 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Multimodal prompt assembly: OpenAI image_url content parts → spliced
|
|
2
|
+
// token ids + merged input embeddings + image-token mask.
|
|
3
|
+
//
|
|
4
|
+
// The chat template renders one <|image|> token (258880) per image part;
|
|
5
|
+
// we expand each into <boi> + image_token × softTokens + <eoi> (matching
|
|
6
|
+
// optiq's frontend), embed the full sequence, then overwrite the
|
|
7
|
+
// image-token rows with the vision tower's features.
|
|
8
|
+
|
|
9
|
+
import { MlxArray } from "../mlx/array";
|
|
10
|
+
import { Dtype } from "../mlx/ffi";
|
|
11
|
+
import * as ops from "../mlx/ops";
|
|
12
|
+
import type { Gemma4Model } from "../model/gemma4";
|
|
13
|
+
import type { ChatTemplate, ChatMessage, ToolDefinition } from "../chat-template";
|
|
14
|
+
import type { LoadedTokenizer } from "../tokenizer";
|
|
15
|
+
|
|
16
|
+
/** Common contract for both vision towers (encoder-free gemma4_unified in
|
|
17
|
+
* ./embedder.ts and the SigLIP encoder in ./siglip.ts): preprocess image
|
|
18
|
+
* bytes into a tower-specific representation, then turn it into
|
|
19
|
+
* language-space soft tokens [1, softTokens, hidden] (pre-divided by
|
|
20
|
+
* embed_scale). The two own different preprocessing, so the tower carries
|
|
21
|
+
* its own. */
|
|
22
|
+
export interface VisionEncoder<P extends { softTokens: number } = { softTokens: number }> {
|
|
23
|
+
preprocess(bytes: Uint8Array): Promise<P>;
|
|
24
|
+
features(pre: P): MlxArray;
|
|
25
|
+
dispose?(): void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface VisionPrompt {
|
|
29
|
+
ids: number[];
|
|
30
|
+
/** Unscaled merged embeddings [1, L, hidden] — caller disposes. */
|
|
31
|
+
embeddings: MlxArray;
|
|
32
|
+
/** bool [L] image-token mask — caller disposes. */
|
|
33
|
+
imageMask: MlxArray;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface VisionTokenIds {
|
|
37
|
+
imageTokenId: number;
|
|
38
|
+
boiTokenId: number;
|
|
39
|
+
eoiTokenId: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Extract image bytes from OpenAI-style content parts, rewriting the
|
|
43
|
+
* parts to the template's {type:"image"} form. */
|
|
44
|
+
export async function extractImages(
|
|
45
|
+
messages: ChatMessage[],
|
|
46
|
+
): Promise<{ messages: ChatMessage[]; images: Uint8Array[] }> {
|
|
47
|
+
const images: Uint8Array[] = [];
|
|
48
|
+
const out: ChatMessage[] = [];
|
|
49
|
+
for (const m of messages) {
|
|
50
|
+
if (!Array.isArray(m.content)) {
|
|
51
|
+
out.push(m);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const parts: Array<Record<string, unknown>> = [];
|
|
55
|
+
for (const part of m.content) {
|
|
56
|
+
if (part.type === "image_url") {
|
|
57
|
+
const url = (part.image_url as { url: string } | undefined)?.url
|
|
58
|
+
?? (part.image_url as unknown as string);
|
|
59
|
+
if (typeof url !== "string") throw new Error("image_url part missing url");
|
|
60
|
+
images.push(await fetchImageBytes(url));
|
|
61
|
+
parts.push({ type: "image" });
|
|
62
|
+
} else if (part.type === "image") {
|
|
63
|
+
// already template-form: expect base64 `data` or pass-through marker
|
|
64
|
+
if (typeof part.data === "string") {
|
|
65
|
+
images.push(Uint8Array.from(Buffer.from(part.data, "base64")));
|
|
66
|
+
parts.push({ type: "image" });
|
|
67
|
+
} else {
|
|
68
|
+
throw new Error("image part requires base64 `data`");
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
parts.push(part);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
out.push({ ...m, content: parts });
|
|
75
|
+
}
|
|
76
|
+
return { messages: out, images };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function fetchImageBytes(url: string): Promise<Uint8Array> {
|
|
80
|
+
if (url.startsWith("data:")) {
|
|
81
|
+
const comma = url.indexOf(",");
|
|
82
|
+
if (comma === -1) throw new Error("malformed data: URL");
|
|
83
|
+
const meta = url.slice(0, comma);
|
|
84
|
+
const body = url.slice(comma + 1);
|
|
85
|
+
if (!meta.includes("base64")) throw new Error("data: URL must be base64");
|
|
86
|
+
return Uint8Array.from(Buffer.from(body, "base64"));
|
|
87
|
+
}
|
|
88
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
89
|
+
const res = await fetch(url);
|
|
90
|
+
if (!res.ok) throw new Error(`image fetch failed: ${res.status} ${url}`);
|
|
91
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
92
|
+
}
|
|
93
|
+
throw new Error(`unsupported image url scheme: ${url.slice(0, 16)}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function buildVisionPrompt<P extends { softTokens: number }>(
|
|
97
|
+
model: Gemma4Model,
|
|
98
|
+
tower: VisionEncoder<P>,
|
|
99
|
+
tokenizer: LoadedTokenizer,
|
|
100
|
+
template: ChatTemplate,
|
|
101
|
+
messages: ChatMessage[],
|
|
102
|
+
images: Uint8Array[],
|
|
103
|
+
tokenIds: VisionTokenIds,
|
|
104
|
+
tools: ToolDefinition[] | null = null,
|
|
105
|
+
): Promise<VisionPrompt> {
|
|
106
|
+
const rendered = template.render(messages, { tools });
|
|
107
|
+
let ids = tokenizer.encode(rendered);
|
|
108
|
+
if (ids[0] === ids[1] && ids[0] === tokenizer.bosTokenId) ids = ids.slice(1);
|
|
109
|
+
|
|
110
|
+
// preprocess + embed every image (in order of appearance), via the
|
|
111
|
+
// tower's own preprocessing (encoder-free vs SigLIP differ here).
|
|
112
|
+
const pre = await Promise.all(images.map((bytes) => tower.preprocess(bytes)));
|
|
113
|
+
|
|
114
|
+
// expand each <|image|> into <boi> + image_token×soft + <eoi>
|
|
115
|
+
const spliced: number[] = [];
|
|
116
|
+
const runs: { start: number; length: number }[] = [];
|
|
117
|
+
let imgIdx = 0;
|
|
118
|
+
for (const id of ids) {
|
|
119
|
+
if (id === tokenIds.imageTokenId) {
|
|
120
|
+
const p = pre[imgIdx];
|
|
121
|
+
if (!p) throw new Error("more <|image|> markers than images");
|
|
122
|
+
spliced.push(tokenIds.boiTokenId);
|
|
123
|
+
runs.push({ start: spliced.length, length: p.softTokens });
|
|
124
|
+
for (let k = 0; k < p.softTokens; k++) spliced.push(tokenIds.imageTokenId);
|
|
125
|
+
spliced.push(tokenIds.eoiTokenId);
|
|
126
|
+
imgIdx++;
|
|
127
|
+
} else {
|
|
128
|
+
spliced.push(id);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (imgIdx !== images.length)
|
|
132
|
+
throw new Error(`${images.length} images but ${imgIdx} <|image|> markers`);
|
|
133
|
+
|
|
134
|
+
// embed text tokens, then overwrite image-token rows with vision features
|
|
135
|
+
const idsArr = ops.fromInt32(spliced, [1, spliced.length]);
|
|
136
|
+
let embeds = model.embed.encode(idsArr);
|
|
137
|
+
idsArr.dispose();
|
|
138
|
+
const hidden = embeds.shape[2]!;
|
|
139
|
+
for (let i = 0; i < runs.length; i++) {
|
|
140
|
+
const { start, length } = runs[i]!;
|
|
141
|
+
const feats = tower.features(pre[i]!); // [1, soft, hidden]
|
|
142
|
+
const cast = feats.astype(embeds.dtype);
|
|
143
|
+
feats.dispose();
|
|
144
|
+
const updated = ops.sliceUpdate(embeds, cast, [0, start, 0], [1, start + length, hidden]);
|
|
145
|
+
cast.dispose();
|
|
146
|
+
embeds.dispose();
|
|
147
|
+
embeds = updated;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const maskInts = new Int32Array(spliced.length);
|
|
151
|
+
for (let i = 0; i < spliced.length; i++)
|
|
152
|
+
maskInts[i] = spliced[i] === tokenIds.imageTokenId ? 1 : 0;
|
|
153
|
+
const maskI32 = MlxArray.fromInt32(maskInts, [spliced.length]);
|
|
154
|
+
const imageMask = maskI32.astype(Dtype.bool);
|
|
155
|
+
maskI32.dispose();
|
|
156
|
+
|
|
157
|
+
return { ids: spliced, embeddings: embeds, imageMask };
|
|
158
|
+
}
|