litert-community/LFM2.5-1.2B-Instruct

Model

LiteRT is Google's on-device runtime, the new name for TensorFlow Lite (Android: com.google.ai.edge.litert:litert), and litert-torch, the renamed ai-edge-torch, is its PyTorch converter: a PyTorch model converted unmodified with litert_torch.convert matched the original to 4e-7 on a Galaxy S26 (measured, LiteRT 2.2.0, Android 16, 2026-09-05).

4

22 commits

7 linked in READMEs

updated Sep 21, 2026

See the code

README

LiteRT is Google's on-device runtime, the new name for TensorFlow Lite (Android: com.google.ai.edge.litert:litert), and litert-torch, the renamed ai-edge-torch, is its PyTorch converter: a PyTorch model converted unmodified with litert_torch.convert matched the original to 4e-7 on a Galaxy S26 (measured, LiteRT 2.2.0, Android 16, 2026-09-05).

Measured on device (edge-compat, lfm2.5-1.2b-instruct-int4): Galaxy S26 · LiteRT-LM 0.16.0 · GPU · did not run: engine_create_failed (2026-08-23); Raspberry Pi 5 · LiteRT-LM 0.16.1 · CPU, 4 threads · decode 9.3 tok/s · prefill 54 tok/s · TTFT 4.84 s (2026-09-01). Record: https://github.com/john-rocky/edge-compat/blob/main/cards/lfm2.5-1.2b-instruct-int4/CARD.md

Measured on device (edge-compat, lfm2.5-1.2b-instruct-int8): Galaxy S26 · LiteRT-LM 0.16.0 · CPU · decode 41.0 tok/s · prefill 491 tok/s · TTFT 440 ms (2026-09-05); Pixel 8a · LiteRT-LM 0.16.0 · CPU · decode 20.4 tok/s · prefill 143 tok/s · TTFT 1.48 s (2026-09-05); Raspberry Pi 5 · LiteRT-LM 0.16.1 · CPU, 4 threads · decode 7.0 tok/s · prefill 75 tok/s · TTFT 3.56 s (2026-09-01). Record: https://github.com/john-rocky/edge-compat/blob/main/cards/lfm2.5-1.2b-instruct-int8/CARD.md

LFM2.5-1.2B-Instruct — LiteRT-LM

LiquidAI/LFM2.5-1.2B-Instruct converted to the LiteRT-LM (.litertlm) format for on-device inference with Google's LiteRT-LM runtime (requires litert-lm ≥ 0.14 / a recent AI Edge Gallery).

Update (2026-08-04): the .litertlm files were updated in place to add the ExecutorMetadata section that litert-lm ≥ 0.15 requires to bind the hybrid conv/attention state buffers (without it, 0.15 fails at inference with missing some output TensorBuffers). Weights and graph are byte-identical to the original release, and the files continue to run on litert-lm 0.14.

LFM2.5-1.2B-Instruct is Liquid AI's flagship on-device model: a hybrid architecture mixing gated short-convolution blocks with grouped-query attention. Per the base model card it outperforms Qwen3-1.7B and Gemma 3 1B on knowledge and instruction-following benchmarks at a smaller footprint.

Load it by id on Android (hfmodels)

hfmodels is an independent, third-party Android library that takes this repository's id, downloads and verifies the .litertlm file, and opens a LiteRT-LM session; this repository ships an hfmodels.json that declares its files and profiles.

// app/build.gradle.kts (minSdk 31)
dependencies { implementation("io.github.john-rocky.hfmodels:hfmodels-litertlm:0.1.1") }
val models = HfModels(applicationContext)
val chat = models.fromPretrained(ModelRef("litert-community/LFM2.5-1.2B-Instruct"), Tasks.Chat)
val session = chat.createConversation(ConversationConfig(systemInstruction = Contents.of("You are a helpful assistant.")))
session.stream(Contents.of(Content.Text("What is 17 + 25? Answer briefly."))).collect { message -> append(message) }
withContext(NonCancellable) { chat.closeAndJoin() }

Verified on a Pixel 8a (Android 16, LiteRT-LM 0.16.1, 2026-09-07) on the int4_gpu variant's gpu and cpu profiles through the library's own catalog gate (a real download from this repository with Range resume and a sha256 check, then one text turn).

