Downloads · 30 days
0
okayuji/Gemma-4-E4B-it-coreml-speculative
Gemma-4-E4B-it-coreml-speculative is a text generation model from okayuji. Use it when you need the model to write or continue text. It is set up for coreml. The card lists the license as apache-2.0.
Run Google's Gemma 4 E4B IT locally on the GPU of an Apple silicon Mac with Core ML. The bundle supports text and image input, and prompt-lookup speculation verified to preserve the same output with speculation off or…
Downloads · 30 days
0
Access
Public
Updated Oct 23, 2026
Repo size
6.8 GB
Likes
0
Public
Click a slice to open those files.
.bin6.8 GB · 99%
From the Hugging Face model README
Run Google's Gemma 4 E4B IT locally on the GPU of an Apple silicon Mac with Core ML. The bundle supports text and image input, and prompt-lookup speculation verified to preserve the same output with speculation off or on. The companion app also includes a Live Camera captioning loop.
Swift runtime & app · Mac setup & model guide · When speculation helps · Verification
MLState. The E2B bundle is the iPhone option.Requires: Apple silicon Mac · macOS 26+ · companion Swift runtime · roughly 8 GB free unified memory (4.0 GB measured footprint; conditions) · ~6.8 GB disk with the image encoder.
hf download okayuji/Gemma-4-E4B-it-coreml-speculative --local-dir ./gemma-4-e4b-speculative
git clone https://github.com/oka-yuji/coreml-llm-samples
cd coreml-llm-samples
swift run -c release --package-path CoreLLMKit corellm-chat --model ../gemma-4-e4b-speculative --stats \
--prompt "List three fruits, one per line."
This repository contains weights and configuration. The companion runtime supplies the stateful chain, shared-KV wiring and speculation loop used by both the CLI and app. For the GUI and image input, follow the Mac guide.
Speculation is opt-in: run the same command with CORELLM_MTP_PLD=1 in the environment to enable prompt-lookup speculation. Draft length defaults to 4; CORELLM_MTP_DRAFT_LEN=6 favors verbatim-heavy work. Output is byte-identical either way. On the measured workloads, speculation helps verbatim copying and is slightly slower for composed replies; see Where speculation pays.
Apple M4 Max (128 GB) / macOS 26.5.2, GPU, greedy (temperature 0), one process per condition,
corellm-chat CLI (2026-07-28). Prompt (72 tokens with chat template):
Extract every person, place, and date from this note as JSON with keys people, places, dates: Maya flew from Osaka to Reykjavik on March 3, 2026, and met Dr. Chen and Lena Novak at the Harpa concert hall on March 5, 2026.
Output — the model wrapped its JSON in a code fence; shown verbatim, identical with speculation off and on (99 tokens to EOS):
```json
{
"people": [
"Maya",
"Dr. Chen",
"Lena Novak"
],
"places": [
"Osaka",
"Reykjavik",
"Harpa concert hall"
],
"dates": [
"March 3, 2026",
"March 5, 2026"
]
}
```
| Run | prompt → gen | Decode | Speculation |
|---|---|---|---|
| Speculation off | 72 → 99 (eos) | 32.0 tok/s | — |
| Speculation on (draft 6) | 72 → 99 (eos) | 29.8 tok/s | acceptance 0.38 |
(Across 5 interleaved off/on rounds the pair-ratio median is ×0.94–0.96.)
Two honest notes on this sample. First, on this build JSON extraction is slightly below
break-even — the JSON scaffolding (\``json`, braces, key names) does not appear in the prompt, so
prompt-lookup has little to draft from; speculation pays on verbatim-copy spans (next section).
Second, this output is byte-identical (212 bytes, same SHA-256) to what the E2B iPhone bundle
produces for the same prompt — a different model size, quantization, compute unit and runtime path
landing on the same JSON.
Same machine and conditions, 5 interleaved off/on rounds, per-round pair-ratio median (2026-07-28). Rows run to EOS or a 48-token cap; the JSON row is the EOS-complete run (99 tokens):
| Workload | Off tok/s | Speedup (draft 6) | Speedup (draft 4) | Acceptance (d6) |
|---|---|---|---|---|
| Verbatim copy (repeat a 10-item list) | 31.4 | ×3.49 | ×3.13 | 0.86 |
| ID enumeration (6 equipment IDs, answered correctly) | 31.0 | ×0.77 | ×0.82 | 0.21 |
| JSON extraction (99 tokens to EOS) | 30.5 | ×0.96 | ×0.94 | 0.38 |
| Free-form prose (one-sentence answer) | 30.0 | ×0.98 | ×0.98 | 0.29 |
Verbatim copy is the one clear win; everything the model has to compose — even something as regular as an ID list — sits slightly below break-even, so leave speculation off for chat-style use. A cautionary tale from this bundle's own gating: an earlier internal build with a broken chat template measured ×2.37 on the enumeration row — the model was parroting the prompt, which turns any reply into a verbatim copy. A broken template can fake speculation gains; every number on this card is from the fixed, canonical-template bundle.
The verbatim-copy gate, shown in full — prompt (Japanese, "Copy this list exactly: apple, mandarin, grape, peach, pear, strawberry, melon, watermelon, kiwi, banana"):
次のリストをそのまま書き写してください。
りんご、みかん、ぶどう、もも、なし、いちご、メロン、すいか、キウイ、バナナ
Output (identical with speculation off and on, 30 tokens):
りんご、みかん、ぶどう、もも、なし、いちご、メロン、すいか、キウイ、バナナ
The CLI run above measured 32.6 tok/s off → 109.2 tok/s on (draft acceptance 0.86); across
5 interleaved rounds the pair-ratio median is ×3.49. The output ends cleanly at the end-of-turn
token — 30 generated tokens, byte-identical off and on (the speculation run's --stats reports 31:
it counts the end-of-turn token, which never appears in the text). Draft length 6 beats 4 on
verbatim work (+11%); with mixed workloads, draft 4 is the safer default.
Ship bundle, Apple M4 Max (128 GB) / macOS 26.5.2, GPU, one process per condition, warmup-excluded medians (2026-07-28):
| Metric | Value |
|---|---|
| Decode (speculation off) | 31.1 tok/s (32.1 ms/tok) |
| Prefill (512-token prompt) | 670 tok/s |
| TTFT, 28-token prompt | 83 ms |
| TTFT, 512-token prompt | 764 ms |
| Multi-turn TTFT, 2nd turn (35 of 53 tokens reused) | 67 ms |
| Cold load (fresh process, to first token ready) | 2.84 s |
| Warm load | 2.50 s |
| Resident footprint | 4.0 GB |
| Disk | 6.5 GB |
The sample, speculation table and key numbers above come from the author's
2026-07-28-e4b-manifest-fix.md: the canonical-template ship bundle, Swift benchmark harness and
companion release CLI. That lab record is not public; the public Mac guide
summarizes the results and provides the off/on reproduction commands. The text-only bundle is
6.5 GB; the image encoder brings the full download to ~6.8 GB.
gemma4, 42 layers, hidden 2560, GQA 8 query / 2 KV heads;
head_dim 256 on sliding layers, 512 on full-attention layers). Chunks 0–12 and 12–24 are
stateful — their KV caches live in MLState, resident on the GPU, so the host never touches
KV shapes. Layers 24–41 share the KV of layers 22/23: chunk 12–24 emits those two stores as
outputs and the two stateless chunks 24–36 / 36–42 consume them as inputs.lm_head (tanh soft-cap 30
baked in; emits token ids, not logits).The runtime reads the prompt template from manifest.json — transcribed verbatim:
"promptPrefix": "<|turn>user\n", "promptSuffix": "<turn|>\n<|turn>model\n" — prepends BOS, and
stops on the end-of-turn token <turn|> (id 106). A single user turn is therefore:
<bos><|turn>user
{user text}<turn|>
<|turn>model
<|turn> / <turn|> are Gemma 4's actual special tokens (ids 105 / 106); the Gemma-3-era
<start_of_turn> / <end_of_turn> strings are not in this vocabulary and tokenize as plain
text — a mismatched template silently degrades output (it costs ~17–18 tokens per turn and leaks a
literal marker string into replies). chat_template.jinja is included for HF-ecosystem tooling.
The bundle carries vision_fp16.mlmodelc next to the language chunks. The companion runtime looks for
it inside the bundle directory, next to manifest.json, and enables image input only when it is
there. An image is resized to 768x768 and becomes 256 soft tokens — 256 of the 2,048 context —
whatever the source resolution.
The vision tower is the same weights as the E2B bundle's: the two vision_config blocks are
byte-identical, 658 of 658 tensors are bit-identical, and the towers' activations agree at
maxAbsDiff 0.000e+00. Only the projection into the language model differs — 2,560 wide here
against E2B's 1,536 — which is why each bundle ships its own copy and the runtime refuses a mismatched
encoder instead of producing garbage from a width mismatch.
Measured on an Apple M4 Max, one process per condition:
| Metric | Value |
|---|---|
| Image question, vision encode | 93–94 ms (GPU) / 313–320 ms (CPU) |
| Image question, TTFT | 0.75 s |
| Image question, decode | 29.8–34.3 tok/s |
| Prefill, 273-token prompt with 256 image rows | 0.44–0.55 s |
| Live Camera, warm cycle (English) | 1.44 s |
| Live Camera, warm cycle (Japanese) | 1.63 s |
The vision encoder runs on the GPU while the language chain keeps the full compute-unit set; the two were sharing one accelerator before that split, and separating them is where the encode went from hundreds of milliseconds to under a hundred.
This is where the stateful graph shows against the E2B bundle. On the same 10-cycle live captioning
run, E4B takes 1.44 s per cycle against E2B's 2.48 s — not because it decodes faster in proportion
(32.0 vs 23.5 tok/s) but because feeding the 256 image rows costs 0.36 s here against 1.21 s there.
Variable-width prefill on an MLState cache absorbs the image span in one pass; a fixed-width
scheduled prefill has to break it into chunks.
| File | Size | Role |
|---|---|---|
chunk_0_12.mlmodelc / chunk_12_24.mlmodelc | 0.65 GB each | stateful transformer chunks (int4) |
chunk_24_36.mlmodelc / chunk_36_42.mlmodelc | 0.63 / 0.31 GB | stateless shared-KV chunks (int4) |
lmhead.mlmodelc | 0.71 GB | argmax head (int8, soft-cap baked in) |
embed_int8.bin + embed_scale.bin | 0.67 GB | token embedding sidecar (int8 + fp32 row scales) |
ple_int8.bin + ple_scale.bin | 2.82 GB | per-layer embedding sidecar (int8 + fp32 row scales) |
tokenizer.json, tokenizer_config.json | 32 MB | tokenizer |
chat_template.jinja | 19 KB | chat template as published by Google for gemma-4-E4B-it |
generation_config.json | 208 B | upstream generation defaults (EOS ids) |
manifest.json, convert_config_v2int4_int8.json | 15 KB | runtime wiring (shapes, stores, sidecar dtypes, prompt template) |
vision_fp16.mlmodelc | 0.31 GB | vision encoder — 768x768 image to 256 soft tokens (fp16) |
LICENSE | 11 KB | Apache License 2.0 full text |
Delete vision_fp16.mlmodelc and the bundle is a 6.5 GB text model with image input switched off.
vision_fp16.mlmodelc. Incremental
refresh of a downloaded bundle is not exposed in the UI.~/Library/Caches/**/com.apple.e5rt.e5bundlecache (tens of GB over time across models). Safe to
delete; the next first-load re-specializes.lm_head emits argmax token ids only — greedy decoding. Temperature sampling would need a
logits-head variant, which this bundle does not include.MLState KV design does not run on the Neural Engine, and the bundle does
not fit 6 GB iPhones. CPU-only execution is not supported for this graph.1、2、3… vs はい、1から10まで…; fp32 top-2 margin
0.97), not degradation. On the measured verbatim / enumeration / JSON workloads, int4 output is
identical to the fp16 build's. AWQ (p999) was tried and worsened fidelity (it introduced a
second divergence), so raw int4 shipped.Everything below was gated on this exact bundle (or its direct inputs) on 2026-07-28, one process per condition, Apple M4 Max / macOS 26.5.2:
transformers fp32 greedy for 32 tokens
exactly (#mismatch = 0). The rebuilt forward was first validated against HF at fp32
(argmax 20/20, logits max |Δ| = 2.98e-4, cos_min 0.999997).vision_config byte-identical, 658 / 658 tensors
bit-identical, activations maxAbsDiff 0.000e+00 — the same tower, differing only in the
projection width.okayuji/Gemma-4-E2B-it-coreml-speculative
— the series' first bundle: E2B on the iPhone Neural Engine, chunked multifunction graph with
host-side KV, dedicated verify functions, KV save/restore.lube8163/gemma-4-12b-coreml-iphone-practical-chat
— appeared the same week as the E2B release (2026-07-25), pairing a width-4 verifier with an MTP
drafter on a 12B model. Differences here, stated as fact, not evaluation: this bundle is
draft-free (prompt lookup — nothing extra to load or keep resident), its off/on outputs are
verified byte-identical, and it decodes at practical speed (30 tok/s class on a Mac GPU versus
that card's reported ~0.2–0.5 tok/s speculative on an iPhone 14 — largely a model-size and platform
difference). I have not reproduced their bundle; the comparison is taken from their published card.This bundle runs with the Core ML runtime in coreml-llm-samples. For separate Core AI / Foundation Models conversions and examples, see coreai-samples. That project is a related collection for comparing the frameworks; its runtime uses different model assets and does not load this Core ML bundle.
google/gemma-4-E4B-it,
released by Google under Apache License 2.0. This repository redistributes a quantized Core ML
conversion under the same license; the full license text is in LICENSE.