mlboydaisuke commited on
Commit
d1ec632
·
verified ·
1 Parent(s): 431614f

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +75 -0
README.md ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - executorch
5
+ - xnnpack
6
+ - pte
7
+ - on-device
8
+ - text-generation
9
+ base_model:
10
+ - microsoft/Phi-4-mini-instruct
11
+ ---
12
+ # Phi-4-mini-instruct — ExecuTorch XNNPACK 8da4w + 8-bit embedding
13
+
14
+ `phi_4_mini_xnnpack_8da4w_e8.pte` (2597.9 MB)
15
+
16
+ - **Source**: Qwen/Phi-4-mini-instruct
17
+ - **License**: Apache-2.0
18
+ - **Quantization**: 8da4w linear + 8-bit embedding (`embedding_quantize: "8,0"`)
19
+ - **Export**: executorch 1.4.0 `export_llm`, static shape (seq_len=1), max_seq_length 2048,
20
+ XNNPACK extended_ops
21
+ - **Config**: `llm_params/phi_4_mini_xnnpack_8da4w_e8.yaml`
22
+
23
+ ## Verification (Mac arm64, 2026-08-21)
24
+
25
+ `llm_params/gen_static.py`, token-by-token prefill then greedy decode, a fresh process per
26
+ prompt so no answer is read through the previous one's cache:
27
+
28
+ | prompt | answer | decode |
29
+ |---|---|---|
30
+ | capital of France? | "The capital of France is Paris." then keeps going | 49.3 tok/s |
31
+ | 17 times 4? | "17 times 4 is equal to 68." and stops | 49.7 tok/s |
32
+
33
+ Stopping is the part worth looking at. Chat template is `<|user|>...<|end|><|assistant|>`,
34
+ bos 199999, eos [200020, 199999] — the model's own
35
+ `generation_config.json`. The upstream example config
36
+ (`examples/models/phi_4_mini/config/phi_4_mini_xnnpack.yaml`) carries 151643 for both, which
37
+ is Qwen's, and a model that never sees its end token does not stop.
38
+
39
+ Not measured on a phone. Worth noting against the rest of the shelf: this decodes at 49
40
+ tok/s where [Qwen3.5-4B](https://huggingface.co/mlboydaisuke/Qwen3.5-4B-ExecuTorch) manages
41
+ 8.6 at a comparable 2.8 GB. The Qwen3.5 exports run with `use_sdpa_with_kv_cache: False`
42
+ and this one with it on.
43
+
44
+ ## Converting it
45
+
46
+ ```bash
47
+ python convert/export_phi_4_mini.py
48
+ ```
49
+
50
+ Not `export_llm` directly, because its download path cannot reach this model:
51
+ `load_checkpoint_from_pytorch_model` reads `pytorch_model.bin` and this repository ships
52
+ safetensors only, so the code falls back to torchtune's checkpointer — a dependency with
53
+ its own torch pin, for a key rename and two splits. The script reads the safetensors, calls
54
+ upstream's own `phi_4_hf_to_meta`, and ties the output embedding back on: input and output
55
+ embeddings are tied here, so there is no `lm_head.weight` to map to `output.weight`, and the
56
+ model refuses a checkpoint without it. The torchtune converter beside it ties them; the
57
+ safetensors one does not.
58
+
59
+ ## Running it
60
+
61
+ ```bash
62
+ python llm_params/gen_static.py \
63
+ --pte phi_4_mini_xnnpack_8da4w_e8.pte \
64
+ --tokenizer tokenizer.json \
65
+ --prompt '<|user|>What is the capital of France?<|end|><|assistant|>' \
66
+ --eos_ids "[200020,199999]"
67
+ ```
68
+
69
+ The 8-bit embedding needs `from executorch.kernels import quantized` before the program is
70
+ loaded. Without it the method will not even load — `kernel
71
+ 'quantized_decomposed::embedding_byte.dtype_out' not found` — which reads like a broken
72
+ export rather than a runtime missing its kernels.
73
+
74
+ (conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models) ·
75
+ iOS sample: [executorch-samples](https://github.com/john-rocky/executorch-samples))