FileRecipeSizeGSM8K (n=100)
LFM2.5-1.2B-Instruct_int8.litertlmint8 dynamic (linears + convs + embedding)1.25 GB81% (bf16 reference: 79%)
LFM2.5-1.2B-Instruct_int4.litertlmint4 blockwise-32 + OCTAV linears, int8 embedding, convs float736 MB72%
LFM2.5-1.2B-Instruct_int4_gpu.litertlmsame int4 recipe, re-exported so it runs on the GPU736 MB= int4 (A/B in notes)

2026-09-21: chat template updated to accept the 0.18 content-parts form (string form unchanged); weights, tokenizer and executor metadata byte-identical.

Context (KV cache)4096 max (see --max-num-tokens note)
BackendCPU for every file; the _int4_gpu file also runs on the GPU with litert-lm ≥ 0.16.0 — Android OpenCL, macOS, and iOS Metal, all verified by generation. On iOS set maxNumTokens to 1024 (see the iPhone section — a mismatched value breaks engine creation)
Templatebundled — full chat template incl. tool-list support + <think> channel declaration
Base modelLiquidAI/LFM2.5-1.2B-Instruct (LFM Open License v1.0)

Quality — GSM8K

GSM8K, greedy, 0-shot chain-of-thought, max-tokens 1024, n=100, same harness for all rows:

ConfigurationGSM8K
PyTorch bf16 (reference)79%
LiteRT int8 (this repo)81%
LiteRT int4-b32 OCTAV (this repo)72%

The int8 file is at full parity with the PyTorch reference (+2pt, within noise). Both files pass an 8-question sanity gate (7/8, zero degenerate outputs). The int4 file trades −7pt for a 41% smaller download.

Usage

litert-lm run ./LFM2.5-1.2B-Instruct_int8.litertlm --prompt "Explain what a hybrid conv-attention LLM is in two sentences."

The bundle carries the tokenizer and the full chat template (ChatML-style <|im_start|>…<|im_end|> with tool-calling support). Generation stops cleanly at <|im_end|>.

--max-num-tokens tip: decode speed drops as the token budget grows (int8 decode: 101 tok/s at 1024 → 77 tok/s at 4096 on an M4 Max) — set it to the smallest value your use case needs (1024 is a good chat default; the file allows up to 4096).

Performance

litert-lm benchmark (litert-lm 0.15.0), CPU backend, Apple M4 Max, -p 256 -d 256 --runs 3 (the tool averages three iterations), warm-up run discarded, otherwise idle machine: decode depends strongly on the KV budget, so both settings are listed:

Variant--max-num-tokensPrefill (256)DecodeTTFT
int810241592 tok/s93.1 tok/s0.17 s
int41024381 tok/s109.4 tok/s0.68 s
int840961121 tok/s78.9 tok/s0.24 s
int44096343 tok/s74.9 tok/s0.76 s

On a Pixel 8a (Tensor G3, CPU backend, measured in AI Edge Gallery): int8 decodes at ~19 tok/s and int4 at ~31 tok/s — on phone-class memory bandwidth the int4 file is ~1.7× faster as well as 41% smaller, so prefer int4 on mid-range devices unless you need the last few GSM8K points.

GPU — the _int4_gpu file

Pixel 8a (Tensor G3), litert_lm_main built from the litert-lm v0.16.0 release tag, 263-token prompt, generation capped at 256, 3 runs per backend:

BackendPrefill (263 tok)DecodeTTFT
GPU (OpenCL)188–193 tok/s21.0–21.2 tok/s1.41–1.44 s
CPU38–54 tok/s15.2–24.3 tok/s4.9–7.0 s

On phone-class hardware the GPU's win is prefill and time-to-first-token (3–6× both); decode is bandwidth-bound and roughly a wash, so long prompts gain far more than long answers. The CPU rows spread because the phone throttles across a run series; the GPU rows repeat to within 2%.

Apple M4 Max (litert-lm benchmark --cache no, litert-lm 0.16.0, -p 256 -d 256 --runs 3, otherwise idle machine; both backends were verified to generate correct text before these numbers were quoted):

BackendPrefill (256)DecodeTTFT
GPU3765 tok/s318.3 tok/s0.07 s
CPU337.0 tok/s80.5 tok/s0.78 s

On a desktop GPU the gain is across the board — roughly 11× prefill and 4× decode against the same file on CPU.

The hybrid short-conv blocks are what make a 1.2B decode at ~100 tok/s on CPU — faster than same-size pure-attention models. Long prompts prefill through the large (up to 1024-token) signatures at >1500 tok/s.

