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,186 @@
|
|
|
1
|
+
// Chat template rendering via @huggingface/jinja (pure JS, purpose-built
|
|
2
|
+
// for HF chat templates). Decision recorded in PLAN.md Phase 1 findings:
|
|
3
|
+
// rendering the model's own chat_template.jinja beats a hand-port because
|
|
4
|
+
// it can't rot when the model updates its template.
|
|
5
|
+
|
|
6
|
+
import { Template } from "@huggingface/jinja";
|
|
7
|
+
|
|
8
|
+
export interface ToolCall {
|
|
9
|
+
id?: string;
|
|
10
|
+
type?: "function";
|
|
11
|
+
function: {
|
|
12
|
+
name: string;
|
|
13
|
+
/** Object form preferred; OpenAI's JSON-string form is normalized by
|
|
14
|
+
* the server before rendering. */
|
|
15
|
+
arguments: Record<string, unknown> | string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ChatMessage {
|
|
20
|
+
role: string;
|
|
21
|
+
content?: string | Array<Record<string, unknown>> | null;
|
|
22
|
+
tool_calls?: ToolCall[];
|
|
23
|
+
tool_call_id?: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
reasoning?: string;
|
|
26
|
+
reasoning_content?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** OpenAI-style tool definition (function type). */
|
|
30
|
+
export interface ToolDefinition {
|
|
31
|
+
type: "function";
|
|
32
|
+
function: {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
parameters?: Record<string, unknown>;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface RenderOptions {
|
|
40
|
+
addGenerationPrompt?: boolean;
|
|
41
|
+
tools?: ToolDefinition[] | null;
|
|
42
|
+
enableThinking?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** JSON-schema type implied by a literal value. */
|
|
46
|
+
function jsonTypeOf(v: unknown): string {
|
|
47
|
+
if (typeof v === "number") return Number.isInteger(v) ? "integer" : "number";
|
|
48
|
+
if (typeof v === "boolean") return "boolean";
|
|
49
|
+
if (Array.isArray(v)) return "array";
|
|
50
|
+
if (v !== null && typeof v === "object") return "object";
|
|
51
|
+
return "string";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Infer a JSON-schema `type` for a node that lacks one (enum/const/anyOf/…). */
|
|
55
|
+
function inferSchemaType(node: Record<string, unknown>): string {
|
|
56
|
+
if (Array.isArray(node.enum) && node.enum.length > 0) return jsonTypeOf(node.enum[0]);
|
|
57
|
+
if ("const" in node) return jsonTypeOf(node.const);
|
|
58
|
+
if (node.properties || node.additionalProperties) return "object";
|
|
59
|
+
if (node.items !== undefined || node.prefixItems !== undefined) return "array";
|
|
60
|
+
for (const key of ["anyOf", "oneOf", "allOf"] as const) {
|
|
61
|
+
const subs = node[key];
|
|
62
|
+
if (Array.isArray(subs) && subs.length > 0) {
|
|
63
|
+
const types = subs
|
|
64
|
+
.map((s) => (s && typeof s === "object" ? (s as Record<string, unknown>).type : undefined))
|
|
65
|
+
.filter((t): t is string => typeof t === "string");
|
|
66
|
+
const first = types[0];
|
|
67
|
+
if (first !== undefined) return first;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return "string";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Recursively ensure every JSON-schema node carries a `type`.
|
|
75
|
+
*
|
|
76
|
+
* Why: HF chat templates (e.g. Gemma's tool-declaration block) do
|
|
77
|
+
* `value['type'] | upper`, which throws "Cannot apply filter upper to
|
|
78
|
+
* UndefinedValue" for schemas that describe a parameter via `anyOf`/`enum`/
|
|
79
|
+
* `const` without a top-level `type` (TypeBox unions/literals emit exactly
|
|
80
|
+
* this). We synthesize a sensible `type` so any tool renders, regardless of
|
|
81
|
+
* how its schema was authored. Returns a new object; never mutates input.
|
|
82
|
+
*/
|
|
83
|
+
export function normalizeSchemaTypes(node: unknown): unknown {
|
|
84
|
+
if (Array.isArray(node)) return node.map(normalizeSchemaTypes);
|
|
85
|
+
if (!node || typeof node !== "object") return node;
|
|
86
|
+
const out: Record<string, unknown> = { ...(node as Record<string, unknown>) };
|
|
87
|
+
if (out.properties && typeof out.properties === "object") {
|
|
88
|
+
const props: Record<string, unknown> = {};
|
|
89
|
+
for (const [k, v] of Object.entries(out.properties as Record<string, unknown>)) props[k] = normalizeSchemaTypes(v);
|
|
90
|
+
out.properties = props;
|
|
91
|
+
}
|
|
92
|
+
if (out.items !== undefined) out.items = normalizeSchemaTypes(out.items);
|
|
93
|
+
if (out.prefixItems !== undefined) out.prefixItems = normalizeSchemaTypes(out.prefixItems);
|
|
94
|
+
if (out.additionalProperties && typeof out.additionalProperties === "object") {
|
|
95
|
+
out.additionalProperties = normalizeSchemaTypes(out.additionalProperties);
|
|
96
|
+
}
|
|
97
|
+
for (const key of ["anyOf", "oneOf", "allOf"] as const) {
|
|
98
|
+
if (Array.isArray(out[key])) out[key] = (out[key] as unknown[]).map(normalizeSchemaTypes);
|
|
99
|
+
}
|
|
100
|
+
if (typeof out.type !== "string") out.type = inferSchemaType(out);
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Apply normalizeSchemaTypes to every tool's parameter schema. */
|
|
105
|
+
export function normalizeToolSchemas(tools: ToolDefinition[] | null): ToolDefinition[] | null {
|
|
106
|
+
if (!tools) return tools;
|
|
107
|
+
return tools.map((t) => ({
|
|
108
|
+
...t,
|
|
109
|
+
function: {
|
|
110
|
+
...t.function,
|
|
111
|
+
parameters: t.function.parameters
|
|
112
|
+
? (normalizeSchemaTypes(t.function.parameters) as Record<string, unknown>)
|
|
113
|
+
: t.function.parameters,
|
|
114
|
+
},
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export class ChatTemplate {
|
|
119
|
+
readonly #template: Template;
|
|
120
|
+
readonly #bosToken: string | null;
|
|
121
|
+
readonly #eosToken: string | null;
|
|
122
|
+
/** Which reasoning format the template's `enable_thinking` channel uses, or
|
|
123
|
+
* null if the model has no switchable reasoning:
|
|
124
|
+
* - "think-tag": `<think>…</think>` text markers (Qwen3.5, MiniCPM5) — split
|
|
125
|
+
* from decoded text by ThinkingTagSplitter.
|
|
126
|
+
* - "gemma-channel": `<|channel>thought\n…<channel|>` (Gemma 4) — the markers
|
|
127
|
+
* are SPECIAL TOKENS stripped at decode, so reasoning is split at the token
|
|
128
|
+
* level in ToolAwareStream (gemma-sentinel mode), not from decoded text.
|
|
129
|
+
* Drives both the parser path and the reasoning capability advertised to Pi. */
|
|
130
|
+
readonly thinkingFormat: "think-tag" | "gemma-channel" | null;
|
|
131
|
+
/** True when the model has a switchable reasoning channel we can parse. */
|
|
132
|
+
readonly supportsThinking: boolean;
|
|
133
|
+
|
|
134
|
+
private constructor(source: string, bosToken: string | null, eosToken: string | null) {
|
|
135
|
+
this.#template = new Template(source);
|
|
136
|
+
this.#bosToken = bosToken;
|
|
137
|
+
this.#eosToken = eosToken;
|
|
138
|
+
const gatesThinking = source.includes("enable_thinking");
|
|
139
|
+
this.thinkingFormat = gatesThinking && source.includes("<think>")
|
|
140
|
+
? "think-tag"
|
|
141
|
+
: gatesThinking && source.includes("<|channel>")
|
|
142
|
+
? "gemma-channel"
|
|
143
|
+
: null;
|
|
144
|
+
this.supportsThinking = this.thinkingFormat !== null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static async load(modelDir: string): Promise<ChatTemplate> {
|
|
148
|
+
const config = (await Bun.file(`${modelDir}/tokenizer_config.json`).json()) as Record<string, any>;
|
|
149
|
+
let source: string | undefined = config.chat_template;
|
|
150
|
+
if (!source) {
|
|
151
|
+
const jinjaFile = Bun.file(`${modelDir}/chat_template.jinja`);
|
|
152
|
+
if (await jinjaFile.exists()) source = await jinjaFile.text();
|
|
153
|
+
}
|
|
154
|
+
if (!source) throw new Error(`${modelDir}: no chat template found`);
|
|
155
|
+
// @huggingface/jinja lacks the `min`/`max` array filters that real
|
|
156
|
+
// Jinja2 has. MiniCPM5's template uses `[a, b]|min` in its assistant
|
|
157
|
+
// tool-call history branch, so without this rewrite every multi-turn
|
|
158
|
+
// tool conversation fails at render time ("Unknown ArrayValue filter").
|
|
159
|
+
source = source
|
|
160
|
+
.replace(
|
|
161
|
+
/\[\s*([\w.]+)\s*,\s*([\w.]+)\s*\]\s*\|\s*min\b/g,
|
|
162
|
+
"($1 if $1 < $2 else $2)",
|
|
163
|
+
)
|
|
164
|
+
.replace(
|
|
165
|
+
/\[\s*([\w.]+)\s*,\s*([\w.]+)\s*\]\s*\|\s*max\b/g,
|
|
166
|
+
"($1 if $1 > $2 else $2)",
|
|
167
|
+
);
|
|
168
|
+
const tokenText = (t: unknown): string | null =>
|
|
169
|
+
t == null ? null : typeof t === "string" ? t : (t as any).content;
|
|
170
|
+
return new ChatTemplate(source, tokenText(config.bos_token), tokenText(config.eos_token));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
render(messages: ChatMessage[], options: RenderOptions = {}): string {
|
|
174
|
+
const { addGenerationPrompt = true, tools = null, enableThinking } = options;
|
|
175
|
+
return this.#template.render({
|
|
176
|
+
messages,
|
|
177
|
+
add_generation_prompt: addGenerationPrompt,
|
|
178
|
+
// Guarantee every tool param schema has a `type` so templates that do
|
|
179
|
+
// `value['type'] | upper` (Gemma) never see UndefinedValue.
|
|
180
|
+
tools: normalizeToolSchemas(tools),
|
|
181
|
+
...(enableThinking !== undefined ? { enable_thinking: enableThinking } : {}),
|
|
182
|
+
bos_token: this.#bosToken,
|
|
183
|
+
eos_token: this.#eosToken,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|