|
Download README.md from j-llm/jevlite: direct link, hf CLI and curl.
- Browser
- Download file 11.6 kB
-
https://huggingface.co/j-llm/jevlite/resolve/main/README.md
- Command line
-
hf download hf://j-llm/jevlite/README.md
-
curl -L -o README.md https://huggingface.co/j-llm/jevlite/resolve/main/README.md
11.6 kB
| license: apache-2.0 | |
| base_model: answerdotai/ModernBERT-base | |
| base_model_relation: finetune | |
| datasets: | |
| - LocalLLaMA/typed-decisions | |
| library_name: coreml | |
| pipeline_tag: text-classification | |
| tags: | |
| - coreml | |
| - mlpackage | |
| - apple | |
| - apple-silicon | |
| - apple-neural-engine | |
| - ane | |
| - macos | |
| - on-device | |
| - modernbert | |
| - typed-decisions | |
| # JevLite for Apple Silicon — typed decisions on the Neural Engine | |
|  | |
|  | |
|  | |
|  | |
|  | |
| **English** | [日本語](#日本語) | |
| **Ready-to-run Core ML packages of a 149M ModernBERT typed-decision engine, built for Apple Silicon.** | |
| Hand it a state plus any set of typed questions (`noul` / `choice` / `score`) and it answers all of | |
| them in one forward pass with a confidence each — fully on-device, no server, no API cost. | |
| - 🍎 **Core ML `.mlpackage`, fp16, runs on the Apple Neural Engine** (`compute_units="cpu_and_ne"`) | |
| - ⚡ **13 ms** per call at 256 tokens on an M2 Max — **5.4× faster than PyTorch-CPU**, with the GPU left free | |
| - 🎯 **No accuracy loss vs PyTorch**: 99.65% decision agreement on the full test split, accuracy −0.15 pp | |
| - 🧩 **Schema stays dynamic**: questions and labels are data, not baked into the graph — new questions need no re-export | |
| - 🔁 fp32 packages (exact parity) and the PyTorch weights included for verification and non-Apple platforms | |
| ## Apple Neural Engine performance | |
| Measured on **Mac14,6 — Apple M2 Max (32 GB), macOS 26.6.2**, coremltools 9.0, batch 1, | |
| median of 100 runs after 20 warmup, real encoded inputs. | |
| | seq len | PyTorch CPU | PyTorch MPS | Core ML `cpu_only` | **Core ML `cpu_and_ne`** | | |
| |---|---|---|---|---| | |
| | 256 | 71.5 ms | 13.4 ms | 32.8 ms | **13.2 ms** | | |
| | 512 | 123.8 ms | 22.9 ms | 64.2 ms | **37.1 ms** | | |
| | 1024 | 253.7 ms | 47.4 ms | 169.0 ms | **111.1 ms** | | |
| - `cpu_and_ne` beats Core ML `cpu_only` by 2.5× / 1.7× / 1.5× and PyTorch-CPU by 5.4× / 3.3× / 2.3×. | |
| - It matches the GPU (MPS) at 256 tokens while keeping the GPU idle — the low-power, GPU-freeing path. | |
| At 512/1024 tokens MPS is still faster. | |
| - ANE participation is inferred from `cpu_and_ne` being consistently faster than `cpu_only` with | |
| identical math; a per-op placement trace from Xcode was not produced. | |
| ### Parity vs PyTorch (full test split, 400 cases / 2,000 decisions, `cpu_and_ne`) | |
| | metric | value | | |
| |---|---| | |
| | decision agreement | **0.9965** | | |
| | accuracy (Core ML / PyTorch) | 0.6445 / 0.6430 | | |
| | confidence MAE | 0.0024 | | |
| The fp32 packages are exact (max |Δlogit| 0.0000) but run on CPU/GPU only — the ANE is fp16-only. | |
| ## Requirements | |
| | package set | OS | hardware | | |
| |---|---|---| | |
| | `coreml/` (fp16, **ANE**) | **macOS 26+** | Apple Silicon | | |
| | `coreml-fp32/` (exact) | macOS 15+ | Apple Silicon | | |
| | `jevlite.pt` / `model.safetensors` | any | CPU / CUDA / MPS | | |
| Python: `torch`, `transformers>=4.48`, `numpy`, `coremltools>=9.0,<10`. The tokenizer is fetched from | |
| `answerdotai/ModernBERT-base`. | |
| ## Quick start (Mac) | |
| ```bash | |
| hf download j-llm/jevlite --local-dir jevlite | |
| cd jevlite | |
| pip install torch "transformers>=4.48" numpy "coremltools>=9.0,<10" | |
| python decide.py --backend coreml --pkg-dir coreml # interactive console on the Neural Engine | |
| ``` | |
| ```python | |
| from engine import DecisionEngine | |
| from typed_schema import Question | |
| eng = DecisionEngine(backend="coreml", ckpt="jevlite.pt", pkg_dir="coreml", | |
| compute_units="cpu_and_ne") # Neural Engine; backend="torch" elsewhere | |
| print(eng.decide({"user": "I was charged twice this month"}, { | |
| "category": Question.choice("What kind of support request is this?", { | |
| "billing": "Charges, invoices, refunds or payment methods.", | |
| "bug": "Something in the product is broken.", | |
| "other": "Anything else."}), | |
| "urgent": Question.noul("This request is urgent."), | |
| })) | |
| eng.close() | |
| ``` | |
| Run from the repo root (`engine.py` loads `05_serve.py` by relative path). The default | |
| `coreml_mode="worker"` isolates the Core ML runtime in a subprocess — use it behind any server. | |
| ## Files | |
| | path | what | | |
| |---|---| | |
| | `coreml/jevlite-{256,512,1024}.mlpackage` | Core ML fp16, Neural Engine. Smallest bucket covering the input is used. ~300 MB each. | | |
| | `coreml-fp32/jevlite-{256,512,1024}.mlpackage` | Core ML fp32, exact parity reference. | | |
| | `jevlite.pt` | PyTorch checkpoint (`state_dict`, encoder, max_len=1024, temperatures). Source of all exports. | | |
| | `model.safetensors` | Same weights as `jevlite.pt` (fp32, 149M params); metadata holds encoder, max_len, temperatures. | | |
| | `*.py`, `requirements.txt` | Minimal inference code from the source repo (unchanged). | | |
| ## How the Core ML graph is split | |
| The `.mlpackage` computes `token_logits [1, S]` — ModernBERT encoder + score head at every position, | |
| inputs `input_ids` / `attention_mask` (int32). Tokenizing the questions, gathering the label-marker | |
| positions, per-type temperature and per-question softmax run in numpy on the CPU | |
| (`coreml_backend.py`, a few µs per call). That is why the schema stays fully dynamic. | |
| ## Model | |
| ModernBERT-base + `Linear(d, 1)` token head, trained 20 epochs on | |
| [`LocalLLaMA/typed-decisions`](https://huggingface.co/datasets/LocalLLaMA/typed-decisions). | |
| Test accuracy 0.6430, ECE 0.0536 (official 400-case split). | |
| Source: [eightman999/open-jev-typed-decision-engine](https://github.com/eightman999/open-jev-typed-decision-engine) | |
| (fork of [intikhab49/open-jev-typed-decision-engine](https://github.com/intikhab49/open-jev-typed-decision-engine)) — | |
| see `ANE_REPORT.md` and `BENCHMARK.md` there for full measurements and limitations. | |
| --- | |
| ## 日本語 | |
| [English](#jevlite-for-apple-silicon--typed-decisions-on-the-neural-engine) | **日本語** | |
| **Apple Silicon 向けにそのまま動かせる、149M パラメータの ModernBERT 型付き判定エンジン(Core ML 版)です。** | |
| 状態(JSON やテキスト)と、型付きの質問(`noul` = 真偽 / `choice` = 選択 / `score` = 段階評価)を任意の数だけ渡すと、 | |
| 1回の推論ですべてに答え、それぞれの確信度を返します。端末内で完結し、サーバーも API 料金も不要です。 | |
| - 🍎 **Core ML `.mlpackage`(fp16)で Apple Neural Engine 上で動作**(`compute_units="cpu_and_ne"`) | |
| - ⚡ M2 Max で 256 トークンなら **1回 13 ms**。PyTorch(CPU)の **5.4 倍速く**、GPU は空いたまま | |
| - 🎯 **PyTorch と比べて精度は落ちない**:テストデータ全件で判定一致率 99.65%、精度差 −0.15 ポイント | |
| - 🧩 **質問は自由に変えられる**:質問やラベルはデータとして渡すので、グラフに焼き込まれていない。新しい質問でも再変換は不要 | |
| - 🔁 完全一致の検証用 fp32 版と、Apple 以外でも使える PyTorch の重みも同梱 | |
| ### Apple Neural Engine での性能 | |
| 計測環境:**Mac14,6 — Apple M2 Max(32 GB)、macOS 26.6.2**、coremltools 9.0、バッチ 1、 | |
| ウォームアップ 20 回のあと 100 回計測した中央値、実際にエンコードした入力を使用。 | |
| | 入力長 | PyTorch CPU | PyTorch MPS | Core ML `cpu_only` | **Core ML `cpu_and_ne`** | | |
| |---|---|---|---|---| | |
| | 256 | 71.5 ms | 13.4 ms | 32.8 ms | **13.2 ms** | | |
| | 512 | 123.8 ms | 22.9 ms | 64.2 ms | **37.1 ms** | | |
| | 1024 | 253.7 ms | 47.4 ms | 169.0 ms | **111.1 ms** | | |
| - `cpu_and_ne` は Core ML `cpu_only` より 2.5 / 1.7 / 1.5 倍、PyTorch(CPU)より 5.4 / 3.3 / 2.3 倍速い。 | |
| - 256 トークンでは GPU(MPS)と同等の速さで、GPU を使わずに済む。省電力で GPU を空けておける構成。 | |
| 512・1024 トークンでは MPS のほうが速い。 | |
| - Neural Engine を使っていることは、同じ計算で `cpu_and_ne` が `cpu_only` より常に速いことから推測している。 | |
| Xcode での演算ごとの割り当ては確認していない。 | |
| ### PyTorch との一致(テストデータ全件:400 件 / 2,000 判定、`cpu_and_ne`) | |
| | 指標 | 値 | | |
| |---|---| | |
| | 判定一致率 | **0.9965** | | |
| | 精度(Core ML / PyTorch) | 0.6445 / 0.6430 | | |
| | 確信度の平均絶対誤差 | 0.0024 | | |
| fp32 版は完全一致(logit 差の最大 0.0000)ですが、Neural Engine は fp16 専用のため CPU/GPU で動きます。 | |
| ### 動作要件 | |
| | ファイル | OS | ハードウェア | | |
| |---|---|---| | |
| | `coreml/`(fp16、**Neural Engine**) | **macOS 26 以上** | Apple Silicon | | |
| | `coreml-fp32/`(完全一致) | macOS 15 以上 | Apple Silicon | | |
| | `jevlite.pt` / `model.safetensors` | 問わない | CPU / CUDA / MPS | | |
| Python パッケージ:`torch`、`transformers>=4.48`、`numpy`、`coremltools>=9.0,<10`。 | |
| トークナイザーは `answerdotai/ModernBERT-base` から取得します。 | |
| ### 使い方(Mac) | |
| ```bash | |
| hf download j-llm/jevlite --local-dir jevlite | |
| cd jevlite | |
| pip install torch "transformers>=4.48" numpy "coremltools>=9.0,<10" | |
| python decide.py --backend coreml --pkg-dir coreml # Neural Engine で対話コンソールを起動 | |
| ``` | |
| Python から使う場合は、上の英語版にあるコード例をそのまま使えます(`backend="coreml"`、`pkg_dir="coreml"`)。 | |
| `engine.py` は `05_serve.py` を相対パスで読むので、ダウンロードしたフォルダで実行してください。 | |
| 既定の `coreml_mode="worker"` は Core ML の実行をサブプロセスに分けるので、サーバーに組み込むときはこちらを使ってください。 | |
| ### ファイル | |
| | パス | 内容 | | |
| |---|---| | |
| | `coreml/jevlite-{256,512,1024}.mlpackage` | Core ML fp16(Neural Engine 用)。入力長をカバーする最小のものが使われる。各約 300 MB。 | | |
| | `coreml-fp32/jevlite-{256,512,1024}.mlpackage` | Core ML fp32。PyTorch と完全一致する検証用。 | | |
| | `jevlite.pt` | PyTorch チェックポイント(`state_dict`、エンコーダ名、max_len=1024、温度)。すべての変換の元。 | | |
| | `model.safetensors` | `jevlite.pt` と同じ重み(fp32、149M)。メタデータにエンコーダ名・max_len・温度を格納。 | | |
| | `*.py`、`requirements.txt` | 元リポジトリの推論コード(変更なし)。 | | |
| ### Core ML 側と Python 側の分担 | |
| `.mlpackage` が計算するのは `token_logits [1, S]`(ModernBERT エンコーダ+スコアヘッドを全位置で評価した値)だけです。 | |
| 入力は `input_ids` / `attention_mask`(int32)。質問のトークン化、ラベル位置の取り出し、型ごとの温度、 | |
| 質問ごとの softmax は CPU 上の numpy で行います(`coreml_backend.py`、1回数マイクロ秒)。 | |
| そのため質問の形は自由に変えられます。 | |
| ### モデル | |
| ModernBERT-base に `Linear(d, 1)` のトークンヘッドを付け、 | |
| [`LocalLLaMA/typed-decisions`](https://huggingface.co/datasets/LocalLLaMA/typed-decisions) で 20 エポック学習しました。 | |
| テスト精度 0.6430、ECE 0.0536(公式の 400 件テストセット)。 | |
| 元リポジトリ:[eightman999/open-jev-typed-decision-engine](https://github.com/eightman999/open-jev-typed-decision-engine) | |
| ([intikhab49/open-jev-typed-decision-engine](https://github.com/intikhab49/open-jev-typed-decision-engine) のフォーク)。 | |
| 詳しい計測結果と制約は、そちらの `ANE_REPORT.md` と `BENCHMARK.md` を参照してください。 | |