GPU — Galaxy S26 (Snapdragon 8 Elite Gen 5)

Galaxy S26 (SM-S942Q / SM8850, Android 16), litert_lm_main from litert-lm 0.16.0, the _int4_gpu file, 19-token prompt, one run per backend:

BackendPrefill (19 tok)DecodeTTFTInit
GPU (OpenCL)80.3 tok/s24.7 tok/s0.28 s15.0 s
CPU (XNNPACK)10.3 tok/s24.1 tok/s1.89 s6.5 s

The prompt was 19 tokens, so read the prefill column as a floor rather than a throughput figure — at that length the fixed per-call cost dominates. The 263-token Pixel 8a rows above are the throughput measurement. Decode is a wash (24.7 against 24.1), which is what bandwidth-bound decode looks like; the GPU's win here is time-to-first-token, 6.7×. The GPU took the whole graph, 542 of 542 ops on LITERT_CL; on CPU, XNNPACK took 469 of 542.

GPU — iPhone 17 Pro (iOS Metal)

The engine-creation failure previously tracked in LiteRT-LM#3129 turned out to be a context-sizing issue on the integration side, not a runtime bug. The Metal delegate compiles its kernels against the KV cache that maxNumTokens pre-allocates; a value that does not match this file's exported plan (our test app derived ~650) makes engine creation fail with a shader-compile error. On iOS Metal, set maxNumTokens to 1024 (Swift EngineConfig(maxNumTokens:), C API litert_lm_engine_settings_set_max_num_tokens).

iPhone 17 Pro, litert-lm v0.16.0 xcframework, maxNumTokens 1024, single run, device charging: decode 67.7 tok/s (the int4 file on CPU on the same phone: 52.6), TTFT 109 ms on a short prompt, prefill 1,982 tok/s at p=128, peak ~470 MB. All Metal kernels compile, generation is coherent, and the file scores the same 8-question sanity gate as on CPU (7/8).

Only the _int4_gpu file loads on the GPU. LFM2.5-1.2B-Instruct_int4.litertlm delegates 536 of its 579 ops and then fails to create the engine, because the remaining 43 do not lower (GATHER_ND: Operation is not supported, plus several INT64 tensors). Use _int4_gpu on the GPU backend and _int4 or _int8 on CPU.

Run on Android

Install a recent Google AI Edge Gallery (1.0.16+ imports .litertlm directly from Hugging Face), import this repo (or adb push a file and use local import), select the CPU backend, and chat. GPU acceleration needs the _int4_gpu file and litert-lm ≥ 0.16.0 (litert_lm_main --backend=gpu, or the SDKs); the Gallery bundles its own runtime, which may lag that version — if its GPU toggle fails there, use CPU.

⚠ Gallery's import dialog defaults to CPU-only. Scroll it to Compatible accelerators and tick GPU at import time; a model already imported has to be deleted and re-imported. Nothing in the bundle sets this. Full recipe: Running converted models on GPU (Android).

Conversion notes

Converted with released litert-torch 0.9.1 (which ships the lfm2 hybrid model support) and packaged for litert-lm ≥ 0.14, with one exporter patch: the stock LFM2 short-conv block saves its conv state from the last columns of the prefill chunk, which are padding whenever the prompt does not exactly fill a prefill signature — corrupting the first generated token of nearly every reply. The patch derives the valid length from the attention mask in-graph and gathers the conv state from the last valid columns instead; with it, engine output is token-identical to an exact per-token reference loop at every prompt length. Multi-length prefill signatures (1–1024) are exported so the runtime can pick tight chunks.

Quantization targets fully-connected + embedding ops (plus convs in the int8 file, quantized at export time); post-hoc int8 of the convs with ai-edge-quantizer breaks generation — quantize convs only at export time.

Why there is a separate _int4_gpu file. The exporter patch above reads the chunk's valid length with index_select and a mask sum, which lower to GATHER_ND and INT64 ops, and GPU delegates reject both — the CPU-only files take 536 of 579 operations on the GPU and the runtime then refuses the partial split. litert-torch 0.9.2 fixed the underlying conv-state bug upstream using valid-token masking and a one-hot matmul state select, which emits neither op. _int4_gpu is that export: litert-torch 0.9.3 + litert-converter 0.3.1, the same int4 recipe and the same weights as the int4 file, plus the executor-metadata section litert-lm ≥ 0.15 needs. It delegates fully on Android OpenCL — 501/501 and 519/519 nodes, zero rejected ops — and runs on the macOS GPU backend. Quality is unchanged: run head to head against the published int4 file on identical prompts, decoding and scoring, both score 38/50 on GSM8K (CPU, n=50), and the GPU file passes an 8-question sanity gate on both backends. The CPU-only files are left exactly as they are rather than replaced, so nothing changes for anyone already using them.

