@tryhamster/gerbil 1.0.0-rc.8 → 1.0.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/LICENSE +1 -1
- package/README.md +247 -84
- package/dist/architectures-C1I5V3Dt.mjs +6070 -0
- package/dist/architectures-C1I5V3Dt.mjs.map +1 -0
- package/dist/browser/index.d.ts +264 -588
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +585 -2334
- package/dist/browser/index.js.map +1 -1
- package/dist/cli.mjs +625 -1098
- package/dist/cli.mjs.map +1 -1
- package/dist/defaults-9komdrbY.mjs +24 -0
- package/dist/defaults-9komdrbY.mjs.map +1 -0
- package/dist/frameworks/express.d.mts +1 -3
- package/dist/frameworks/express.d.mts.map +1 -1
- package/dist/frameworks/express.mjs +7 -7
- package/dist/frameworks/express.mjs.map +1 -1
- package/dist/frameworks/fastify.d.mts +1 -1
- package/dist/frameworks/fastify.d.mts.map +1 -1
- package/dist/frameworks/fastify.mjs +3 -3
- package/dist/frameworks/fastify.mjs.map +1 -1
- package/dist/frameworks/hono.d.mts +1 -1
- package/dist/frameworks/hono.d.mts.map +1 -1
- package/dist/frameworks/hono.mjs +4 -4
- package/dist/frameworks/hono.mjs.map +1 -1
- package/dist/frameworks/next.d.mts +3 -2
- package/dist/frameworks/next.d.mts.map +1 -1
- package/dist/frameworks/next.mjs +4 -4
- package/dist/frameworks/next.mjs.map +1 -1
- package/dist/frameworks/react.d.mts +1 -1
- package/dist/frameworks/trpc.d.mts +1 -1
- package/dist/frameworks/trpc.d.mts.map +1 -1
- package/dist/frameworks/trpc.mjs +4 -4
- package/dist/frameworks/trpc.mjs.map +1 -1
- package/dist/gerbil-BHrJJIa4.mjs +1656 -0
- package/dist/gerbil-BHrJJIa4.mjs.map +1 -0
- package/dist/gerbil-BT9fCydo.d.mts +488 -0
- package/dist/gerbil-BT9fCydo.d.mts.map +1 -0
- package/dist/gerbil-DomNfIr1.mjs +4 -0
- package/dist/gpu/hooks.d.mts +520 -0
- package/dist/gpu/hooks.d.mts.map +1 -0
- package/dist/gpu/hooks.mjs +1188 -0
- package/dist/gpu/hooks.mjs.map +1 -0
- package/dist/gpu/index.d.mts +2 -0
- package/dist/gpu/index.mjs +6 -0
- package/dist/gpu-33qCAtHW.mjs +3615 -0
- package/dist/gpu-33qCAtHW.mjs.map +1 -0
- package/dist/index-Dgmb2kE3.d.mts +245 -0
- package/dist/index-Dgmb2kE3.d.mts.map +1 -0
- package/dist/index-jEAL2s-A.d.mts +2022 -0
- package/dist/index-jEAL2s-A.d.mts.map +1 -0
- package/dist/index.d.mts +22 -487
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +13 -8
- package/dist/index.mjs.map +1 -1
- package/dist/indexeddb-store-BWIMtxxH.mjs +103 -0
- package/dist/indexeddb-store-BWIMtxxH.mjs.map +1 -0
- package/dist/indexeddb-store-ClH12Xnl.mjs +4 -0
- package/dist/integrations/ai-sdk.d.mts +75 -6
- package/dist/integrations/ai-sdk.d.mts.map +1 -1
- package/dist/integrations/ai-sdk.mjs +131 -15
- package/dist/integrations/ai-sdk.mjs.map +1 -1
- package/dist/integrations/langchain.d.mts +1 -1
- package/dist/integrations/langchain.d.mts.map +1 -1
- package/dist/integrations/langchain.mjs +5 -5
- package/dist/integrations/langchain.mjs.map +1 -1
- package/dist/integrations/llamaindex.d.mts +1 -1
- package/dist/integrations/llamaindex.d.mts.map +1 -1
- package/dist/integrations/llamaindex.mjs +5 -5
- package/dist/integrations/llamaindex.mjs.map +1 -1
- package/dist/integrations/mcp-client.mjs +3 -3
- package/dist/integrations/mcp-client.mjs.map +1 -1
- package/dist/integrations/mcp.d.mts +3 -2
- package/dist/integrations/mcp.d.mts.map +1 -1
- package/dist/integrations/mcp.mjs +5 -5
- package/dist/{mcp-BvbriaBy.mjs → mcp-1DaMsaBc.mjs} +4 -4
- package/dist/mcp-1DaMsaBc.mjs.map +1 -0
- package/dist/memory/index.d.mts +3 -0
- package/dist/memory/index.mjs +6 -0
- package/dist/memory-D1P7Tmda.mjs +4 -0
- package/dist/memory-DVN0MnIG.mjs +132 -0
- package/dist/memory-DVN0MnIG.mjs.map +1 -0
- package/dist/memory-Dj0J1v88.mjs +294 -0
- package/dist/memory-Dj0J1v88.mjs.map +1 -0
- package/dist/moonshine-stt-BLyVoRpB.mjs +4 -0
- package/dist/moonshine-stt-v_P_Ci_m.mjs +11936 -0
- package/dist/moonshine-stt-v_P_Ci_m.mjs.map +1 -0
- package/dist/{one-liner-s-lD8rCC.mjs → one-liner-DnQn7HJK.mjs} +14 -16
- package/dist/one-liner-DnQn7HJK.mjs.map +1 -0
- package/dist/repl-jV5gcJFA.mjs +9 -0
- package/dist/skills/index.d.mts +270 -320
- package/dist/skills/index.d.mts.map +1 -1
- package/dist/skills/index.mjs +5 -5
- package/dist/{skills-CD3Orlex.mjs → skills-DX8D59UH.mjs} +187 -32
- package/dist/skills-DX8D59UH.mjs.map +1 -0
- package/dist/{tools-Bi1P7Xoy.mjs → tools-DQ1mPUw5.mjs} +34 -22
- package/dist/tools-DQ1mPUw5.mjs.map +1 -0
- package/dist/{types-CiTc7ez3.d.mts → types-D6FiR_oh.d.mts} +106 -12
- package/dist/types-D6FiR_oh.d.mts.map +1 -0
- package/dist/types-DQBe2lFo.d.mts +165 -0
- package/dist/types-DQBe2lFo.d.mts.map +1 -0
- package/dist/{utils-CZBZ8dgR.mjs → utils-DKO55ZmZ.mjs} +1 -1
- package/dist/{utils-CZBZ8dgR.mjs.map → utils-DKO55ZmZ.mjs.map} +1 -1
- package/dist/vector-B0panuy6.mjs +95 -0
- package/dist/vector-B0panuy6.mjs.map +1 -0
- package/docs/PROJECT-STATE.md +321 -0
- package/docs/adding-a-model-family.md +280 -0
- package/docs/ai-sdk.md +70 -61
- package/docs/architecture/overview.md +17 -7
- package/docs/browser.md +203 -8
- package/docs/embeddings.md +156 -0
- package/docs/gerbil-site-native-migration.md +217 -0
- package/docs/gpu-engine/architectures.md +398 -0
- package/docs/gpu-engine/ir.md +372 -0
- package/docs/gpu-engine/kernels.md +718 -0
- package/docs/gpu-engine/paper.html +1759 -0
- package/docs/gpu-engine/paper.md +2109 -0
- package/docs/gpu-engine/safetensors.md +312 -0
- package/docs/gpu-engine/tokenizer.md +302 -0
- package/docs/memory-rag.md +91 -0
- package/docs/metal-safari-intel.md +190 -0
- package/docs/mobile-failure-diagnosis.md +124 -0
- package/docs/mobile.md +99 -0
- package/docs/observability.md +230 -0
- package/docs/onnx-removal-plan.md +339 -0
- package/docs/research/autoresearch-portable.md +904 -0
- package/docs/research/dispatch-reduction-hivemind.md +84 -0
- package/docs/research/ios-safari-model-caching.md +117 -0
- package/docs/research/mobile-webgpu-speed-fusion.md +135 -0
- package/docs/research/native-stt-model-selection.md +49 -0
- package/docs/research/native-tts-model-selection.md +90 -0
- package/docs/research/native-vs-chromium-decision.md +152 -0
- package/docs/research/nemotron-mamba2-inference.md +910 -0
- package/docs/research/qwen35-multimodal.md +293 -0
- package/docs/research/qwen36-gemma4-targets.md +337 -0
- package/docs/research/sota-embedding-models.md +179 -0
- package/docs/research/sota-mobile-models-2026.md +263 -0
- package/docs/research/sota-modality-models.md +202 -0
- package/docs/research/tps-baselines.md +71 -0
- package/docs/research/webgpu-m4-reference.md +104 -0
- package/docs/site-update-plan.md +155 -0
- package/docs/structured-output.md +123 -0
- package/docs/stt.md +63 -446
- package/docs/tts.md +77 -499
- package/docs/vision.md +100 -338
- package/package.json +22 -7
- package/dist/chrome-backend-CORwaIyC.mjs +0 -1212
- package/dist/chrome-backend-CORwaIyC.mjs.map +0 -1
- package/dist/chrome-backend-DIKYoWj-.mjs +0 -3
- package/dist/gerbil-CJ3ifloF.mjs +0 -4
- package/dist/gerbil-Dw4Qj77e.mjs +0 -1631
- package/dist/gerbil-Dw4Qj77e.mjs.map +0 -1
- package/dist/gerbil-qOTe1nl2.d.mts +0 -431
- package/dist/gerbil-qOTe1nl2.d.mts.map +0 -1
- package/dist/kokoro-BNTb6egA.mjs +0 -20210
- package/dist/kokoro-BNTb6egA.mjs.map +0 -1
- package/dist/kokoro-DFRQ1OeM.js +0 -20212
- package/dist/kokoro-DFRQ1OeM.js.map +0 -1
- package/dist/mcp-BvbriaBy.mjs.map +0 -1
- package/dist/one-liner-s-lD8rCC.mjs.map +0 -1
- package/dist/repl-DveXw36T.mjs +0 -9
- package/dist/skills-CD3Orlex.mjs.map +0 -1
- package/dist/stt-CpLYbGFd.mjs +0 -433
- package/dist/stt-CpLYbGFd.mjs.map +0 -1
- package/dist/stt-DRPLEEHB.mjs +0 -3
- package/dist/stt-Te8Qz-Ay.js +0 -433
- package/dist/stt-Te8Qz-Ay.js.map +0 -1
- package/dist/tools-Bi1P7Xoy.mjs.map +0 -1
- package/dist/transformers.web-DokyH3rP.js +0 -3
- package/dist/transformers.web-M6mCnEYJ.js +0 -30382
- package/dist/transformers.web-M6mCnEYJ.js.map +0 -1
- package/dist/tts-C0xx3CtE.js +0 -724
- package/dist/tts-C0xx3CtE.js.map +0 -1
- package/dist/tts-DXgsKGCe.mjs +0 -3
- package/dist/tts-DeGANMNV.mjs +0 -730
- package/dist/tts-DeGANMNV.mjs.map +0 -1
- package/dist/types-CiTc7ez3.d.mts.map +0 -1
- /package/dist/{auto-update-S9s5-g0C.mjs → auto-update-BVaLXcDE.mjs} +0 -0
- /package/dist/{chunk-CkXuGtQK.mjs → chunk-B9cbKln6.mjs} +0 -0
- /package/dist/{microphone-DaMZFRuR.mjs → microphone-Bqmoz9_K.mjs} +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# SOTA Small On-Device Models per Modality — Gerbil Native-Build Research (June 2026)
|
|
2
|
+
|
|
3
|
+
Research date: **2026-06-13**. Engine baseline: Gerbil from-scratch WebGPU INT4 engine.
|
|
4
|
+
Companion to `sota-mobile-models-2026.md` (which covers text LLMs). This doc covers the
|
|
5
|
+
**multimodal modalities** the engine wants to support natively: TTS, STT, text embeddings, vision.
|
|
6
|
+
|
|
7
|
+
**Method.** Facts below are verified against **live HuggingFace** wherever possible — `config.json`,
|
|
8
|
+
the model file list (which reveals pipeline structure for ONNX TTS), and safetensors/blob sizes are
|
|
9
|
+
ground truth. Each claim is tagged **[config]** (live HF config/file list), **[card/docs]** (official
|
|
10
|
+
card or vendor doc), or **[web]** (Perplexity/secondary, softer). Knowledge-cutoff guesses were
|
|
11
|
+
avoided; every repo below was hit live.
|
|
12
|
+
|
|
13
|
+
## Gerbil op inventory (what "native-build tier" is measured against)
|
|
14
|
+
|
|
15
|
+
Verified from `src/gpu/ir.ts` + `src/gpu/kernels/wgsl/`:
|
|
16
|
+
|
|
17
|
+
- **Have (real kernels):** `matmul`, `matmul_int4`, flash `attention`, `causal_conv1d` +
|
|
18
|
+
`ConvStateUpdate`, `linear_attention` (Gated DeltaNet / Mamba-2 scan `MambaSSM`), `rmsnorm`,
|
|
19
|
+
`layernorm`, `rope` (incl. partial-rotary capable), `silu`, `swiglu`, `gelu`, `sigmoid_gate`,
|
|
20
|
+
`softmax`, `embedding`, `add`, `mul`.
|
|
21
|
+
- **Stubbed (declared in IR, no kernel):** `Conv2d`, `AvgPool2d`, `CrossAttention`.
|
|
22
|
+
|
|
23
|
+
Tier convention (from the `add-model-family` skill, same as the text-LLM doc):
|
|
24
|
+
**Tier 1** = hours, reuse all ops (loader/config work only). **Tier 2** = days, 1–2 novel kernels.
|
|
25
|
+
**Tier 3** = weeks, a new computation class (e.g. ONNX-graph interpreter, flow-matching sampler).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## TL;DR — the one to build first per modality
|
|
30
|
+
|
|
31
|
+
| Modality | Build first | Why | Tier |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| **Embeddings** | **Qwen3-Embedding-0.6B** | Arch is literally `Qwen3ForCausalLM` — **zero new kernels**, reuses the engine's existing Qwen3 path. Ship in hours. | **Tier 1** |
|
|
34
|
+
| **STT** | **Moonshine-base** (then -tiny) | Smallest real encoder-decoder transformer; raw-waveform Conv1d frontend reuses `causal_conv1d`; only a non-causal conv + cross-attention to add. | **Tier 2** |
|
|
35
|
+
| **TTS** | **Kokoro-82M** (keep) as floor; **port none natively yet** | Every *better* small TTS (Kitten, Supertonic) ships **ONNX-graph-only** — no safetensors tensors to map to our IR. Native TTS is a Tier-3 lift. Recommend ONNX-runtime-web bridge short-term. | **Tier 3** |
|
|
36
|
+
| **Vision** | **Skip standalone** if Qwen3.5-VL lands | A standalone VLM (SmolVLM2-256M) needs Conv2d + CrossAttention (Perceiver) + a separate SigLIP encoder — three stubs to fill. Not worth it if Qwen3.5-VL covers vision natively. | **Tier 2–3** |
|
|
37
|
+
|
|
38
|
+
**Single highest-ROI build: Qwen3-Embedding-0.6B.** It is the only cross-modality pick that is
|
|
39
|
+
genuinely free on our engine.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 1. Text Embeddings — clearest win
|
|
44
|
+
|
|
45
|
+
### #1 (BUILD FIRST) — Qwen3-Embedding-0.6B — **Tier 1 (hours)**
|
|
46
|
+
- **Repo:** `Qwen/Qwen3-Embedding-0.6B`
|
|
47
|
+
- **Params:** 0.6B. **4-bit download:** ~0.4–0.45 GB (Q4 weights; Ollama packages ~0.64 GB w/ overhead). **[web]**
|
|
48
|
+
- **Arch [config, verified live]:** `architectures: ["Qwen3ForCausalLM"]`, `model_type: qwen3`,
|
|
49
|
+
28 layers, hidden 1024, GQA 16 heads / 8 KV, head_dim 128, SiLU MLP, RoPE θ=1e6, RMSNorm,
|
|
50
|
+
tied embeddings, vocab 151669. **Decoder-only / causal**; embedding via **last-token pooling**
|
|
51
|
+
with an instruction prefix. MTEB multilingual ~64.3. **[config + web]**
|
|
52
|
+
- **Why Tier 1:** this is the *same architecture family Gerbil already runs* (Qwen3 dense). The only
|
|
53
|
+
delta vs text-gen: stop after the final hidden state, take the last token's vector, L2-normalize —
|
|
54
|
+
no logits/sampling. **New kernels: none.** A pooling+normalize tail and an "embeddings mode" flag.
|
|
55
|
+
|
|
56
|
+
### #2 — EmbeddingGemma-300M — **Tier 2 (days; bidirectional attention is the novelty)**
|
|
57
|
+
- **Repo:** `google/embeddinggemma-300m` (**gated** — login required to fetch weights). **[config: gated]**
|
|
58
|
+
- **Params:** 300M. **4-bit:** ~0.3–0.4 GB.
|
|
59
|
+
- **Arch [card/web]:** `model_type: gemma3_text`, `sentence-transformers`, `pipeline: sentence-similarity`.
|
|
60
|
+
Encoder converted from Gemma 3 via the **T5Gemma** recipe → **bidirectional (non-causal) encoder**,
|
|
61
|
+
**mean pooling**, output dim 768 with **Matryoshka** 512/256/128 truncation. Best open model <500M on MTEB.
|
|
62
|
+
- **Why Tier 2 not 1:** our `attention.wgsl` is a *causal* flash kernel. A bidirectional encoder needs
|
|
63
|
+
a **full (non-causal) attention mask** variant — a small kernel branch, plus mean-pool tail. Gating
|
|
64
|
+
also complicates distribution. Strong model, but Qwen3-Embedding is the free win.
|
|
65
|
+
|
|
66
|
+
### #3 — legacy tiny BERT-encoders (BGE-small / GTE-small / Nomic) — **Tier 2**
|
|
67
|
+
- `BAAI/bge-small-en-v1.5` (~33M, dim 384, CLS pool), `thenlper/gte-small` (~33M, mean pool),
|
|
68
|
+
`nomic-ai/nomic-embed-text-v1.5` (~137M, dim 768, mean pool, MTEB ~62.3). **[web]**
|
|
69
|
+
- All **bidirectional BERT encoders** → need the same non-causal attention + LayerNorm (have it) +
|
|
70
|
+
pooling. 4-bit sizes are tiny (30–280 MB). Good fallbacks if a sub-50M footprint matters, but lower
|
|
71
|
+
quality than Qwen3-Embedding / EmbeddingGemma and still Tier 2 (bidirectional mask).
|
|
72
|
+
|
|
73
|
+
**Ranking:** Qwen3-Embedding-0.6B (build first, Tier 1) → EmbeddingGemma-300M (best quality/size if
|
|
74
|
+
you add bidirectional attention + accept gating) → BGE/GTE/Nomic (ultralight Tier-2 fallbacks).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 2. STT (Speech-to-Text) — Moonshine is the native-friendliest
|
|
79
|
+
|
|
80
|
+
### #1 (BUILD FIRST) — Moonshine (base → tiny) — **Tier 2 (days)**
|
|
81
|
+
- **Repos:** `UsefulSensors/moonshine-base`, `UsefulSensors/moonshine-tiny`
|
|
82
|
+
- **Params:** base ~60M, tiny ~27M. **4-bit:** base ~60–90 MB, tiny ~30 MB.
|
|
83
|
+
- **Arch [config, verified live]:** `MoonshineForConditionalGeneration`, encoder-decoder transformer,
|
|
84
|
+
hidden 416, 8 encoder + 8 decoder layers, **partial RoPE (factor 0.62)**, encoder GELU / decoder SiLU,
|
|
85
|
+
vocab 32768. **Frontend is raw 16 kHz waveform** (`Wav2Vec2FeatureExtractor`, `feature_size: 1`,
|
|
86
|
+
`do_normalize: false`) — **no mel spectrogram**: a stack of strided **Conv1d** layers subsamples the
|
|
87
|
+
raw audio. **[config]**
|
|
88
|
+
- **Why Moonshine over Whisper:** Whisper needs a **2-conv log-mel frontend** (mel filterbank +
|
|
89
|
+
Conv2d-ish), absolute sinusoidal positions, and fixed 30 s padded windows. Moonshine has **no mel
|
|
90
|
+
step**, variable-length input, and **RoPE** — which we already have. Its conv subsampling maps onto
|
|
91
|
+
our existing **`causal_conv1d`** primitive (made non-causal/strided). It's the best architectural fit.
|
|
92
|
+
- **New kernels:** (1) a **strided non-causal Conv1d** variant of `causal_conv1d` for the encoder
|
|
93
|
+
frontend; (2) **encoder-decoder CrossAttention** (currently stubbed) — the decoder attends to encoder
|
|
94
|
+
states. RMSNorm/RoPE/SiLU/softmax/matmul_int4 all reused. Partial-rotary is already supported.
|
|
95
|
+
|
|
96
|
+
### #2 — Whisper tiny/base — **Tier 2–3 (more frontend work)**
|
|
97
|
+
- `openai/whisper-tiny` (~39M), `openai/whisper-base` (~74M), `openai/whisper-small` (~244M).
|
|
98
|
+
Encoder-decoder transformer, **log-mel + 2× Conv** frontend, sinusoidal positions, cross-attention.
|
|
99
|
+
4-bit: tiny ~40 MB, base ~75 MB, small ~250 MB. **[web]**
|
|
100
|
+
- **Why lower:** the **mel-spectrogram + Conv2d frontend** and absolute positional embeddings are extra
|
|
101
|
+
computation classes vs Moonshine. Distil-Whisper variants (`distil-whisper/*`) shrink the decoder but
|
|
102
|
+
keep the same frontend. Pick Whisper only if you need its broader multilingual robustness; otherwise
|
|
103
|
+
Moonshine is leaner to build and run.
|
|
104
|
+
|
|
105
|
+
### Not recommended for native (Tier 3): NVIDIA NeMo Canary / Parakeet
|
|
106
|
+
- FastConformer encoders = **heavy depthwise-separable Conv2d + relative-position attention + CTC/RNN-T
|
|
107
|
+
transducer decoder**. Multiple new computation classes (transducer beam search, conv-heavy frontend).
|
|
108
|
+
High accuracy but the worst native-build fit of the STT options. **[web]**
|
|
109
|
+
|
|
110
|
+
**Ranking:** Moonshine-base (build first) → Moonshine-tiny (smallest) → Whisper tiny/base (if
|
|
111
|
+
multilingual robustness needed) → NeMo (skip for native).
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 3. TTS (Text-to-Speech) — better-than-Kokoro models are ONNX-locked
|
|
116
|
+
|
|
117
|
+
The owner is right that **Kokoro-82M is last-gen**. The catch for *native* WebGPU: every credible
|
|
118
|
+
2026 upgrade ships as a **frozen ONNX graph**, not safetensors weight tensors — so there is nothing
|
|
119
|
+
to map onto Gerbil's IR without first writing an ONNX-graph importer. This makes native TTS the
|
|
120
|
+
single hardest modality on our engine.
|
|
121
|
+
|
|
122
|
+
### Landscape (verified live on HF)
|
|
123
|
+
|
|
124
|
+
| Model | Repo | Size / format | Architecture |
|
|
125
|
+
|---|---|---|---|
|
|
126
|
+
| **Supertonic-3** | `Supertone/supertonic-3` | **ONNX only**, ~400 MB total: `text_encoder` 36 MB + `duration_predictor` 3.7 MB + `vector_estimator` **256 MB** + `vocoder` 101 MB | **Flow-matching / StyleTTS2-style pipeline** (NOT a transformer LM): text enc → duration predictor → flow-matching acoustic ("vector_estimator") → neural vocoder. 39 langs, on-device, 822 likes (trending, May 2026). **[config]** |
|
|
127
|
+
| **Kitten TTS** | `KittenML/kitten-tts-nano-0.2`, `…nano-0.8-fp32`, `…mini-0.1` | **ONNX only** + `voices.npz`; nano ~25 MB, mini larger | Tiny (15–80M) non-autoregressive duration-predictor + lightweight vocoder; CPU-first. Beats Kokoro on **latency/size**, ~par on quality. **[config + web]** |
|
|
128
|
+
| **Kokoro-82M** | `hexgrad/Kokoro-82M` | safetensors available; ~80 MB | StyleTTS2-derived: text enc + duration/pitch predictor + **iSTFT/HiFiGAN-style vocoder**. Last-gen but **the only one with real weight tensors**. **[web]** |
|
|
129
|
+
| **Supertonic-2 / OuteTTS** | `Supertone/supertonic-2`, OuteTTS repos | ONNX (Supertonic) / LM-codec (OuteTTS) | OuteTTS = neural-codec LM (transformer that emits audio codec tokens + needs a codec decoder). Bigger, heavier. **[web]** |
|
|
130
|
+
|
|
131
|
+
### Architecture reality vs Gerbil ops
|
|
132
|
+
A StyleTTS2/Supertonic pipeline is **not a transformer LM**. It is: a small text/phoneme encoder
|
|
133
|
+
(matmul + attention — fine), a **duration predictor** (Conv1d + small regressor), an acoustic model
|
|
134
|
+
that is either **flow-matching/diffusion** (iterative sampler — a new computation class) or a mel
|
|
135
|
+
decoder, and a **GAN/iSTFT vocoder** (transposed Conv1d + iSTFT — new kernels). None of the
|
|
136
|
+
better-than-Kokoro models expose these as mappable safetensors; they're sealed ONNX subgraphs.
|
|
137
|
+
|
|
138
|
+
### Recommendation
|
|
139
|
+
1. **Short term:** keep **Kokoro-82M** as the quality floor, and ship newer/better TTS
|
|
140
|
+
(**Supertonic-3**, **Kitten**) via an **`onnxruntime-web` (WebGPU EP) bridge** rather than the
|
|
141
|
+
native engine. This gets "better than Kokoro" shipping now with zero kernel work.
|
|
142
|
+
2. **If/when native TTS is mandated (Tier 3):** the most tractable native target is **Kokoro-82M
|
|
143
|
+
itself** (real safetensors), because porting it forces exactly the reusable primitives a native TTS
|
|
144
|
+
stack needs — **transposed/strided Conv1d, iSTFT, and an upsampling vocoder kernel** — which then
|
|
145
|
+
also unblock a future native Supertonic-class pipeline. Do NOT start with an ONNX-only model.
|
|
146
|
+
|
|
147
|
+
**Ranking (native-build effort, ascending):** Kokoro-82M (only real-weights option; Tier 3) →
|
|
148
|
+
everything else requires an ONNX importer first. **Best quality available now: Supertonic-3 via ONNX
|
|
149
|
+
bridge.** Best size/latency: Kitten via ONNX bridge.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 4. Vision — likely NOT needed standalone
|
|
154
|
+
|
|
155
|
+
**Flag: if Qwen3.5-VL covers vision natively (separate investigation), a standalone vision model is
|
|
156
|
+
not worth building.** Reasons: a standalone small VLM still drags in the exact ops we've stubbed
|
|
157
|
+
(Conv2d, CrossAttention) plus a *second* model (a SigLIP encoder) and its own resampler — strictly
|
|
158
|
+
more native-build surface than letting the text engine's existing transformer stack absorb vision
|
|
159
|
+
tokens from a Qwen3.5-VL projector.
|
|
160
|
+
|
|
161
|
+
### If a standalone is required — smallest good option
|
|
162
|
+
|
|
163
|
+
**SmolVLM2-256M-Video-Instruct — Tier 2–3**
|
|
164
|
+
- **Repo:** `HuggingFaceTB/SmolVLM2-256M-Video-Instruct` (also 500M variant).
|
|
165
|
+
- **Params:** 256M. **4-bit:** ~0.15–0.20 GB. **[config + web]**
|
|
166
|
+
- **Arch [config, verified live]:** `SmolVLMForConditionalGeneration`. Text backbone = **Llama**
|
|
167
|
+
(`VLlama3ForCausalLM`, hidden 576, 30 layers, GQA 9/3 — Tier 1 on our engine). Vision = **SigLIP ViT**
|
|
168
|
+
with **Conv2d patch embedding**. A **Perceiver resampler** (`perceiver_config`, `scale_factor: 4`)
|
|
169
|
+
compresses vision tokens via **cross-attention**. **[config]**
|
|
170
|
+
- **New kernels:** (1) **Conv2d** patch-embed (currently stubbed); (2) **CrossAttention** for the
|
|
171
|
+
Perceiver resampler (stubbed); (3) the SigLIP encoder is a second sub-model to wire (its attention is
|
|
172
|
+
bidirectional). The Llama text half is free. So even the *smallest* standalone VLM lights up **two of
|
|
173
|
+
our three stubs** plus a whole extra encoder.
|
|
174
|
+
|
|
175
|
+
### Other standalone references (larger)
|
|
176
|
+
- `vikhyatk/moondream2` (~1.6B), Moondream3 (larger): compact ViT + decoder; ~0.8–1.0 GB 4-bit. **[web]**
|
|
177
|
+
- `Qwen/Qwen2.5-VL-3B-Instruct`: custom ViT + dynamic resolution, ~1.5–2 GB 4-bit; bigger but strong OCR. **[web]**
|
|
178
|
+
- **Separate encoders** (if you ever want CLIP-style only): SigLIP2 (general) or FastVLM's **FastViTHD**
|
|
179
|
+
(hybrid conv-transformer, Conv2d-heavy, latency-optimized). Both need Conv2d. **[web]**
|
|
180
|
+
|
|
181
|
+
**Recommendation:** **Do not build a standalone vision model** pending the Qwen3.5-VL native check. If
|
|
182
|
+
forced, SmolVLM2-256M is the smallest — but budget for **Conv2d + CrossAttention** kernels and a SigLIP
|
|
183
|
+
encoder. Those same two kernels are the long pole for any vision path, so build them once for
|
|
184
|
+
Qwen3.5-VL rather than twice.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Cross-modality build order (recommendation)
|
|
189
|
+
|
|
190
|
+
1. **Qwen3-Embedding-0.6B** — Tier 1, hours, zero kernels. Ship embeddings immediately on the existing
|
|
191
|
+
Qwen3 path (add last-token pooling + normalize). **Highest ROI by far.**
|
|
192
|
+
2. **Moonshine-base STT** — Tier 2, days. Add a strided non-causal Conv1d (from `causal_conv1d`) and
|
|
193
|
+
encoder-decoder CrossAttention. Unblocks STT and gives us the first real CrossAttention kernel.
|
|
194
|
+
3. **Vision: wait for Qwen3.5-VL.** The Conv2d + CrossAttention kernels needed for SmolVLM are the same
|
|
195
|
+
ones Qwen3.5-VL needs — build them once, in the text-engine path, not for a throwaway standalone.
|
|
196
|
+
4. **TTS: ONNX-bridge Supertonic-3/Kitten now**, native Kokoro later (Tier 3). Native TTS is the
|
|
197
|
+
biggest lift (flow-matching sampler + vocoder/iSTFT + transposed conv) and the worst fit today —
|
|
198
|
+
defer until a vocoder kernel family is justified.
|
|
199
|
+
|
|
200
|
+
**Net:** one Tier-1 build (embeddings) ships a real new modality this week; the STT build (Moonshine)
|
|
201
|
+
is the natural next step and yields the reusable CrossAttention kernel; vision and TTS are deliberately
|
|
202
|
+
deferred behind shared-kernel and ONNX-bridge decisions rather than built blindly.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# TPS Baselines & Goals
|
|
2
|
+
|
|
3
|
+
Established 2026-06-12, after the four-bug mobile fix campaign (see `docs/mobile-failure-diagnosis.md`).
|
|
4
|
+
Model: Qwen3.5-0.8B, MLX 4-bit (INT4), greedy decode. All outputs verified byte-identical across platforms.
|
|
5
|
+
|
|
6
|
+
## Baselines (current)
|
|
7
|
+
|
|
8
|
+
| Platform | Config | Decode tok/s | Notes |
|
|
9
|
+
|---|---|---|---|
|
|
10
|
+
| M4 Max, node-dawn | single encoder/pass | **207** (207.4/207.0/207.9 cooled) | after 2026-06-13 autoresearch session; warm peak 221, throttled floor ~128 |
|
|
11
|
+
| M4 Max, node-dawn (pre-optimization) | single encoder/pass | 145.0 | post detection-fix baseline this session started from |
|
|
12
|
+
| iPad (iPadOS 26.5, WebKit) | batch-all (1 CB) | **31.7** | historical zero-logits config — now correct |
|
|
13
|
+
| iPad, sustained 200 tok | batch-all | **51.7** | t15 2026-06-13: no throttling over 200 tokens; includes optimizer kernel wins via dist |
|
|
14
|
+
| iPad, submit floor | group=1, awaited | 6.4–7.7 | correctness floor for older WebKit |
|
|
15
|
+
|
|
16
|
+
**2026-06-13 update:** the 50+ iPad goal is MET (51.7 sustained). New mobile goal: **70+ tok/s**
|
|
17
|
+
(mobile prefill tuning — t13 showed prefill-heavy drops to 8.2 tok/s overall — plus continued
|
|
18
|
+
kernel wins). maxseq=1024 verified working on device (37.1 tok/s, no crash).
|
|
19
|
+
|
|
20
|
+
Group-size scaling on iPad (24-token gens): 1→6.4 · 8→19.7 · 32→24.6 · 64→28.8 · 128→29.7 · all→31.7.
|
|
21
|
+
Interpretation: round-trip-bound until ~32/CB, then dispatch-bound.
|
|
22
|
+
|
|
23
|
+
## Goals
|
|
24
|
+
|
|
25
|
+
| Platform | Goal | Path |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| Desktop (M4 Max) | **180+ tok/s** | autoresearch loop: kernel tuning (K_THREADS/N_TILE/workgroup), fused KV append (+24 dispatches), fused GEMV+residual (+48), backlog P1 items |
|
|
28
|
+
| iPad | **50+ tok/s** | single compute pass (vs pass-per-dispatch) on 26.5+, kernel opts shared with desktop, dispatch-count reduction (helps mobile 2-3x more than desktop) |
|
|
29
|
+
| Load time (iPad) | < 15 s warm | HTTP-cache-served shard, quantize-on-GPU |
|
|
30
|
+
|
|
31
|
+
## Engine consolidation gate (2026-06-13) — RESOLVED
|
|
32
|
+
|
|
33
|
+
Tested transformers.js 4.2.0 on the iPad (iOS 26.5, WebKit) against the **same
|
|
34
|
+
model** the native engine runs (Qwen3.5-0.8B, ONNX vs MLX-4bit), to decide
|
|
35
|
+
whether one engine could replace two.
|
|
36
|
+
|
|
37
|
+
| Engine / path | Result | tok/s |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **Native WGSL** (Qwen3.5-0.8B) | works | **~51** |
|
|
40
|
+
| transformers.js **WebGPU** (Qwen3.5-0.8B-ONNX q4) | works, coherent (handles the hybrid arch) | **6.9–11.6** |
|
|
41
|
+
| transformers.js **WASM** (q4) | **fails** — `GatherBlockQuantized` op missing from the WASM backend (op coverage, not memory) | — |
|
|
42
|
+
|
|
43
|
+
**Verdict:** transformers.js *does* run on mobile now (the original reason native
|
|
44
|
+
was built is gone), but it's **~4–7× slower than native on text**, its WASM
|
|
45
|
+
fallback can't run q4 models anywhere, and decode-heavy modalities (Whisper
|
|
46
|
+
decode, VLM text, diffusion) will inherit that ~5× slowdown on mobile. So the
|
|
47
|
+
decision is **two deliberate lanes, not one engine**:
|
|
48
|
+
|
|
49
|
+
- **Native = fast text lane** — the models we implement (Qwen, Gemma next), plus
|
|
50
|
+
embeddings (cheap to add). Mobile-proven, ~5× faster.
|
|
51
|
+
- **transformers.js = breadth lane** — STT/TTS/vision/image-gen + the ONNX zoo,
|
|
52
|
+
and the no-WebGPU WASM tier. **Open caveat:** decode-heavy modalities on mobile
|
|
53
|
+
are likely too slow via tfjs; measure per-modality before assuming, and build
|
|
54
|
+
native where a mobile modality both matters and is too slow on tfjs.
|
|
55
|
+
|
|
56
|
+
**Also found:** the model re-downloads (~160s) on *every* iOS load for both
|
|
57
|
+
engines — the Cache API isn't persisting on WebKit (likely eviction under
|
|
58
|
+
storage pressure). Needs a durable fix (OPFS/IndexedDB, or chunked cache).
|
|
59
|
+
|
|
60
|
+
## Production submit strategy (WebKit)
|
|
61
|
+
|
|
62
|
+
OS-dependent: iPadOS/iOS 26.5+ → batch-all (bug fixed upstream). Older 26.x → group=64 if a
|
|
63
|
+
startup coherence probe passes, else group=1 awaited. Probe: small batched dependent-chain
|
|
64
|
+
dispatch comparing batched vs per-dispatch results at engine init.
|
|
65
|
+
|
|
66
|
+
## Invariants any optimization must respect
|
|
67
|
+
|
|
68
|
+
- iPad `maxComputeWorkgroupStorageSize` = 16384 (attention smem is exactly at the limit)
|
|
69
|
+
- iPad default `maxBufferSize` = 256MB, `maxStorageBufferBindingSize` = 128MB (embedding ~127MB — no headroom for bigger vocabs without sharding)
|
|
70
|
+
- Activation buffers are liveness-pooled: fused kernels must never read+write the same pooled buffer in one dispatch
|
|
71
|
+
- Two-phase attention reduction barrier is a race fix, not a perf knob
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# WebGPU / WGSL / Apple M4 Max — Condensed Reference
|
|
2
|
+
|
|
3
|
+
Quick reference for the kernel optimizer. All numbers verified against specs.
|
|
4
|
+
|
|
5
|
+
## Hard Limits (WebGPU Spec)
|
|
6
|
+
|
|
7
|
+
| Constraint | Limit | Notes |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| Max workgroup invocations | 256 | Product of all dimensions |
|
|
10
|
+
| Max workgroup X/Y | 256 | |
|
|
11
|
+
| Max workgroup Z | 64 | |
|
|
12
|
+
| Workgroup storage (`var<workgroup>`) | 16 KB | All `var<workgroup>` combined |
|
|
13
|
+
| Storage buffer default max | 128 MB | Can request higher via adapter |
|
|
14
|
+
| Uniform buffer max | 64 KB | |
|
|
15
|
+
| SIMD width (Apple) | 32 threads | Fixed across all Apple GPUs |
|
|
16
|
+
|
|
17
|
+
## Apple M4 Max Hardware
|
|
18
|
+
|
|
19
|
+
| Spec | Value |
|
|
20
|
+
|---|---|
|
|
21
|
+
| GPU cores | 40 (or 32 in lower SKU) |
|
|
22
|
+
| Memory bandwidth | 546 GB/s (40-core) / 410 GB/s (32-core) |
|
|
23
|
+
| Memory type | LPDDR5X, unified CPU/GPU |
|
|
24
|
+
| L1 cache per core | 8 KB |
|
|
25
|
+
| L2 cache (shared) | 1 MB |
|
|
26
|
+
| System-level cache (SLC) | 8 MB |
|
|
27
|
+
| Cache line size | 128 bytes |
|
|
28
|
+
| Metal threadgroup memory | 32 KB max |
|
|
29
|
+
| Metal max threads/threadgroup | 1024 |
|
|
30
|
+
| Threadgroup memory alignment | 16 bytes |
|
|
31
|
+
| Shared memory banks | 32 banks, 4-byte granularity |
|
|
32
|
+
| SIMD group size | 32 threads (fixed) |
|
|
33
|
+
| Peak FP32 TFLOPS | ~17.04 (40-core boost) |
|
|
34
|
+
|
|
35
|
+
## Key Architecture Facts
|
|
36
|
+
|
|
37
|
+
- **Unified memory**: CPU and GPU share the same physical memory. No PCIe transfers. Zero-copy.
|
|
38
|
+
- **Memory-bound kernels**: INT4 matvec at ~8 FLOPS/byte — bandwidth is the bottleneck, not compute.
|
|
39
|
+
- **Dynamic shader core memory** (M3/M4): Register file acts as a cache. Unused threadgroup memory can be reclaimed for registers. Improves occupancy for complex shaders.
|
|
40
|
+
- **Optimal occupancy**: 1K–2K concurrent threads per GPU core. For 40 cores = 40K–80K total threads.
|
|
41
|
+
- **Bank conflicts**: 32-bank shared memory, 4-byte stride. Pad arrays by 32 to avoid conflicts.
|
|
42
|
+
|
|
43
|
+
## Workgroup Sizing Guidelines
|
|
44
|
+
|
|
45
|
+
1. Start at 64, tune in multiples of 32 (SIMD width)
|
|
46
|
+
2. Smaller workgroups (32–64) give scheduler more flexibility for load balancing
|
|
47
|
+
3. Larger workgroups (128–256) can improve data reuse but increase register pressure
|
|
48
|
+
4. For memory-bound kernels: smaller workgroups often win (less sync overhead)
|
|
49
|
+
5. For compute-bound kernels: larger workgroups can improve ALU utilization
|
|
50
|
+
|
|
51
|
+
## WGSL Memory Alignment
|
|
52
|
+
|
|
53
|
+
| Type | Alignment | Size |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `f32`, `u32`, `i32` | 4 bytes | 4 bytes |
|
|
56
|
+
| `vec2<f32>` | 8 bytes | 8 bytes |
|
|
57
|
+
| `vec3<f32>` | 16 bytes | 12 bytes (+4 padding) |
|
|
58
|
+
| `vec4<f32>` | 16 bytes | 16 bytes |
|
|
59
|
+
| Struct | max(member alignments) | rounded up to alignment |
|
|
60
|
+
|
|
61
|
+
## Subgroup Operations (Partial Support)
|
|
62
|
+
|
|
63
|
+
Available in Dawn/Metal backend:
|
|
64
|
+
- `subgroupAdd` → Metal `simd_sum`
|
|
65
|
+
- `subgroupBroadcast` → Metal `simd_broadcast`
|
|
66
|
+
- `subgroupBallot` → Metal `simd_ballot`
|
|
67
|
+
|
|
68
|
+
**Not available yet**: subgroup barrier. Must use `workgroupBarrier()` instead.
|
|
69
|
+
|
|
70
|
+
**Restriction**: Some backends restrict subgroup ops to 1D workgroups only.
|
|
71
|
+
|
|
72
|
+
## Dispatch Mechanics
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
global_invocation_id = workgroup_id * workgroup_size + local_invocation_id
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For a buffer of N elements with workgroup_size W:
|
|
79
|
+
```
|
|
80
|
+
dispatchWorkgroups(ceil(N / W), 1, 1)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Threads with `global_invocation_id >= N` must early-exit via guard condition.
|
|
84
|
+
|
|
85
|
+
## Critical Constraint: N_TILE / Dispatch Alignment
|
|
86
|
+
|
|
87
|
+
**THE #1 BUG TO AVOID** (caused 12 invalid experiments):
|
|
88
|
+
|
|
89
|
+
In our matvec kernels, each workgroup computes `N_TILE` output columns:
|
|
90
|
+
```
|
|
91
|
+
N_TILE = workgroup_size / K_THREADS
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The JS dispatch must use the SAME N_TILE:
|
|
95
|
+
```javascript
|
|
96
|
+
dispatchWorkgroups(ceil(N / N_TILE), 1, 1)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If WGSL `N_TILE` ≠ JS dispatch `N_TILE`, workgroups skip columns → garbage output with inflated tok/s (500+ tok/s is always a broken shader).
|
|
100
|
+
|
|
101
|
+
**Rule**: NEVER change `N_TILE`, `workgroup_size`, or `K_THREADS` in the WGSL shader without ensuring:
|
|
102
|
+
1. `N_TILE == workgroup_size / K_THREADS`
|
|
103
|
+
2. The JS dispatch `getDispatchSize()` uses the same `N_TILE`
|
|
104
|
+
3. Shared memory arrays (`array<f32, SIZE>`) have `SIZE >= workgroup_size`
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Gerbil Marketing/Docs Site — Update Plan
|
|
2
|
+
|
|
3
|
+
**Target repo:** `/Users/shenron/Code/gerbil-site` (separate Next.js app, App Router)
|
|
4
|
+
**Date scoped:** 2026-06-13
|
|
5
|
+
**Status:** Plan only — no site edits made yet. Execute against `gerbil-site`, not this repo.
|
|
6
|
+
|
|
7
|
+
## Why this exists
|
|
8
|
+
|
|
9
|
+
The site predates two major shifts and is now materially wrong:
|
|
10
|
+
|
|
11
|
+
1. **Native WGSL engine now works on mobile.** iPad/iOS Safari 26.5+ (WebKit) runs Qwen3.5-0.8B at **~41–51 tok/s, byte-correct**. It previously crashed. The site still says "iOS will crash," gates WebGPU to "Chrome/Edge 113+ only," and shows Safari as "may have quirks."
|
|
12
|
+
2. **Desktop got an autoresearch optimization pass.** M4 Max via node-dawn is now **~207 tok/s** (was ~145). Published numbers (40–200, 100–150) are stale and low.
|
|
13
|
+
|
|
14
|
+
There are also two **architecture-reality gaps**:
|
|
15
|
+
|
|
16
|
+
- The site presents a single transformers.js/ONNX stack. Reality is **two lanes**: (a) a **native WGSL engine** — fast text, mobile-proven; (b) a **transformers.js/ONNX lane** — modality breadth (STT/TTS/vision/embeddings), full-speed on desktop, **~5x slower on mobile** and only suitable for light/single-pass modalities there.
|
|
17
|
+
- The **model lineup is dated**: Kokoro TTS is old (better small TTS exists now), and **vision should be served by Qwen3.5 natively**, not a separate `ministral-3b` ONNX vision model.
|
|
18
|
+
|
|
19
|
+
## Real performance numbers to publish
|
|
20
|
+
|
|
21
|
+
| Context | Number | Notes |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Desktop native (M4 Max, node-dawn) | **~207 tok/s** | Qwen3.5-0.8B, post-autoresearch (was ~145) |
|
|
24
|
+
| iPad / iOS Safari 26.5+ native | **~41–51 tok/s** | Qwen3.5-0.8B Q4, byte-correct vs reference |
|
|
25
|
+
| Browser desktop native (Chrome/Edge) | ~150–207 tok/s range | keep honest; native WGSL |
|
|
26
|
+
| transformers.js/ONNX on mobile | **~5x slower** | light/single-pass modalities only (one TTS line, one embedding, short transcription). Not for streaming chat. |
|
|
27
|
+
| CPU (Node fallback) | ~30–60 tok/s | unchanged |
|
|
28
|
+
| WASM fallback | ~5–10 tok/s | unchanged |
|
|
29
|
+
|
|
30
|
+
**Browser support reality:** Chrome/Edge **113+** AND Safari/iOS **26.5+** (WebKit). WebGPU requires **HTTPS** (secure context) — call this out, it's the #1 mobile gotcha. Firefox still behind a flag → not recommended.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Per-file change list
|
|
35
|
+
|
|
36
|
+
Priority key: **P0** = factually wrong / actively misleading; **P1** = important correctness/positioning; **P2** = polish/consistency.
|
|
37
|
+
|
|
38
|
+
### 1. `app/page.tsx` (homepage)
|
|
39
|
+
|
|
40
|
+
- **P0 — line ~151** (GPU section subheadline):
|
|
41
|
+
- Current: `"40-200+ tok/s via WebGPU with CPU fallback that runs anywhere JavaScript runs. Text, vision, TTS & transcription. All WebGPU accelerated. Cached in IndexedDB."`
|
|
42
|
+
- New: `"Up to ~207 tok/s on desktop (M4 Max) and ~41-51 tok/s on iPad/iOS Safari 26.5+ — native WebGPU, byte-correct. Plus vision, TTS & transcription via the ONNX lane. Runs anywhere JavaScript runs. Cached in IndexedDB."`
|
|
43
|
+
- Note: drop "All WebGPU accelerated" blanket claim — the ONNX modalities are not all WebGPU on mobile.
|
|
44
|
+
|
|
45
|
+
- **P1 — line ~164** (`~100MB-2.5GB ONNX models` chip): keep but reframe — this is the ONNX lane. Consider adding a native-engine chip: `Native WGSL engine (mobile-proven)`.
|
|
46
|
+
|
|
47
|
+
- **P1 — Hero subheadline (lines ~91–98):** Currently lists "Text, vision, TTS, transcription, tools & skills" flatly. Add a one-line mention that text now runs on **mobile Safari**, the headline differentiator. Suggested addition near line 96: `Now runs on iPhone & iPad (Safari 26.5+), not just desktop.`
|
|
48
|
+
|
|
49
|
+
- **P2 — line ~482** (Vision code example): uses `g.loadModel("ministral-3b")`. See model-lineup section — vision should move to Qwen3.5 native. At minimum update the comment; ideally switch the model id once the native VLM path is the recommended one.
|
|
50
|
+
|
|
51
|
+
- **P2 — line ~575** (TTS code example, `Kokoro-82M`, `af_heart`): Kokoro is dated. Keep working but plan to swap default to the newer small TTS (see lineup section). Low urgency — code still runs.
|
|
52
|
+
|
|
53
|
+
- **P2 — line ~648** (CLI sample output `⚡ 47.2 tok/s`): cosmetic; bump to a current-looking number (e.g. `~190 tok/s`) so the hero CLI doesn't undersell.
|
|
54
|
+
|
|
55
|
+
### 2. `app/playground/page.tsx`
|
|
56
|
+
|
|
57
|
+
- **P0 — line 59:**
|
|
58
|
+
- Current: `Requires WebGPU support (Chrome 113+, Edge 113+)`
|
|
59
|
+
- New: `Requires WebGPU (Chrome/Edge 113+, or Safari/iOS 26.5+). Must be served over HTTPS.`
|
|
60
|
+
|
|
61
|
+
- **P1 — lines 124–146** (Chat Models list) and **150–163** (Vision): lineup is dated. Vision lists only `ministral-3b — 2.5GB`; should reflect native Qwen3.5 vision once available, and note mobile can't run 2.5GB ONNX vision. Add a note that **native-engine models (Qwen3.5-0.8B) are the mobile-capable ones**.
|
|
62
|
+
|
|
63
|
+
- **P1 — lines 170–183** (TTS panel, `Kokoro-82M — 330MB`): mark Kokoro as legacy / note a newer smaller TTS is recommended.
|
|
64
|
+
|
|
65
|
+
### 3. `components/PlaygroundNative.tsx` — **the live mobile demo**
|
|
66
|
+
|
|
67
|
+
This is the native WGSL playground. **It now works on mobile but the homepage never shows it by default.**
|
|
68
|
+
|
|
69
|
+
- **P0 — `components/Playground.tsx` lines 40–43** decide which playground renders:
|
|
70
|
+
```ts
|
|
71
|
+
const [mode, setMode] = useState<"native" | "full">(() => {
|
|
72
|
+
if (typeof window === "undefined") return "full";
|
|
73
|
+
return localStorage.getItem("gerbil-backend") === "native" ? "native" : "full";
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
Default is **`full`** (ONNX `PlaygroundFull`) unless localStorage opts into native. So a first-time visitor — especially on an iPad — gets the ONNX playground, which is the slow/fragile lane on mobile, **not** the fast native engine that now works. **Action:** detect mobile/Safari and default to `native` there (the proven-fast lane), or at least default new visitors to `native` for the text tab. This is the single highest-leverage change to make the "works on mobile" story real on the page.
|
|
77
|
+
|
|
78
|
+
- **P1 — `PlaygroundNative.tsx` has NO iOS guards.** Confirmed: no `isModelSafeForDevice` / crash-detection / mobile gating in this component (unlike `PlaygroundFull.tsx`, which has crash warnings at lines ~419, ~994, ~1007). Before it crashed on mobile; now it runs. Action: it's safe to surface on mobile, but add a light guard so it picks the **Q4 (404 MB)** native model by default on mobile rather than F32 (1.6 GB). Currently `nativeDtype` defaults to `"f32"` (line 72) and `nativeModel` defaults to the 4bit MLX model (line 71) — verify the default actually loads the small Q4 path on mobile; F32 default dtype on a 1.6GB model would be too heavy for an iPhone.
|
|
79
|
+
|
|
80
|
+
- **P2 — line 51** (Summarize example prompt) says "WebGPU now works in Node.js via Dawn... Small models run at 100+ tok/s on both client and server." Update the embedded number to reflect ~207 desktop / mobile reality, or generalize it. Same stale string is duplicated in `PlaygroundFull.tsx` line 132.
|
|
81
|
+
|
|
82
|
+
### 4. `components/AISDKPlayground.tsx`
|
|
83
|
+
|
|
84
|
+
- **P0 — lines 258, 267, 280:** three identical error strings `"WebGPU not supported in this browser. Try Chrome 113+"`.
|
|
85
|
+
- New: `"WebGPU not supported. Use Chrome/Edge 113+ or Safari/iOS 26.5+, served over HTTPS."`
|
|
86
|
+
|
|
87
|
+
- **P1 — line 192–197:** `useEmbedding` is stubbed out (`embed = null`) and the embeddings tab will throw on run. Either restore the hook or disable the Embed tab. (Separate from the freshness story but it's a broken live demo.)
|
|
88
|
+
|
|
89
|
+
### 5. `app/docs/browser/page.tsx` — **most stale file (1058 lines)**
|
|
90
|
+
|
|
91
|
+
- **P0 — line 16** (top banner): `100-150 tok/s with WebGPU` → `Up to ~207 tok/s desktop, ~41-51 tok/s on iPad/iOS native`.
|
|
92
|
+
|
|
93
|
+
- **P0 — lines 705–719** (`iOS Memory Guards` section intro): currently asserts `iOS Safari and iOS Chrome have strict memory limits (~300-400MB effective for WKWebView)` and frames iOS as crash-prone. **Rewrite the framing**: native WGSL engine now runs Qwen3.5-0.8B on iOS Safari 26.5+ at 41–51 tok/s, byte-correct. Keep the memory-guard *utilities* documentation (they're still real and useful for the ONNX lane / large models), but reframe from "iOS will crash" to "iOS is supported on the native engine; memory guards protect the heavier ONNX lane."
|
|
94
|
+
|
|
95
|
+
- **P0 — lines 692–694** (Browser Support table, Safari row): `Safari / 18+ / ⚠ May have quirks` → `Safari / iOS 26.5+ (WebKit) / ✓ Native engine supported`. Add the HTTPS-required caveat as a table footnote.
|
|
96
|
+
|
|
97
|
+
- **P0 — line 688** (Chrome/Edge row `113+`): fine, but add a note that Safari now joins full support for the native engine.
|
|
98
|
+
|
|
99
|
+
- **P1 — lines 250–257, 330–333, 940–942:** `isWebGPUSupported` / alert / troubleshooting copy all say "Chrome/Edge 113+" only. Add Safari/iOS 26.5+ everywhere.
|
|
100
|
+
|
|
101
|
+
- **P1 — lines 649–667** (Browser Models speed table `100-150` / `150-200` / `200-300 tok/s`): these are ONNX-lane numbers and now read low next to 207. Recheck against current benchmarks; at minimum add a native-engine row for Qwen3.5-0.8B.
|
|
102
|
+
|
|
103
|
+
- **P1 — lines 770–822** (iOS Compatibility Matrix): rebuild around the native engine. Add Qwen3.5-0.8B Q4 (404 MB) as **✓ iOS Safe (native, ~41-51 tok/s)**. Keep ONNX large models as risky/blocked. The current matrix only covers ONNX models.
|
|
104
|
+
|
|
105
|
+
- **P2 — line 401–404** (Mobile q4 note): still accurate for the ONNX lane; clarify it applies to ONNX, and that the native engine has its own Q4 path.
|
|
106
|
+
|
|
107
|
+
### 6. `app/docs/architecture/page.tsx` — **needs the two-lane story (591 lines)**
|
|
108
|
+
|
|
109
|
+
- **P0 — entire framing (lines 19–118):** The system-overview and pipeline Mermaid diagrams show only `transformers.js → ONNX Runtime`. There is **no mention of the native WGSL engine**. Add it as a first-class lane:
|
|
110
|
+
- Lane A: **Native WGSL engine** — hand-written WebGPU compute kernels, fast text generation, runs on desktop (node-dawn ~207 tok/s) and mobile Safari (~41-51 tok/s). This is the default text path.
|
|
111
|
+
- Lane B: **transformers.js / ONNX Runtime** — modality breadth (STT/TTS/vision/embeddings), full speed on desktop, ~5x slower on mobile, light/single-pass only there.
|
|
112
|
+
- Update both Mermaid charts to show the split (browser/node → router → {Native WGSL | ONNX}).
|
|
113
|
+
|
|
114
|
+
- **P1 — lines 135–152** (Execution Backends table): `WebGPU / Browser, Chrome / ~100-150 tok/s` → split native vs ONNX, add Safari/iOS, bump desktop native to ~207.
|
|
115
|
+
|
|
116
|
+
- **P1 — lines 70–74** (Key Decision "WebGPU First"): mentions only headless Chrome (ChromeGPUBackend) for Node. Reality now includes **node-dawn** for the native engine. Add node-dawn as the native-engine Node path.
|
|
117
|
+
|
|
118
|
+
- **P2 — lines 236–264** (Node WebGPU path, ChromeGPUBackend, port 43724): still valid for the ONNX lane; clarify which lane it belongs to vs node-dawn.
|
|
119
|
+
|
|
120
|
+
### 7. Model lineup — `components/ModelsTable.tsx`, `app/docs/models/page.tsx`, `app/docs/vision/page.tsx`, `app/docs/tts/page.tsx`
|
|
121
|
+
|
|
122
|
+
- **P1 — Vision via Qwen3.5 native, not `ministral-3b`:**
|
|
123
|
+
- `ModelsTable.tsx` line ~22–28: `ministral-3b` flagged `vision: true`.
|
|
124
|
+
- `vision/page.tsx` lines 24, 57, 119: all use `ministral-3b` (2.5GB ONNX).
|
|
125
|
+
- `models/page.tsx` line 71–76: "For vision → ministral-3b".
|
|
126
|
+
- Action: once the native Qwen3.5 vision path is the recommendation, point vision at Qwen3.5 (same family as the fast/mobile text engine). Note that 2.5GB ONNX vision is desktop-only; native Qwen3.5 vision is the path forward. Keep `ministral-3b` documented as a heavier ONNX option if still supported.
|
|
127
|
+
|
|
128
|
+
- **P2 — Kokoro is dated TTS:**
|
|
129
|
+
- `ModelsTable.tsx` line ~194 (`kokoro-82m`), `tts/page.tsx` lines 11/31/61/158, `page.tsx` line ~575.
|
|
130
|
+
- Action: introduce the newer small TTS as the recommended default; demote Kokoro to "also supported." `supertonic-66m` is already listed (ModelsTable line ~205, tts page line ~39) — if that's the better small model, make it the default in copy and code samples.
|
|
131
|
+
|
|
132
|
+
- **P2 — `components/FeatureCards.tsx` line 65:** `"40-200 tok/s on WebGPU"` → `"Up to ~207 tok/s on desktop, runs on iPhone & iPad too."`
|
|
133
|
+
|
|
134
|
+
### 8. Sweep (lower priority, same stale patterns)
|
|
135
|
+
|
|
136
|
+
- `app/docs/vision/page.tsx` line 422: `70-100+ tok/s (WebGPU)` — vision is genuinely slower; verify but likely fine. ONNX-lane, desktop.
|
|
137
|
+
- `app/docs/repl/page.tsx` lines 289–291: sample REPL output `45-47 tok/s` — cosmetic, bump if desired.
|
|
138
|
+
- `components/PlaygroundFull.tsx` lines 132 (dup summarize prompt), 317/678 (vision ~25 tok/s) — ONNX lane, mostly accurate; update the embedded "100+ tok/s" claim.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Suggested execution order
|
|
143
|
+
|
|
144
|
+
1. **P0 correctness pass** (no design work): `playground/page.tsx:59`, `AISDKPlayground.tsx` 258/267/280, `browser/page.tsx` 16/688–694/705–719, `page.tsx:151`. These are pure copy fixes — Safari/iOS 26.5+, HTTPS, real tok/s.
|
|
145
|
+
2. **Playground default-to-native on mobile** (`Playground.tsx` + light guard in `PlaygroundNative.tsx`): makes the "works on mobile" claim demonstrably true on the live site. Highest-leverage single change.
|
|
146
|
+
3. **Architecture two-lane rewrite** (`architecture/page.tsx`): the conceptual fix everything else hangs off.
|
|
147
|
+
4. **iOS compatibility matrix + browser models tables** rebuild around the native engine.
|
|
148
|
+
5. **Model lineup** (vision → Qwen3.5 native, TTS default off Kokoro) — coordinate with whatever the engine actually ships as the recommended native VLM/TTS.
|
|
149
|
+
|
|
150
|
+
## Open items to confirm before editing
|
|
151
|
+
|
|
152
|
+
- Exact recommended **native vision model id** for Qwen3.5 (is the native VLM path shipped, or still desktop-ONNX `ministral-3b` for now?).
|
|
153
|
+
- The **newer small TTS** model id to replace Kokoro as default (Supertonic-66M, or something newer?).
|
|
154
|
+
- Whether to keep the desktop browser native number as a single figure (~207) or a range; pick one and use it consistently across all files.
|
|
155
|
+
- `useEmbedding` is stubbed in `AISDKPlayground.tsx` (line 192) — restore or disable that tab.
|