kem-gov commited on
Commit
3837ef0
·
verified ·
1 Parent(s): 95c5c70

Sync model repo (text/metadata)

Browse files
README.md ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: onnxruntime-genai
3
+ display_name: TinyLlama-1.1B-Chat INT4 — ONNX GenAI (Vivo X300)
4
+ license: apache-2.0
5
+ tags:
6
+ - text-generation
7
+ - tinyllama
8
+ - llama
9
+ - int4
10
+ - quantized
11
+ - onnx
12
+ - onnxruntime-genai
13
+ - mlas
14
+ - kleidiai
15
+ - arm
16
+ - android
17
+ - vivo-x300
18
+ - edge-ai
19
+ - k_quant_last
20
+ pipeline_tag: text-generation
21
+ datasets:
22
+ - Rowan/hellaswag
23
+ metrics:
24
+ - accuracy
25
+ base_model: TinyLlama/TinyLlama-1.1B-Chat-v1.0
26
+ base_model_relation: quantized
27
+ model-index:
28
+ - name: tinyllama-1.1b-chat-onnx-genai-exp10-kquantlast-emb-int8-asym
29
+ results:
30
+ - task:
31
+ type: text-generation
32
+ name: Commonsense Reasoning (HellaSwag)
33
+ dataset:
34
+ type: Rowan/hellaswag
35
+ name: HellaSwag
36
+ split: validation
37
+ args:
38
+ eval_samples: 8000
39
+ metrics:
40
+ - type: accuracy
41
+ value: 59.00
42
+ name: HellaSwag Accuracy (acc_norm, character-normalized)
43
+ - type: accuracy
44
+ value: 45.98
45
+ name: HellaSwag Accuracy (raw, acc)
46
+ ---
47
+
48
+ # TinyLlama-1.1B-Chat INT4 + INT8 Embeddings — ONNX (GenAI-Builder, k_quant_last + asym, MLAS + KleidiAI on Vivo X300)
49
+
50
+ Mixed-precision quantized version of [`TinyLlama/TinyLlama-1.1B-Chat-v1.0`](https://huggingface.co/TinyLlama/TinyLlama-1.1B-Chat-v1.0): **INT4 weights (GPTQ)** for the transformer-block Linears, **INT8 weights for the LM head** (`k_quant_last` protection), **INT8 per-token dynamic activations**, and an **INT8 per-row embedding table** — benchmarked on a **Vivo X300 (Android 16 / OriginOS 6)** smartphone with the MediaTek Dimensity 9500 (C1-Ultra / C1-Premium / C1-Pro, aarch64). The decode loop is dispatched almost entirely (99.84 % of runtime) to ONNX Runtime's MLAS execution provider, with `MatMulNBits` hitting the **KleidiAI fast-path** (`qsi8d32p x qsi4c32p` SDOT kernel) for W4A8-dynamic GEMM acceleration on the phone's ARMv9 cores.
51
+
52
+ ## Key Highlights
53
+
54
+ Paired on-device benchmark on the Vivo X300 smartphone (Android 16 / OriginOS 6, `onnxruntime-genai` 1.27.0, `intra_threads = 4`, 30 measured runs, 5 warm-ups, ~154-token prompt, 30 decoded tokens) — the FP32 baseline (`optimum-cli` ONNX export, 4197 MB) and the optimized INT4+INT8-emb bundle were run in the same session on the same phone:
55
+
56
+ - **Bundle size — 727.86 MB** vs FP32 4196.99 MB (**5.77× compression**).
57
+ - **55.65 tok/s decode throughput** on-device vs FP32 7.82 tok/s (**+47.83 tok/s, 7.12× speedup**).
58
+ - **510.14 ms time-to-first-token** for a ~154-token prompt vs FP32 905.95 ms (−395.81 ms).
59
+ - **883.66 ms cold-start model load** vs FP32 5900.94 ms (−5017 ms); **890.47 MB peak USS memory** vs FP32 4086.28 MB (**4.59× memory reduction**).
60
+ - **1047.62 ms E2E p50 latency** vs FP32 4757.49 ms (−3710 ms).
61
+ - **99.84 % MLAS time coverage** — 5 376 / 5 592 operators (96.14 %) dispatched to MLAS; `MatMulNBits` (83.96 % of decode time) uses the KleidiAI fast-path.
62
+ - **Minimal accuracy loss** — HellaSwag `acc_norm` **59.0 %** (Δ **-0.80 pp** vs the 59.8 % FP32 baseline; identical bundle to the Graviton measurement — INT8/INT4 weights are hardware-independent).
63
+
64
+ ## Model Details
65
+
66
+ ### Model Description
67
+
68
+ W4A8-dynamic quantized re-pack of TinyLlama's `TinyLlama-1.1B-Chat-v1.0` for efficient ARM-CPU inference via `onnxruntime-genai`. Every Linear projection in attention and the FFN is re-packed to per-row group-wise **INT4 weights** (group size 32) using **GPTQ** as the weight-calibration algorithm — recipe `exp10_kquantlast_emb_int8_asym`, asymmetric per-group `(scale, zero_point)`. The **final LM-head projection** is protected by the `k_quant_last` algorithm and kept at **INT8 weights** rather than being compressed to 4 bits (the output-vocabulary projection is the most sensitive layer in the network). Activations are quantized to **INT8 per-token dynamic** at runtime: each row gets its own `delta_t = max(|X[t, :]|) / 127`, so the loudest token and the median token both use the full INT8 grid. The token embedding table is stored **INT8 per-row** (one `(scale, zero_point)` per vocabulary token).
69
+
70
+ - **Developed by:** TinyLlama project (base model); ONNX INT4 re-pack by Marvik using the `onnxruntime-genai` model-builder toolchain.
71
+ - **Model type:** Causal Language Model (decoder-only Transformer, 22 layers, hidden size 2048, 32 / 4 GQA, 2048-token context).
72
+ - **License:** Apache-2.0 (inherited from the TinyLlama-1.1B-Chat-v1.0 base model).
73
+ - **Base model:** [`TinyLlama/TinyLlama-1.1B-Chat-v1.0`](https://huggingface.co/TinyLlama/TinyLlama-1.1B-Chat-v1.0) — quantized, not fine-tuned.
74
+ - **Deployment target for this card:** Vivo X300 (MediaTek Dimensity 9500, 8-core aarch64 — 2x C1-Ultra + 3x C1-Premium + 3x C1-Pro, 16 GB LPDDR, Android 16 / OriginOS 6).
75
+
76
+ ### Model Sources
77
+
78
+ - **Base model:** https://huggingface.co/TinyLlama/TinyLlama-1.1B-Chat-v1.0
79
+ - **TinyLlama project:** https://github.com/jzhang38/TinyLlama
80
+ - **ONNX Runtime GenAI:** https://github.com/microsoft/onnxruntime-genai
81
+
82
+ ## How to Get Started with the Model
83
+
84
+ ### Install dependencies
85
+
86
+ ```bash
87
+ # onnxruntime + the genai wrapper (Python 3.12)
88
+ pip install "onnxruntime>=1.22" "onnxruntime-genai>=0.14" tokenizers jinja2
89
+ ```
90
+
91
+ > **On-device Android note.** On-device benchmarking of this bundle was done with a cross-compiled `bench_genai` C runner pushed to the phone via ADB (see the sibling Android runner in the source repo). The Python `example.py` in this card is meant to be used off-device (Linux / macOS / aarch64 server) to reproduce the same accuracy from the same bundle. `onnxruntime-genai >= 0.14.0` ships `manylinux_2_28_aarch64` wheels for Linux aarch64; Android on-device inference is done via the ONNX Runtime C API + KleidiAI-enabled shared library.
92
+
93
+ ### Download the model
94
+
95
+ ```python
96
+ from huggingface_hub import snapshot_download
97
+
98
+ local_dir = snapshot_download(
99
+ repo_id="Arm/tinyllama-1-1b-chat-onnx-genai-int4-kquantlast-emb-int8-vivo-x300",
100
+ allow_patterns=[
101
+ "model.onnx",
102
+ "model.onnx.data",
103
+ "genai_config.json",
104
+ "tokenizer.json",
105
+ "tokenizer_config.json",
106
+ "tokenizer.model",
107
+ "special_tokens_map.json",
108
+ "chat_template.jinja",
109
+ ],
110
+ )
111
+ ```
112
+
113
+ ### Run inference
114
+
115
+ The bundled `example.py` runs a single chat-style generation end-to-end and saves the result to `predictions.json` next to the script:
116
+
117
+ ```bash
118
+ python example.py
119
+ ```
120
+
121
+ Core inference loop (equivalent to what `example.py` does):
122
+
123
+ ```python
124
+ import onnxruntime_genai as og
125
+
126
+ # Load the model directory (must contain model.onnx + model.onnx.data + genai_config.json + tokenizer)
127
+ model = og.Model("./model_dir")
128
+ tokenizer = og.Tokenizer(model)
129
+
130
+ prompt = (
131
+ "<|user|>\nExplain in one paragraph what gravity is and why it matters.</s>\n"
132
+ "<|assistant|>"
133
+ )
134
+ input_ids = tokenizer.encode(prompt)
135
+
136
+ params = og.GeneratorParams(model)
137
+ params.set_search_options(max_length=256, do_sample=False, temperature=0.0)
138
+ generator = og.Generator(model, params)
139
+ generator.append_tokens(input_ids)
140
+
141
+ while not generator.is_done():
142
+ generator.generate_next_token()
143
+
144
+ print(tokenizer.decode(generator.get_sequence(0)))
145
+ ```
146
+
147
+ ## Evaluation
148
+
149
+ ### Testing Data, Factors & Metrics
150
+
151
+ #### Testing Data
152
+
153
+ - **HellaSwag** — [`Rowan/hellaswag`](https://huggingface.co/datasets/Rowan/hellaswag) validation split, full 8 000 questions, zero-shot. Accuracy is bundle-only (identical `model.onnx` + `model.onnx.data` used on the Vivo phone and on the Graviton server), so `acc_norm` = 59.00 % / raw `acc` = 45.98 % applies verbatim to this deployment.
154
+ - **On-device latency & memory** — measured on a **Vivo X300** smartphone: 30 measured runs + 5 warm-ups, ~154-token prompt (rendered from the standard "gravity" prompt via the bundled Zephyr chat template), 30 decoded tokens per run, `intra_op_num_threads = 4`.
155
+
156
+ #### Metrics
157
+
158
+ - **HellaSwag Accuracy (`acc_norm`)** — character-length-normalized accuracy. For each (context, 4 endings) tuple, the model scores each ending's log-likelihood under the context, divides by the ending's character length, and picks the argmax. This is the `lm_eval` equivalent of `acc_norm` and the standard HellaSwag headline number.
159
+ - **HellaSwag Accuracy (raw `acc`)** — same task, without length normalization. Reported alongside `acc_norm` because raw accuracy is more sensitive to logit-scale drift introduced by quantization.
160
+ - **Decode Throughput (tok/s)** — end-to-end tokens/sec over a 30-token continuation on the Vivo X300.
161
+ - **TTFT (ms)** — wall-clock latency from "submit prompt" to "first token emitted" for a ~154-token prompt.
162
+ - **Per-token Decode Latency (ms)** — median autoregressive cost per generated token.
163
+ - **E2E Latency (p50 / p90 / p99)** — end-to-end run wall-clock (prefill + 30 decoded tokens), across the 30 measured runs.
164
+ - **Peak Memory (USS, MB)** — peak unique-set-size of the `bench_genai` process on the phone (mmapped weights + KV cache + ORT scratch).
165
+ - **MLAS Operator / Time Coverage** — fraction of ONNX operators (and runtime) dispatched to ORT's MLAS execution provider.
166
+
167
+ ### Results
168
+
169
+ #### Accuracy (HellaSwag, zero-shot, 8 000 validation samples)
170
+
171
+ Accuracy is deterministic per bundle (INT8/INT4 arithmetic is hardware-independent), so these numbers are the same on Vivo X300 and on Graviton — they characterize the exp10 recipe, not the device.
172
+
173
+ | Metric | FP32 (Original) | INT4 + INT8-emb (Optimized) | Delta |
174
+ |:---|:---:|:---:|:---:|
175
+ | HellaSwag Accuracy (`acc_norm`) | 59.80 % | **59.00 %** | **-0.80 pp** |
176
+ | HellaSwag Accuracy (raw `acc`) | 46.76 % | **45.98 %** | **-0.78 pp** |
177
+ | Standard error (per side, pp) | 0.55 | 0.55 | — |
178
+
179
+ The 95 % CIs (approx. +/- 1.10 pp at n = 8 000) overlap, so the small drop on both metrics is within statistical noise.
180
+
181
+ #### On-device Performance (Vivo X300, MLAS + KleidiAI, intra_threads = 4, 30 measured runs, paired)
182
+
183
+ | Metric | FP32 (Original) | INT4 + INT8-emb (Optimized) | Delta |
184
+ |:---|:---:|:---:|:---:|
185
+ | Decode Throughput | 7.82 tok/s | **55.65 tok/s** | **+47.83 tok/s (7.12×)** |
186
+ | Time-to-First-Token (~154-token prompt) | 905.95 ms | **510.14 ms** | −395.81 ms |
187
+ | Per-token Decode (median) | 127.87 ms | **17.97 ms** | −109.90 ms (7.12×) |
188
+ | Decode Total (30 tokens) | 3.84 s | **0.54 s** | −3.30 s |
189
+ | E2E Latency p50 | 4757.49 ms | **1047.62 ms** | −3709.86 ms |
190
+ | E2E Latency p90 | 4798.12 ms | **1218.37 ms** | −3579.75 ms |
191
+ | E2E Latency p99 | 4804.92 ms | **1251.55 ms** | −3553.37 ms |
192
+ | Time-to-First-Inference (cold) | 4414.16 ms | **1009.50 ms** | −3404.66 ms |
193
+ | Model Load Time (cold) | 5900.94 ms | **883.66 ms** | −5017.28 ms |
194
+ | Init Memory (USS) | 4063.73 MB | **863.54 MB** | −3200.19 MB |
195
+ | Median Memory (USS) | 4067.23 MB | **866.41 MB** | −3200.82 MB (4.69×) |
196
+ | Peak Memory (USS) | 4086.28 MB | **890.47 MB** | −3195.80 MB (4.59×) |
197
+ | CPU utilisation (peak) | 800.00 % (8 active threads) | 800.00 % (8 active threads) | — |
198
+
199
+ The FP32 baseline is the `optimum-cli` ONNX export of `TinyLlama/TinyLlama-1.1B-Chat-v1.0` (4196.99 MB). Both bundles were pushed via ADB to the same phone and benched back-to-back in the same session — the numbers above are directly comparable. The optimized bundle beats FP32 on every latency axis: prefill (TTFT), per-token decode, cold-start load, and end-to-end p50/p90/p99. `MatMulNBits` on the KleidiAI fast-path is what makes the 7.12× decode speedup possible.
200
+
201
+ #### Runtime Backend Coverage (optimized model, on-device)
202
+
203
+ | Metric | Value |
204
+ |:---|---:|
205
+ | Total operators (full decode) | 5 592 |
206
+ | MLAS operators | 5 376 (**96.14 %**) |
207
+ | Default-CPU operators | 216 |
208
+ | MLAS Time Coverage | **99.84 %** |
209
+ | KleidiAI fast-path operators | `MatMulNBits` (2 664 ops, 83.96 % of decode time) |
210
+
211
+ Top ops by runtime share: `MatMulNBits` 83.96 %, `GroupQueryAttention` 11.60 %, `SkipSimplifiedLayerNormalization` 1.68 %, `QuickGelu` 1.54 %, `Mul` 1.02 % — everything remaining is in the noise floor (< 0.1 % each: `Cast`, `Gather`, `SimplifiedLayerNormalization`, `ReduceSum`, `Sub`, `Unsqueeze`, `Shape`). Non-MLAS ops (216 total, 0.16 % of runtime): `Cast`, `Gather`, `ReduceSum`, `Shape`, `Unsqueeze`.
212
+
213
+ #### Model Size
214
+
215
+ | Artifact | Size |
216
+ |:---|---:|
217
+ | `model.onnx` (graph) | ~193 KB |
218
+ | `model.onnx.data` (external INT4 weights + INT8 embedding table) | **~727 MB** |
219
+ | Tokenizer (`tokenizer.json` + `.model`) | ~4 MB |
220
+ | **Total bundle** | **~728 MB** |
221
+
222
+ Parameter count: 1 100 M (unchanged — quantization repacks weights, does not prune them).
223
+
224
+ ## Technical Specifications
225
+
226
+ ### Objective
227
+
228
+ Causal language modelling / instruction following — given a sequence of input tokens, predict the next-token distribution; iterate to generate a continuation. Fine-tuned for chat-style turns with a 32k SentencePiece vocabulary and a 2048-token context window.
229
+
230
+ ### Quantization
231
+
232
+ - **Method:** Post-Training Quantization (PTQ) — weights packed by the ONNX Runtime GenAI `model_builder` with `int4_algo_config=k_quant_last`, `int4_block_size=32`, `int4_is_symmetric=false`. The INT4 weight quantization is calibrated with **GPTQ** on **WikiText2** (256 sequences × 512 tokens each, ~131k tokens total). Activations are quantized at runtime per-token (dynamic INT8), and the embedding table is stored INT8 per-row.
233
+ - **Bit-width:** INT4 weights (packed 2-per-byte) + INT8 per-token dynamic activations (W4A8 dyn) + INT8 per-row embeddings + **INT8 LM-head weights** (protected).
234
+ - **Weight calibration algorithm:** **GPTQ** — layer-wise Hessian-based error compensation over 256 WikiText2 sequences of 512 tokens each (~131k calibration tokens total); produces the per-group `(scale, zero_point)` values for the INT4-packed `MatMulNBits` tensors.
235
+ - **Granularity (weights):** Per-row, group-wise (group size = 32).
236
+ - **Granularity (activations):** Per-row (per-token) dynamic — `(scale, zero_point)` recomputed at runtime, no offline calibration.
237
+ - **Symmetry:** Asymmetric weights (each group stores `(scale, zero_point)`); asymmetric activations (per-token min/max).
238
+ - **Last-layer protection (`k_quant_last`):** the **final LM-head projection** (vocab-size output MatMul, ~64 MB) is kept at **INT8 weights** rather than compressed to INT4. This is the single most quantization-sensitive layer in the network — protecting it recovers most of the `acc_norm` drop that a pure-INT4 export would incur, at the cost of ~32 MB extra bundle size relative to full INT4.
239
+ - **Embedding table:** Stored as **INT8 per-row** (one `(scale, zero_point)` per vocabulary token). The lookup is a `Gather` op (not a MatMul), so quantizing it is a pure storage choice — no kernel changes downstream.
240
+ - **Backend:** ONNX Runtime CPU EP with MLAS + KleidiAI fast-path for `MatMulNBits`.
241
+ - **Layers kept at higher precision:** LM head at INT8; LayerNorms, residual adds, GeLU stay in FP16/FP32 inside the MLAS-fused `GroupQueryAttention` / `SkipSimplifiedLayerNormalization` ops because they are already cheap.
242
+
243
+ ### Export Pipeline
244
+
245
+ 1. Load the FP32 base model from `TinyLlama/TinyLlama-1.1B-Chat-v1.0`.
246
+ 2. Export to FP32 ONNX via `optimum-cli export onnx` (the ~4.10 GB baseline).
247
+ 3. Re-pack with the ONNX Runtime GenAI model builder using `--extra_options int4_is_symmetric=false int4_block_size=32 int4_algo_config=k_quant_last`. GPTQ calibration data (256 WikiText2 sequences × 512 tokens each, ~131k tokens) is fed to the builder so the per-group `(scale, zero_point)` values minimise the layer-wise reconstruction loss rather than being derived from bare min/max. The builder packs transformer-block Linear weights into `MatMulNBits` (4-bit, group = 32, asymmetric, GPTQ-calibrated), keeps the final LM-head projection at INT8 via `k_quant_last`, fuses attention into a single `GroupQueryAttention` op, wires up the KV-cache inputs/outputs, and writes `model.onnx` + `model.onnx.data` + `genai_config.json`.
248
+ 4. Apply INT8 per-row surgery to the token embedding table (saves ~96 MB on a 32 000 x 2 048 table at no measurable accuracy cost).
249
+ 5. Ship the tokenizer files alongside (`tokenizer.json`, `tokenizer.model`, `tokenizer_config.json`, `special_tokens_map.json`, `chat_template.jinja`).
250
+
251
+ ### On-device Runner
252
+
253
+ For the on-phone benchmark reported in this card, the same bundle was pushed to the Vivo X300 via ADB and invoked from a small C runner (`bench_genai`) linked against the ORT + `onnxruntime-genai` shared libraries with KleidiAI enabled. The runner does 5 warm-up + 30 measured generations of 30 tokens each from the rendered chat prompt, samples per-thread CPU / RSS every 200 ms while running, and reports median TTFT / tokens-per-second / p90/p99 E2E latency / peak USS memory / MLAS coverage from the ORT profiling JSON.
254
+
255
+ ### Preprocessing
256
+
257
+ | Property | Value |
258
+ |---|---|
259
+ | Input shape | `[1, T]` (`int64` `input_ids`) |
260
+ | Tokenizer | `tokenizer.json` (Llama SentencePiece BPE, 32 000 vocab) |
261
+ | Chat template | `chat_template.jinja` (Zephyr-style `<|user|>` / `<|assistant|>` markers) |
262
+ | `position_ids` input | **Not exposed** — the GenAI graph derives positions internally |
263
+
264
+ **Steps**:
265
+ 1. Apply the chat template to the user prompt (wraps in `<|user|>\n...</s>\n<|assistant|>`).
266
+ 2. Tokenize with the bundled SentencePiece BPE tokenizer to obtain `input_ids`.
267
+ 3. Hand to `onnxruntime-genai`'s `Generator`; the runtime owns the autoregressive loop and the KV cache.
268
+
269
+ **Normalization**: None required — `input_ids` are integer token indices, not real-valued features.
270
+
271
+ ### Postprocessing
272
+
273
+ | Property | Value |
274
+ |---|---|
275
+ | Output | One token-id per decode step (greedy argmax over the 32 000-token vocabulary) |
276
+ | Decoder | Same SentencePiece BPE tokenizer used for input |
277
+ | HellaSwag scoring | Per-ending log-likelihood under the context, normalized by ending character length (`acc_norm`) or raw (`acc`) |
278
+
279
+ **Steps**:
280
+ 1. Iterate `Generator.generate_next_token()` until EOS (`</s>`) is emitted or the `max_length` budget is hit.
281
+ 2. `Tokenizer.decode(output_ids, skip_special_tokens=True)` to obtain the human-readable continuation.
282
+
283
+ ## Known Limitations
284
+
285
+ - **Evaluation scope is HellaSwag-only.** HellaSwag is a four-choice commonsense reasoning benchmark; it does not measure code, math, multi-turn instruction following, or long-context behaviour. Quantization-sensitive benchmarks (MMLU, GSM8K, HumanEval) may show larger gaps than the -0.80 pp seen here.
286
+ - **Latency & memory are Vivo X300-specific.** The MediaTek Dimensity 9500 (C1-Ultra / C1-Premium / C1-Pro, ARMv9) is a recent premium mobile SoC; older Android SoCs (Cortex-A76, A78, Snapdragon 7-series) or non-Android aarch64 devices (Raspberry Pi, Cortex-A55) will see materially different absolute numbers. Relative INT4-vs-FP32 speedup is expected to remain favourable because both paths share the same MLAS + KleidiAI code paths.
287
+ - **Fixed `intra_op_num_threads = 4`** in the published Vivo runtime numbers. Batch > 1 was not measured; larger thread counts on the phone's big cores may further improve throughput at the cost of memory / battery.
288
+ - **2 048-token context window.** Inherited from the TinyLlama base model — long-context inputs (> 2 048 tokens) are not supported.
289
+ - **`onnxruntime-genai` aarch64 wheel ships from 0.14.0.** Older versions (<= 0.13.2) require a source build on aarch64 to enable KleidiAI. On Android the runtime is built from source via the ORT NDK toolchain rather than pip-installed.
290
+
291
+ ## Citation
292
+
293
+ If you use this model, please also cite the upstream papers:
294
+
295
+ ```bibtex
296
+ @misc{zhang2024tinyllama,
297
+ title={TinyLlama: An Open-Source Small Language Model},
298
+ author={Peiyuan Zhang and Guangtao Zeng and Tianduo Wang and Wei Lu},
299
+ year={2024},
300
+ eprint={2401.02385},
301
+ archivePrefix={arXiv},
302
+ primaryClass={cs.CL}
303
+ }
304
+
305
+ @misc{zellers2019hellaswag,
306
+ title={HellaSwag: Can a Machine Really Finish Your Sentence?},
307
+ author={Rowan Zellers and Ari Holtzman and Yonatan Bisk and Ali Farhadi and Yejin Choi},
308
+ year={2019},
309
+ eprint={1905.07830},
310
+ archivePrefix={arXiv},
311
+ primaryClass={cs.CL}
312
+ }
313
+ ```
benchmarks/README.md ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Benchmarks
2
+
3
+ Machine-readable measurement records for this model, using the delivered
4
+ `nlp-llm` metadata shape from the ARM Model Optimization Pipeline.
5
+
6
+ These complement the eval block in the model card. The card carries the headline
7
+ numbers in human-readable form; these YAMLs carry the same data with target
8
+ hardware, runtime config, dataset, and benchmark workload context.
9
+
10
+ ## Files
11
+
12
+ - `tinyllama-1-1b-chat-onnx-genai-vivo-x300-int4.yaml` — optimized INT4/INT8 ONNX
13
+ Runtime GenAI measurements on the Vivo X300 smartphone via MLAS + KleidiAI.
14
+ - `tinyllama-1-1b-chat-onnx-genai-vivo-x300-fp32.yaml` — FP32 runtime baseline on
15
+ the same target/workload, from the delivery baseline metadata.
16
+
17
+ ## Reading these
18
+
19
+ Each record has three main areas:
20
+
21
+ - `context.{model,target,runtime,dataset,benchmark}` — everything needed to
22
+ understand the measurement setup.
23
+ - `performance` — LLM runtime metrics: E2E latency percentiles, TTFT, decode
24
+ throughput, model-load / time-to-first-inference, and peak/average memory.
25
+ - `accuracy` — HellaSwag zero-shot accuracy (`acc_norm`, character-normalized).
26
+
27
+ The two records share target/runtime/dataset/workload context. The disambiguator
28
+ is `weight_dtype`.
29
+
30
+ ## Notes specific to this model
31
+
32
+ - This is the `TinyLlama/TinyLlama-1.1B-Chat-v1.0` chat model, re-packed to
33
+ W4A8-dynamic INT4 (GPTQ) with INT8 per-row embeddings and an INT8 LM head via
34
+ the `onnxruntime-genai` model builder (recipe `exp10_kquantlast_emb_int8_asym`).
35
+ - The runtime metrics were measured on the **Vivo X300 premium smartphone**
36
+ (C1-Ultra / C1-Premium / C1-Pro, Android 16 / OriginOS 6), not a server CPU or
37
+ Raspberry Pi. The AWS Graviton G4 cut of this same INT4 model is a separate repo
38
+ (`tinyllama-1-1b-chat-onnx-genai-int4-kquantlast-emb-int8-graviton-g4`); the optimized
39
+ weights are byte-identical across the two targets — only the benchmark records differ.
40
+ - The optimized `model.onnx.data` sidecar is about 728 MB and is gitignored because it
41
+ exceeds GitHub's 100 MB per-file limit. The FP32 baseline ONNX artifact (~4.10 GB) is
42
+ not present in this repository.
43
+
44
+ ## Provenance
45
+
46
+ Source: `models/tinyllama_1_1b_chat_vivo_x300_onnx/` (`metadata.yaml`,
47
+ `baseline_metadata.yaml`, `report.json`, and `huggingface/README.md`). The optimized
48
+ record maps from the delivered `metadata.yaml`; the FP32 baseline maps from the
49
+ delivered `baseline_metadata.yaml`.
benchmarks/tinyllama-1-1b-chat-onnx-genai-vivo-x300-fp32.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: 1.0.0
2
+ task: llm-generative
3
+ created_at: '2026-07-10T13:41:20Z'
4
+ context:
5
+ model:
6
+ id: Arm/tinyllama-1-1b-chat-onnx-genai-int4-kquantlast-emb-int8-vivo-x300
7
+ filename: model.onnx
8
+ base_model_id: TinyLlama/TinyLlama-1.1B-Chat-v1.0
9
+ profile: Baseline
10
+ weight_dtype: fp32
11
+ model_size_mb: 4196.994
12
+ format: onnx
13
+ target:
14
+ name: Vivo X300
15
+ hardware_class: Premium smartphone
16
+ cpu_architecture: arm64
17
+ cpu_model: C1-Ultra, C1-Premium, C1-Pro
18
+ cpu_core_count: 8
19
+ cpu_clock_ghz: 4.21
20
+ system_memory_gb: 16
21
+ os: android
22
+ os_version: Android 16 / OriginOS 6
23
+ runtime:
24
+ name: onnxruntime
25
+ execution_backend: cpu
26
+ version: 1.27.0
27
+ config:
28
+ n_threads: 8
29
+ optimisations:
30
+ - MLAS
31
+ - KleidiAI
32
+ dataset:
33
+ name: HellaSwag
34
+ reference_url: https://huggingface.co/datasets/Rowan/hellaswag
35
+ slice: validation
36
+ sample_count: 8000
37
+ benchmark:
38
+ batch_size: 1
39
+ num_runs: 30
40
+ warmup_runs: 5
41
+ prompt_length_tokens: 154
42
+ generation_length_tokens: 30
43
+ accuracy:
44
+ benchmark_name: HellaSwag
45
+ accuracy_pct: 59.8
46
+ shot_count: 0
47
+ performance:
48
+ end_to_end_latency_ms:
49
+ p50: 4757.487
50
+ p90: 4798.116
51
+ p99: 4804.921
52
+ peak_memory_mb: 4086.28
53
+ average_memory_mb: 4067.23
54
+ ttft_ms: 905.95
55
+ tokens_per_second: 7.82
56
+ model_load_time_ms: 5900.936
57
+ time_to_first_inference_ms: 4414.16
benchmarks/tinyllama-1-1b-chat-onnx-genai-vivo-x300-int4.yaml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: 1.0.0
2
+ task: llm-generative
3
+ created_at: '2026-07-09T02:55:51Z'
4
+ context:
5
+ model:
6
+ id: Arm/tinyllama-1-1b-chat-onnx-genai-int4-kquantlast-emb-int8-vivo-x300
7
+ filename: model.onnx
8
+ base_model_id: TinyLlama/TinyLlama-1.1B-Chat-v1.0
9
+ profile: Arm-Optimized
10
+ weight_dtype: int4
11
+ quantization:
12
+ method: GPTQ
13
+ weight_bits: 4
14
+ activation_bits: 8
15
+ symmetric: false
16
+ mode: dynamic
17
+ weight_granularity: per-group
18
+ variant: W4A8_dyn_emb_int8
19
+ calibration:
20
+ dataset_name: WikiText2
21
+ sample_count: 256
22
+ selection: random
23
+ model_size_mb: 727.861
24
+ format: onnx
25
+ target:
26
+ name: Vivo X300
27
+ hardware_class: Premium smartphone
28
+ cpu_architecture: arm64
29
+ cpu_model: C1-Ultra, C1-Premium, C1-Pro
30
+ cpu_core_count: 8
31
+ cpu_clock_ghz: 4.21
32
+ system_memory_gb: 16
33
+ os: android
34
+ os_version: Android 16 / OriginOS 6
35
+ runtime:
36
+ name: onnxruntime
37
+ execution_backend: cpu
38
+ version: 1.27.0
39
+ config:
40
+ n_threads: 8
41
+ optimisations:
42
+ - MLAS
43
+ - KleidiAI
44
+ dataset:
45
+ name: HellaSwag
46
+ reference_url: https://huggingface.co/datasets/Rowan/hellaswag
47
+ slice: validation
48
+ sample_count: 8000
49
+ benchmark:
50
+ batch_size: 1
51
+ num_runs: 30
52
+ warmup_runs: 5
53
+ prompt_length_tokens: 154
54
+ generation_length_tokens: 30
55
+ accuracy:
56
+ benchmark_name: HellaSwag
57
+ accuracy_pct: 59.0
58
+ shot_count: 0
59
+ performance:
60
+ end_to_end_latency_ms:
61
+ p50: 1047.625
62
+ p90: 1218.37
63
+ p99: 1251.551
64
+ peak_memory_mb: 890.47
65
+ average_memory_mb: 866.41
66
+ delegation_pct: 99.84
67
+ ttft_ms: 510.14
68
+ tokens_per_second: 55.65
69
+ model_load_time_ms: 883.655
70
+ time_to_first_inference_ms: 1009.498
chat_template.jinja ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% for message in messages %}
2
+ {% if message['role'] == 'user' %}
3
+ {{ '<|user|>
4
+ ' + message['content'] + eos_token }}
5
+ {% elif message['role'] == 'system' %}
6
+ {{ '<|system|>
7
+ ' + message['content'] + eos_token }}
8
+ {% elif message['role'] == 'assistant' %}
9
+ {{ '<|assistant|>
10
+ ' + message['content'] + eos_token }}
11
+ {% endif %}
12
+ {% if loop.last and add_generation_prompt %}
13
+ {{ '<|assistant|>' }}
14
+ {% endif %}
15
+ {% endfor %}
config.yaml ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ input:
2
+ shape: [1, "T"]
3
+ dtype: int64
4
+ name: input_ids
5
+ preprocessing:
6
+ - apply_chat_template: chat_template.jinja
7
+ - tokenize:
8
+ tokenizer: tokenizer.json
9
+ add_special_tokens: true
10
+ notes: |
11
+ `T` is the runtime sequence length (variable, up to 2048). `position_ids`
12
+ is NOT exposed as an input — the ONNX Runtime GenAI graph derives positions
13
+ internally. KV-cache I/O is wired up internally by
14
+ `onnxruntime-genai.Generator` and is not exposed at the Python API surface.
15
+
16
+ output:
17
+ format: "Token ids streamed one at a time by onnxruntime-genai.Generator"
18
+ postprocessing:
19
+ decode:
20
+ tokenizer: tokenizer.json
21
+ stop_on:
22
+ - eos_token
23
+ - max_length
24
+
25
+ generation:
26
+ default_max_length: 256
27
+ default_decode_tokens: 30
28
+ do_sample: false
29
+ temperature: 0.0
30
+ top_p: 1.0
31
+ intra_op_num_threads: 4
32
+
33
+ model:
34
+ format: onnx
35
+ graph_layout: onnxruntime-genai
36
+ fused_attention: GroupQueryAttention
37
+ num_layers: 22
38
+ hidden_size: 2048
39
+ num_attention_heads: 32
40
+ num_kv_heads: 4
41
+ head_size: 64
42
+ vocab_size: 32000
43
+ max_context_length: 2048
44
+
45
+ quantization:
46
+ weight_dtype: int4
47
+ weight_symmetric: false
48
+ weight_group_size: 32
49
+ weight_calibration_algorithm: GPTQ # per-group (scale, zero_point) fit by GPTQ
50
+ weight_algo_config: k_quant_last # LM-head protection (see last_layer_dtype)
51
+ last_layer_dtype: int8 # final LM-head projection kept INT8
52
+ last_layer_protection: k_quant_last
53
+ activation_dtype: int8
54
+ activation_mode: per_token_dynamic
55
+ activation_symmetric: false
56
+ embedding_dtype: int8
57
+ embedding_granularity: per_row # one (scale, zero_point) per vocabulary token
58
+ scheme: W4A8_dyn_emb_int8_lmhead_int8
59
+
60
+ runtime:
61
+ execution_provider: cpu
62
+ mlas: true
63
+ kleidiai: true
64
+ onnxruntime_version: 1.27.0
example.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Minimal inference example for TinyLlama-1.1B-Chat exp10 W4A8 (ONNX Runtime GenAI).
2
+
3
+ Loads the ONNX Runtime GenAI model + tokenizer + Jinja chat template *from this
4
+ folder* and runs a single chat-style generation, then saves the response to
5
+ ``predictions.json`` next to this script. Requires:
6
+
7
+ onnxruntime>=1.22
8
+ onnxruntime-genai>=0.14.0 # Linux-aarch64 wheels available since 0.14.0
9
+ tokenizers # HF tokenizers library (loads tokenizer.json)
10
+ jinja2 # renders the bundled chat template
11
+
12
+ The folder is expected to contain the standard GenAI bundle:
13
+
14
+ model.onnx
15
+ model.onnx.data # external-data weights side-car
16
+ genai_config.json
17
+ tokenizer.json
18
+ tokenizer_config.json
19
+ chat_template.jinja # TinyLlama Zephyr-style chat template
20
+
21
+ Run it from inside this directory:
22
+
23
+ python example.py
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import json
29
+ from pathlib import Path
30
+
31
+ import onnxruntime_genai as og
32
+ from jinja2 import Environment
33
+ from tokenizers import Tokenizer
34
+
35
+
36
+ # -- Configuration -------------------------------------------------------------
37
+ # HellaSwag-style commonsense continuation prompt. Small chat models
38
+ # (~1B) generate cleanest output on well-scoped everyday scenarios (see
39
+ # TinyLlama's 59% HellaSwag acc_norm) vs open-ended factual prose which
40
+ # tends to hallucinate and loop.
41
+ DEFAULT_PROMPT = (
42
+ "A woman is in the kitchen making pancakes. She pours the batter onto "
43
+ "a hot pan and waits for bubbles to appear on the surface. Once the "
44
+ "bubbles pop, she"
45
+ )
46
+ MAX_LENGTH = 256 # absolute token budget (prompt + decoded)
47
+ DO_SAMPLE = False # greedy decode for reproducibility
48
+ TEMPERATURE = 0.0 # ignored unless do_sample=True
49
+
50
+
51
+ def _raise_exception(msg: str) -> None:
52
+ """Bridge for the chat template's ``raise_exception`` helper."""
53
+ raise RuntimeError(msg)
54
+
55
+
56
+ def render_chat_template(
57
+ template_path: Path, bundle_dir: Path, user_prompt: str
58
+ ) -> str:
59
+ """Render ``chat_template.jinja`` with a single user turn.
60
+
61
+ Reads BOS/EOS tokens from ``tokenizer_config.json`` so the rendered string
62
+ matches the actual tokenizer's special tokens. ``add_generation_prompt=True``
63
+ appends the assistant header so the model continues from there.
64
+ """
65
+ template_src = template_path.read_text(encoding="utf-8")
66
+ with (bundle_dir / "tokenizer_config.json").open() as f:
67
+ tok_cfg = json.load(f)
68
+
69
+ env = Environment(trim_blocks=True, lstrip_blocks=True, autoescape=False)
70
+ env.globals["raise_exception"] = _raise_exception
71
+ template = env.from_string(template_src)
72
+
73
+ return template.render(
74
+ messages=[{"role": "user", "content": user_prompt}],
75
+ bos_token=tok_cfg.get("bos_token", "<s>"),
76
+ eos_token=tok_cfg.get("eos_token", "</s>"),
77
+ add_generation_prompt=True,
78
+ )
79
+
80
+
81
+ def load_model(bundle_dir: Path) -> tuple[og.Model, Tokenizer]:
82
+ """Load the ONNX Runtime GenAI model and the bundled HF tokenizer."""
83
+ model = og.Model(str(bundle_dir))
84
+ tokenizer = Tokenizer.from_file(str(bundle_dir / "tokenizer.json"))
85
+ return model, tokenizer
86
+
87
+
88
+ def generate(
89
+ model: og.Model,
90
+ tokenizer: Tokenizer,
91
+ chat_prompt: str,
92
+ ) -> tuple[str, int, int]:
93
+ """Run greedy decode for one chat turn.
94
+
95
+ Returns ``(decoded_response, prompt_token_count, generated_token_count)``.
96
+ """
97
+ # The chat template already contains the BOS marker; don't double-add it.
98
+ input_ids = tokenizer.encode(chat_prompt, add_special_tokens=False).ids
99
+
100
+ params = og.GeneratorParams(model)
101
+ params.set_search_options(
102
+ max_length=MAX_LENGTH,
103
+ do_sample=DO_SAMPLE,
104
+ temperature=TEMPERATURE,
105
+ )
106
+
107
+ generator = og.Generator(model, params)
108
+ generator.append_tokens(input_ids)
109
+ while not generator.is_done():
110
+ generator.generate_next_token()
111
+
112
+ full_ids = list(generator.get_sequence(0))
113
+ response_ids = full_ids[len(input_ids) :]
114
+ decoded = tokenizer.decode(response_ids, skip_special_tokens=True)
115
+ return decoded, len(input_ids), len(response_ids)
116
+
117
+
118
+ def save_results(
119
+ bundle_dir: Path,
120
+ user_prompt: str,
121
+ response: str,
122
+ prompt_tokens: int,
123
+ generated_tokens: int,
124
+ ) -> Path:
125
+ """Persist the prompt/response pair as ``predictions.json``."""
126
+ output_path = bundle_dir / "predictions.json"
127
+ payload = {
128
+ "prompt": user_prompt,
129
+ "response": response,
130
+ "prompt_tokens": prompt_tokens,
131
+ "generated_tokens": generated_tokens,
132
+ "max_length": MAX_LENGTH,
133
+ "do_sample": DO_SAMPLE,
134
+ "temperature": TEMPERATURE,
135
+ }
136
+ output_path.write_text(json.dumps(payload, indent=2, ensure_ascii=False))
137
+ return output_path
138
+
139
+
140
+ def main() -> None:
141
+ bundle_dir = Path(__file__).resolve().parent
142
+ template_path = bundle_dir / "chat_template.jinja"
143
+
144
+ print(f"Loading model from: {bundle_dir}")
145
+ model, tokenizer = load_model(bundle_dir)
146
+
147
+ chat_prompt = render_chat_template(template_path, bundle_dir, DEFAULT_PROMPT)
148
+ print(f"\nPrompt: {DEFAULT_PROMPT}\n")
149
+ print("Generating...")
150
+ response, prompt_tokens, generated_tokens = generate(model, tokenizer, chat_prompt)
151
+
152
+ print("\n--- Response ---")
153
+ print(response)
154
+ print("--- /Response ---")
155
+ print(
156
+ f"\nPrompt tokens: {prompt_tokens} | " f"Generated tokens: {generated_tokens}"
157
+ )
158
+
159
+ saved = save_results(
160
+ bundle_dir, DEFAULT_PROMPT, response, prompt_tokens, generated_tokens
161
+ )
162
+ print(f"Saved: {saved}")
163
+
164
+
165
+ if __name__ == "__main__":
166
+ main()
genai_config.json ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": {
3
+ "bos_token_id": 1,
4
+ "context_length": 2048,
5
+ "decoder": {
6
+ "session_options": {
7
+ "log_id": "onnxruntime-genai",
8
+ "provider_options": []
9
+ },
10
+ "filename": "model.onnx",
11
+ "head_size": 64,
12
+ "hidden_size": 2048,
13
+ "inputs": {
14
+ "input_ids": "input_ids",
15
+ "attention_mask": "attention_mask",
16
+ "past_key_names": "past_key_values.%d.key",
17
+ "past_value_names": "past_key_values.%d.value"
18
+ },
19
+ "outputs": {
20
+ "logits": "logits",
21
+ "present_key_names": "present.%d.key",
22
+ "present_value_names": "present.%d.value"
23
+ },
24
+ "num_attention_heads": 32,
25
+ "num_hidden_layers": 22,
26
+ "num_key_value_heads": 4
27
+ },
28
+ "eos_token_id": 2,
29
+ "pad_token_id": 0,
30
+ "type": "llama",
31
+ "vocab_size": 32000
32
+ },
33
+ "search": {
34
+ "diversity_penalty": 0.0,
35
+ "do_sample": false,
36
+ "early_stopping": true,
37
+ "length_penalty": 1.0,
38
+ "max_length": 2048,
39
+ "min_length": 0,
40
+ "no_repeat_ngram_size": 0,
41
+ "num_beams": 1,
42
+ "num_return_sequences": 1,
43
+ "past_present_share_buffer": true,
44
+ "repetition_penalty": 1.0,
45
+ "temperature": 1.0,
46
+ "top_k": 50,
47
+ "top_p": 1.0
48
+ }
49
+ }
generation_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 1,
3
+ "eos_token_id": 2,
4
+ "max_length": 2048,
5
+ "pad_token_id": 0,
6
+ "transformers_version": "4.35.0"
7
+ }
metadata.yaml ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: 1.0.0
2
+ task: llm-generative
3
+ created_at: '2026-07-09T02:55:51Z'
4
+ context:
5
+ model:
6
+ id: Arm/tinyllama-1-1b-chat-onnx-genai-int4-kquantlast-emb-int8-vivo-x300
7
+ base_model_id: TinyLlama/TinyLlama-1.1B-Chat-v1.0
8
+ profile: Arm-Optimized
9
+ weight_dtype: int4
10
+ quantization:
11
+ method: GPTQ
12
+ weight_bits: 4
13
+ activation_bits: 8
14
+ symmetric: false
15
+ mode: dynamic
16
+ weight_granularity: per-group
17
+ calibration:
18
+ dataset_name: WikiText2
19
+ sample_count: 256
20
+ selection: random
21
+ model_size_mb: 727.861
22
+ parameter_count: 1100179456
23
+ format: onnx
24
+ filename: model.onnx
25
+ target:
26
+ name: Vivo X300
27
+ hardware_class: Premium smartphone
28
+ cpu_architecture: arm64
29
+ cpu_model: C1-Ultra, C1-Premium, C1-Pro
30
+ cpu_core_count: 8
31
+ system_memory_gb: 16
32
+ os: android
33
+ os_version: Android 16 / OriginOS 6
34
+ runtime:
35
+ name: onnxruntime
36
+ execution_backend: cpu
37
+ config:
38
+ optimisations:
39
+ - MLAS
40
+ - KleidiAI
41
+ n_threads: 8
42
+ version: 1.27.0
43
+ dataset:
44
+ name: HellaSwag
45
+ sample_count: 8000
46
+ reference_url: https://huggingface.co/datasets/Rowan/hellaswag
47
+ benchmark:
48
+ batch_size: 1
49
+ num_runs: 30
50
+ warmup_runs: 5
51
+ prompt_length_tokens: 154
52
+ generation_length_tokens: 30
53
+ performance:
54
+ end_to_end_latency_ms:
55
+ p50: 1047.625
56
+ p90: 1218.37
57
+ p99: 1251.551
58
+ model_load_time_ms: 883.655
59
+ time_to_first_inference_ms: 1009.498
60
+ ttft_ms: 510.14
61
+ tokens_per_second: 55.65
62
+ peak_memory_mb: 890.47
63
+ average_memory_mb: 866.41
64
+ delegation_pct: 99.84
65
+ accuracy:
66
+ benchmark_name: HellaSwag
67
+ accuracy_pct: 59.0
68
+ shot_count: 0
predictions.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "prompt": "A woman is in the kitchen making pancakes. She pours the batter onto a hot pan and waits for bubbles to appear on the surface. Once the bubbles pop, she",
3
+ "response": "A man is in the kitchen making pancakes. He pours the batter onto a hot pan and waits for bubbles to appear on the surface. Once the bubbles pop, he uses a spatula to smooth out the surface of the pancake and then flips it over.",
4
+ "prompt_tokens": 56,
5
+ "generated_tokens": 64,
6
+ "max_length": 256,
7
+ "do_sample": false,
8
+ "temperature": 0.0
9
+ }
special_tokens_map.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "</s>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "</s>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "unk_token": {
24
+ "content": "<unk>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ }
30
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9e556afd44213b6bd1be2b850ebbbd98f5481437a8021afaf58ee7fb1818d347
3
+ size 499723
tokenizer_config.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": null,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<s>",
5
+ "clean_up_tokenization_spaces": false,
6
+ "eos_token": "</s>",
7
+ "is_local": true,
8
+ "local_files_only": false,
9
+ "model_max_length": 2048,
10
+ "pad_token": "</s>",
11
+ "padding_side": "right",
12
+ "sp_model_kwargs": {},
13
+ "tokenizer_class": "LlamaTokenizer",
14
+ "unk_token": "<unk>",
15
+ "use_default_system_prompt": false
16
+ }