Raspberry Pi 5 (CPU)

Measured on a Raspberry Pi 5 Model B Rev 1.1 (8 GB, Raspberry Pi OS 64-bit) with litert-lm benchmark 0.16.1: CPU backend, 4 threads, 256 prefill + 256 decode tokens, --cache memory (the compile cache lives and dies with the process, so every invocation compiles the model from scratch; nothing is reused between runs), one warm-up plus one timed iteration per invocation, 3 invocations per file with cooldown in between. Values are the median across invocations (min–max in parentheses). No thermal throttling occurred during these runs (vcgencmd get_throttled stayed 0x0). Every file listed produced coherent text in a real generation on this backend before its numbers were recorded.

FilePrefill (tok/s)Decode (tok/s)TTFTPeak RSS
LFM2.5-1.2B-Instruct_int4.litertlm54.1 (53.7–54.2)9.3 (9.3–9.3)4.8 s1.4 GB
LFM2.5-1.2B-Instruct_int4_gpu.litertlm54.6 (53.5–54.6)9.3 (9.3–9.3)4.8 s1.4 GB
LFM2.5-1.2B-Instruct_int8.litertlm75.0 (74.5–75.7)7.0 (7.0–7.1)3.6 s1.9 GB

License and changes

Distributed under the LFM Open License v1.0 (see LICENSE, inherited from the base model). Note the license's commercial-use limitation for organizations above US$10M annual revenue. Changes from the original work: weights converted from safetensors bf16 to LiteRT flatbuffers and quantized as described above; tokenizer and chat template repackaged unmodified into the .litertlm bundle; exporter conv-state fix as described in Conversion notes. This repository is a community conversion and is not affiliated with Liquid AI.

edge
hybrid
liquid
litert
litert-lm
litertlm
on-device
text-generation

litert-community/LFM2.5-1.2B-Instruct

Model

LiteRT is Google's on-device runtime, the new name for TensorFlow Lite (Android: com.google.ai.edge.litert:litert), and litert-torch, the renamed ai-edge-torch, is its PyTorch converter: a PyTorch model converted unmodified with litert_torch.convert matched the original to 4e-7 on a Galaxy S26 (measured, LiteRT 2.2.0, Android 16, 2026-09-05).

4

22 commits

7 linked in READMEs

updated Sep 21, 2026

See the code

README

LiteRT is Google's on-device runtime, the new name for TensorFlow Lite (Android: com.google.ai.edge.litert:litert), and litert-torch, the renamed ai-edge-torch, is its PyTorch converter: a PyTorch model converted unmodified with litert_torch.convert matched the original to 4e-7 on a Galaxy S26 (measured, LiteRT 2.2.0, Android 16, 2026-09-05).

Measured on device (edge-compat, lfm2.5-1.2b-instruct-int4): Galaxy S26 · LiteRT-LM 0.16.0 · GPU · did not run: engine_create_failed (2026-08-23); Raspberry Pi 5 · LiteRT-LM 0.16.1 · CPU, 4 threads · decode 9.3 tok/s · prefill 54 tok/s · TTFT 4.84 s (2026-09-01). Record: https://github.com/john-rocky/edge-compat/blob/main/cards/lfm2.5-1.2b-instruct-int4/CARD.md

Measured on device (edge-compat, lfm2.5-1.2b-instruct-int8): Galaxy S26 · LiteRT-LM 0.16.0 · CPU · decode 41.0 tok/s · prefill 491 tok/s · TTFT 440 ms (2026-09-05); Pixel 8a · LiteRT-LM 0.16.0 · CPU · decode 20.4 tok/s · prefill 143 tok/s · TTFT 1.48 s (2026-09-05); Raspberry Pi 5 · LiteRT-LM 0.16.1 · CPU, 4 threads · decode 7.0 tok/s · prefill 75 tok/s · TTFT 3.56 s (2026-09-01). Record: https://github.com/john-rocky/edge-compat/blob/main/cards/lfm2.5-1.2b-instruct-int8/CARD.md

