File size: 6,700 Bytes
e9f8aad af19b42 e9f8aad 958e2c0 073d1f4 958e2c0 e9f8aad a1fd999 4abd289 e9f8aad 4abd289 114f98a 4abd289 114f98a e9f8aad 4abd289 e9f8aad 4abd289 e9f8aad 4abd289 e9f8aad 4abd289 9a96803 4abd289 9a96803 e9f8aad 4abd289 e9f8aad 4abd289 e9f8aad 4abd289 e9f8aad 4abd289 e9f8aad 4abd289 049cc16 4abd289 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | ---
license: apache-2.0
base_model: google/gemma-4-E4B
tags:
- coreml
- apple-neural-engine
- decision-model
- d1a
library_name: coreml
pipeline_tag: text-classification
---
<p align="center"><img src="https://huggingface.co/JohnP1/d1a-e4b-coreml/resolve/main/d1a-avatar.png" width="200" alt="D1A avatar: an anime girl with silver-white and dark purple hair, round glasses and headphones on a round #D1A badge"></p>
# D1A-E4B v0.6 · Core ML (text, ≤ 512 tokens)
**A small decision model for the Apple Neural Engine: give it a document and a few questions, and it picks the answers.** Each question
is yes/no, multiple choice or a score; D1A returns a calibrated probability for every option in one forward pass, with no
generated text, so every answer is a valid option.
This is the Core ML build: text only, documents up to 512 tokens, about 1.8 s per request on an M4's Neural Engine, 6.1 GB.
For photos, voice, video, longer documents or more speed (0.63 s on the M4's GPU), use the MLX build
[JohnP1/d1a-e4b-mlx-q8](https://huggingface.co/JohnP1/d1a-e4b-mlx-q8). D1A labels pull requests, routes requests and triages
messages; it is built on Google's Gemma 4 E4B ([jonpol01/d1a](https://github.com/jonpol01/d1a)).
This repository is the text model converted to Core ML; the conversion is described in jonpol01/d1a#224.
## Status
- **Correct at ≤ 512 tokens.** On 28 real requests (42 questions), no clear-cut answer changes against the fp32 PyTorch
rebuild of the same model, on an M1 Max and an M4.
- **Verification is small so far.** Those 42 questions are this build's only accuracy check. The full evaluation suites
and the 145-request demo smoke test that the MLX build passed have not been run on it. If you need measured accuracy
across tasks, use [JohnP1/d1a-e4b-mlx-q8](https://huggingface.co/JohnP1/d1a-e4b-mlx-q8).
- **Speed (median request):** M4 Neural Engine 1.8 s (MLX on the GPU: 0.63 s); M1 Max 2.9 s (MLX: 0.81 s).
- **Use it** where the GPU should stay free or power matters (iPhone, iPad). On a Mac, the MLX build is faster.
- **Not included yet:** photo, voice and video (their encoders are separate models, still to convert), and inputs longer than
512 tokens (2,048-token programs gave wrong answers on the M4 Neural Engine, measured with D1A-E2B's chunks).
## Run it
```bash
pip install coremltools numpy torch transformers safetensors "d1a @ git+https://github.com/jonpol01/d1a"
hf download JohnP1/d1a-e4b-coreml --revision v0.6 --local-dir d1a-e4b-coreml
python d1a-e4b-coreml/reference/run.py d1a-e4b-coreml request.json
```
`request.json` is a System One request, for example:
```json
{"state": "Shoes arrived two weeks late and in the wrong size. Also I see two charges on my card.",
"questions": {"team": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"returns": null, "shipping": null, "billing": null}},
"urgent": {"type": "noul", "instructions": "Does this need a reply today?"}}}
```
The first run compiles the chunks into `coreml/.compiled/` (a few minutes); later runs load them.
## Files
| Path | What |
|---|---|
| `coreml/L512_<a>-<b>.mlpackage` | 7 chunks of the 42-layer text model, int8 weights (per block of 64). Chunk 18-24 outputs the shared keys and values that chunks 24-42 read. |
| `embeddings.safetensors` | the token and per-layer embedding tables (MLX affine-quantized, from JohnP1/d1a-e4b-mlx-q8@v0.6), read row by row on the host |
| `head.safetensors`, `d1a_config.json` | the pointer head, the temperature and the pad and delimiter ids |
| `config.json`, `tokenizer.json`, `tokenizer_config.json` | the Gemma 4 model config and tokenizer |
| `io.json` | each chunk's input names |
| `reference/` | Python reference: `run.py` (one request), `workers.py` (one process per chunk), `d1a_coreml.py` (host-side embeddings and masks) |
## How a request runs
1. Encode it with D1A's layout (`d1a.core.encoding.encode`) and right-pad it to 512 tokens with the pad token.
2. Look up the token embeddings (scaled by √hidden) and the per-layer embeddings (scaled by √256) on the host.
3. Build the block-causal masks (full and sliding), clamped to −1e4.
4. Run the chunks in order, each in its own process. Several large Neural Engine programs in one process can crash the
runtime.
5. Read the hidden states at each question's `<decide>` and `</opt>` positions, score them with the head, divide by the
temperature, and take the softmax.
macOS 15 / iOS 18 or later.
## D1A builds compared
Measured on 2026-10-11 on the same 28 real requests (42 questions, all ≤ 512 tokens), on an Apple M1 Max and an Apple M4.
| | E2B · MLX | E2B · Core ML | E4B · MLX | E4B · Core ML |
|---|---|---|---|---|
| Version | v0.6 | v0.6 | v0.6 | v0.6 |
| Repository | JohnP1/d1a-e2b-mlx-q8 | JohnP1/d1a-e2b-coreml | JohnP1/d1a-e4b-mlx-q8 | JohnP1/d1a-e4b-coreml |
| Runs on | Mac GPU | Neural Engine (iPhone, iPad, M4-class Macs) | Mac GPU | Neural Engine |
| Text | yes | yes | yes | yes |
| Photo, voice, video (16 frames, no sound) | yes | not yet (next) | yes | not yet |
| Input length | long documents | ≤ 512 tokens | long documents | ≤ 512 tokens |
| Questions | yes/no, choice, score, with a calibrated probability for each option | same | same | same |
| Languages | questions in English; documents in English or Japanese | same | same | same |
| PR labels, 487 newest PRs: type / severity | 87.5% / 77.2%; 0 of 30 P0/P1 found | same model | 90.6% / 79.1%; 13 of 30 P0/P1 | same model |
| Size | 3.8 GB + 1.0 GB media | 3.5 GB (1.8 GB chunks + 1.6 GB embeddings) | 6.6 GB + 1.0 GB media | 6.1 GB (3.9 GB chunks + 2.1 GB embeddings) |
| Median request, M4 (p95) | **0.20 s** (0.26) | 0.96 s (0.97) | 0.63 s (0.89) | 1.80 s (1.91) |
| Median request, M1 Max (p95) | **0.17 s** (0.23) | 9.7 s (10.0) ² | 0.81 s (1.33) | 2.93 s (2.95) |
| Load, M4 / M1 Max | 2 s / 9 s | 40 s / 247 s | 3 s / – | 52 s / 106 s |
| Answer changes vs fp32 PyTorch ¹ | 0 of 37 clear-cut (M4: 1 near-tie of 42) | 0 of 37 clear-cut (M4: 1 near-tie of 42) | 0 of 38 clear-cut | 0 of 38 clear-cut |
| Photo / voice / video, median (M1 Max) | 0.83 s over the 14 demo requests | – | – | – |
¹ Each build is compared with the fp32 PyTorch rebuild of the same v0.6 model. "Clear-cut" means the reference's top
answer leads by more than 0.05; a near-tie can flip either way.
² On the M1 Max's Neural Engine, the E2B chunks fall back to the CPU: each chunk takes the same time with or without the
Neural Engine. The M4 runs the same files on its Neural Engine.
## License
Apache-2.0. Base model: Gemma 4 by Google (Apache-2.0). D1A is built on Kev by Jared Palmer (Apache-2.0).
|