LFM2.5-1.2B-Instruct — LiteRT-LM

LiquidAI/LFM2.5-1.2B-Instruct converted to the LiteRT-LM (.litertlm) format for on-device inference with Google's LiteRT-LM runtime (requires litert-lm ≥ 0.14 / a recent AI Edge Gallery).

Update (2026-08-04): the .litertlm files were updated in place to add the ExecutorMetadata section that litert-lm ≥ 0.15 requires to bind the hybrid conv/attention state buffers (without it, 0.15 fails at inference with missing some output TensorBuffers). Weights and graph are byte-identical to the original release, and the files continue to run on litert-lm 0.14.

LFM2.5-1.2B-Instruct is Liquid AI's flagship on-device model: a hybrid architecture mixing gated short-convolution blocks with grouped-query attention. Per the base model card it outperforms Qwen3-1.7B and Gemma 3 1B on knowledge and instruction-following benchmarks at a smaller footprint.

Load it by id on Android (hfmodels)

hfmodels is an independent, third-party Android library that takes this repository's id, downloads and verifies the .litertlm file, and opens a LiteRT-LM session; this repository ships an hfmodels.json that declares its files and profiles.

// app/build.gradle.kts (minSdk 31)
dependencies { implementation("io.github.john-rocky.hfmodels:hfmodels-litertlm:0.1.1") }
val models = HfModels(applicationContext)
val chat = models.fromPretrained(ModelRef("litert-community/LFM2.5-1.2B-Instruct"), Tasks.Chat)
val session = chat.createConversation(ConversationConfig(systemInstruction = Contents.of("You are a helpful assistant.")))
session.stream(Contents.of(Content.Text("What is 17 + 25? Answer briefly."))).collect { message -> append(message) }
withContext(NonCancellable) { chat.closeAndJoin() }

Verified on a Pixel 8a (Android 16, LiteRT-LM 0.16.1, 2026-09-07) on the int4_gpu variant's gpu and cpu profiles through the library's own catalog gate (a real download from this repository with Range resume and a sha256 check, then one text turn).

FileRecipeSizeGSM8K (n=100)
LFM2.5-1.2B-Instruct_int8.litertlmint8 dynamic (linears + convs + embedding)1.25 GB81% (bf16 reference: 79%)
LFM2.5-1.2B-Instruct_int4.litertlmint4 blockwise-32 + OCTAV linears, int8 embedding, convs float736 MB72%
LFM2.5-1.2B-Instruct_int4_gpu.litertlmsame int4 recipe, re-exported so it runs on the GPU736 MB= int4 (A/B in notes)

2026-09-21: chat template updated to accept the 0.18 content-parts form (string form unchanged); weights, tokenizer and executor metadata byte-identical.

Context (KV cache)4096 max (see --max-num-tokens note)
BackendCPU for every file; the _int4_gpu file also runs on the GPU with litert-lm ≥ 0.16.0 — Android OpenCL, macOS, and iOS Metal, all verified by generation. On iOS set maxNumTokens to 1024 (see the iPhone section — a mismatched value breaks engine creation)
Templatebundled — full chat template incl. tool-list support + <think> channel declaration
Base modelLiquidAI/LFM2.5-1.2B-Instruct (LFM Open License v1.0)

Quality — GSM8K

GSM8K, greedy, 0-shot chain-of-thought, max-tokens 1024, n=100, same harness for all rows:

ConfigurationGSM8K
PyTorch bf16 (reference)79%
LiteRT int8 (this repo)81%
LiteRT int4-b32 OCTAV (this repo)72%

The int8 file is at full parity with the PyTorch reference (+2pt, within noise). Both files pass an 8-question sanity gate (7/8, zero degenerate outputs). The int4 file trades −7pt for a 41% smaller download.

Usage

litert-lm run ./LFM2.5-1.2B-Instruct_int8.litertlm --prompt "Explain what a hybrid conv-attention LLM is in two sentences."

The bundle carries the tokenizer and the full chat template (ChatML-style <|im_start|>…<|im_end|> with tool-calling support). Generation stops cleanly at <|im_end|>.

--max-num-tokens tip: decode speed drops as the token budget grows (int8 decode: 101 tok/s at 1024 → 77 tok/s at 4096 on an M4 Max) — set it to the smallest value your use case needs (1024 is a good chat default; the file allows up to 4096).

Performance

litert-lm benchmark (litert-lm 0.15.0), CPU backend, Apple M4 Max, -p 256 -d 256 --runs 3 (the tool averages three iterations), warm-up run discarded, otherwise idle machine: decode depends strongly on the KV budget, so both settings are listed:

Variant--max-num-tokensPrefill (256)DecodeTTFT
int810241592 tok/s93.1 tok/s0.17 s
int41024381 tok/s109.4 tok/s0.68 s
int840961121 tok/s78.9 tok/s0.24 s
int44096343 tok/s74.9 tok/s0.76 s

On a Pixel 8a (Tensor G3, CPU backend, measured in AI Edge Gallery): int8 decodes at ~19 tok/s and int4 at ~31 tok/s — on phone-class memory bandwidth the int4 file is ~1.7× faster as well as 41% smaller, so prefer int4 on mid-range devices unless you need the last few GSM8K points.

GPU — the _int4_gpu file

Pixel 8a (Tensor G3), litert_lm_main built from the litert-lm v0.16.0 release tag, 263-token prompt, generation capped at 256, 3 runs per backend:

BackendPrefill (263 tok)DecodeTTFT
GPU (OpenCL)188–193 tok/s21.0–21.2 tok/s1.41–1.44 s
CPU38–54 tok/s15.2–24.3 tok/s4.9–7.0 s

On phone-class hardware the GPU's win is prefill and time-to-first-token (3–6× both); decode is bandwidth-bound and roughly a wash, so long prompts gain far more than long answers. The CPU rows spread because the phone throttles across a run series; the GPU rows repeat to within 2%.

Apple M4 Max (litert-lm benchmark --cache no, litert-lm 0.16.0, -p 256 -d 256 --runs 3, otherwise idle machine; both backends were verified to generate correct text before these numbers were quoted):

BackendPrefill (256)DecodeTTFT
GPU3765 tok/s318.3 tok/s0.07 s
CPU337.0 tok/s80.5 tok/s0.78 s

On a desktop GPU the gain is across the board — roughly 11× prefill and 4× decode against the same file on CPU.

The hybrid short-conv blocks are what make a 1.2B decode at ~100 tok/s on CPU — faster than same-size pure-attention models. Long prompts prefill through the large (up to 1024-token) signatures at >1500 tok/s.

GPU — Galaxy S26 (Snapdragon 8 Elite Gen 5)

Galaxy S26 (SM-S942Q / SM8850, Android 16), litert_lm_main from litert-lm 0.16.0, the _int4_gpu file, 19-token prompt, one run per backend:

BackendPrefill (19 tok)DecodeTTFTInit
GPU (OpenCL)80.3 tok/s24.7 tok/s0.28 s15.0 s
CPU (XNNPACK)10.3 tok/s24.1 tok/s1.89 s6.5 s

The prompt was 19 tokens, so read the prefill column as a floor rather than a throughput figure — at that length the fixed per-call cost dominates. The 263-token Pixel 8a rows above are the throughput measurement. Decode is a wash (24.7 against 24.1), which is what bandwidth-bound decode looks like; the GPU's win here is time-to-first-token, 6.7×. The GPU took the whole graph, 542 of 542 ops on LITERT_CL; on CPU, XNNPACK took 469 of 542.

GPU — iPhone 17 Pro (iOS Metal)

The engine-creation failure previously tracked in LiteRT-LM#3129 turned out to be a context-sizing issue on the integration side, not a runtime bug. The Metal delegate compiles its kernels against the KV cache that maxNumTokens pre-allocates; a value that does not match this file's exported plan (our test app derived ~650) makes engine creation fail with a shader-compile error. On iOS Metal, set maxNumTokens to 1024 (Swift EngineConfig(maxNumTokens:), C API litert_lm_engine_settings_set_max_num_tokens).

iPhone 17 Pro, litert-lm v0.16.0 xcframework, maxNumTokens 1024, single run, device charging: decode 67.7 tok/s (the int4 file on CPU on the same phone: 52.6), TTFT 109 ms on a short prompt, prefill 1,982 tok/s at p=128, peak ~470 MB. All Metal kernels compile, generation is coherent, and the file scores the same 8-question sanity gate as on CPU (7/8).

Only the _int4_gpu file loads on the GPU. LFM2.5-1.2B-Instruct_int4.litertlm delegates 536 of its 579 ops and then fails to create the engine, because the remaining 43 do not lower (GATHER_ND: Operation is not supported, plus several INT64 tensors). Use _int4_gpu on the GPU backend and _int4 or _int8 on CPU.

Run on Android

Install a recent Google AI Edge Gallery (1.0.16+ imports .litertlm directly from Hugging Face), import this repo (or adb push a file and use local import), select the CPU backend, and chat. GPU acceleration needs the _int4_gpu file and litert-lm ≥ 0.16.0 (litert_lm_main --backend=gpu, or the SDKs); the Gallery bundles its own runtime, which may lag that version — if its GPU toggle fails there, use CPU.

⚠ Gallery's import dialog defaults to CPU-only. Scroll it to Compatible accelerators and tick GPU at import time; a model already imported has to be deleted and re-imported. Nothing in the bundle sets this. Full recipe: Running converted models on GPU (Android).

Conversion notes

Converted with released litert-torch 0.9.1 (which ships the lfm2 hybrid model support) and packaged for litert-lm ≥ 0.14, with one exporter patch: the stock LFM2 short-conv block saves its conv state from the last columns of the prefill chunk, which are padding whenever the prompt does not exactly fill a prefill signature — corrupting the first generated token of nearly every reply. The patch derives the valid length from the attention mask in-graph and gathers the conv state from the last valid columns instead; with it, engine output is token-identical to an exact per-token reference loop at every prompt length. Multi-length prefill signatures (1–1024) are exported so the runtime can pick tight chunks.

Quantization targets fully-connected + embedding ops (plus convs in the int8 file, quantized at export time); post-hoc int8 of the convs with ai-edge-quantizer breaks generation — quantize convs only at export time.

Why there is a separate _int4_gpu file. The exporter patch above reads the chunk's valid length with index_select and a mask sum, which lower to GATHER_ND and INT64 ops, and GPU delegates reject both — the CPU-only files take 536 of 579 operations on the GPU and the runtime then refuses the partial split. litert-torch 0.9.2 fixed the underlying conv-state bug upstream using valid-token masking and a one-hot matmul state select, which emits neither op. _int4_gpu is that export: litert-torch 0.9.3 + litert-converter 0.3.1, the same int4 recipe and the same weights as the int4 file, plus the executor-metadata section litert-lm ≥ 0.15 needs. It delegates fully on Android OpenCL — 501/501 and 519/519 nodes, zero rejected ops — and runs on the macOS GPU backend. Quality is unchanged: run head to head against the published int4 file on identical prompts, decoding and scoring, both score 38/50 on GSM8K (CPU, n=50), and the GPU file passes an 8-question sanity gate on both backends. The CPU-only files are left exactly as they are rather than replaced, so nothing changes for anyone already using them.

Raspberry Pi 5 (CPU)

Measured on a Raspberry Pi 5 Model B Rev 1.1 (8 GB, Raspberry Pi OS 64-bit) with litert-lm benchmark 0.16.1: CPU backend, 4 threads, 256 prefill + 256 decode tokens, --cache memory (the compile cache lives and dies with the process, so every invocation compiles the model from scratch; nothing is reused between runs), one warm-up plus one timed iteration per invocation, 3 invocations per file with cooldown in between. Values are the median across invocations (min–max in parentheses). No thermal throttling occurred during these runs (vcgencmd get_throttled stayed 0x0). Every file listed produced coherent text in a real generation on this backend before its numbers were recorded.

FilePrefill (tok/s)Decode (tok/s)TTFTPeak RSS
LFM2.5-1.2B-Instruct_int4.litertlm54.1 (53.7–54.2)9.3 (9.3–9.3)4.8 s1.4 GB
LFM2.5-1.2B-Instruct_int4_gpu.litertlm54.6 (53.5–54.6)9.3 (9.3–9.3)4.8 s1.4 GB
LFM2.5-1.2B-Instruct_int8.litertlm75.0 (74.5–75.7)7.0 (7.0–7.1)3.6 s1.9 GB

License and changes

Distributed under the LFM Open License v1.0 (see LICENSE, inherited from the base model). Note the license's commercial-use limitation for organizations above US$10M annual revenue. Changes from the original work: weights converted from safetensors bf16 to LiteRT flatbuffers and quantized as described above; tokenizer and chat template repackaged unmodified into the .litertlm bundle; exporter conv-state fix as described in Conversion notes. This repository is a community conversion and is not affiliated with Liquid AI.

edge
hybrid
liquid
litert
litert-lm
litertlm
on-device
text-generation