LFM2.5-350M β€” QHexRT NPU bundle (Hexagon v79 + v81)

Precompiled LiquidAI LFM2.5-350M (Lfm2ForCausalLM) for the QHexRT runtime on Qualcomm Hexagon v79 (Snapdragon 8 Elite / SM8750, e.g. Galaxy S25). A hybrid LLM with 10 short-conv layers + 6 GQA-attention layers β€” the transformer and the tied lm-head run on the NPU (HMX/HVX), driven by the lfm_generate host-op through QHexRT's manifest plan-interpreter; the host does only embed lookup, RoPE/mask, the cache copies, and the argmax scan. Device-validated end-to-end (greedy decode matches the fp32 reference for the first 6 generated tokens, then tracks coherently under fp16).

Contents (v79/)

file what size
lfm2-5-350m-2048.json QHexRT manifest β€” balanced (recommended) (MAXCTX=2048, ~29 tok/s); matches Genie's context.size β€”
lfm2-5-350m-512s.json QHexRT manifest β€” fast (MAXCTX=512, ~41 tok/s) β€”
lfm2-5-350m-4k.json QHexRT manifest β€” long context (MAXCTX=4096, ~14 tok/s) β€”
lfm_2048_shared.bin weight-shared context holding batched-prefill (AR=512) + 512-decode + 2048-decode graphs 583 MB
lfm_512_4k_shared.bin weight-shared context holding batched-prefill (AR=512) + 512-decode + 4096-decode graphs 586 MB
lfm_lmh.bin NPU lm-head graph β€” hidden[1,1024] β†’ logits[1,65536] (tied), fp16 on HMX 134 MB
lfm_embed_f16.bin token embedding table [65536,1024] f16 (host embed lookup) 134 MB
tokenizer.json LFM2 tokenizer (vocab 65536) 3.3 MB

Three context windows β€” pick the manifest. -2048 is the recommended default (balanced speed + real long context, matches Genie's 2048); -512s is fastest for short turns; -4k is for genuinely long inputs. Each manifest loads only its own weight-shared bin, so a run pulls one ~585 MB context β€” the extra decode-width graphs cost only a few MB each (identical fp16 weights stored once). Batched prefill seeds the decode caches in one forward β†’ O(1) TTFT for prompts up to 512 tokens; decode then runs autoregressively on the NPU lm-head. A sliding-window KV ring lets the conversation continue past the window (the model keeps the most recent MAXCTX tokens). All three are device-validated coherent (incl. verified long-range recall at 4096).

Run (QHexRT CLI)

hf download runanywhere/lfm2_5_350m_HNPU --local-dir lfm2_5_350m_HNPU
# qhx_generate from a QHexRT build; QNN libs from the QAIRT SDK (lib/aarch64-android) + v79 HTP skel.
adb push lfm2_5_350m_HNPU/v79 /data/local/tmp/wq/lfm
adb shell "cd /data/local/tmp/wq && export ADSP_LIBRARY_PATH='/data/local/tmp/wq/dsp;/data/local/tmp/wq;/vendor/dsp/cdsp'; \
  LD_LIBRARY_PATH=. ./qhx_generate lfm/lfm2-5-350m-2048.json libQnnHtp.so libQnnSystem.so lfm 40 'The capital of France is'"
# -> coherent continuation; [lfm] prefill(TTFT) ~52 ms (any prompt) + decode ~34 ms/tok (~29 tok/s)

Performance (measured on-device, v79 / Samsung S25)

Context TTFT Decode tok/s Peak RSS KV cache Coherent
512 54 ms 24.6 ms/tok 40.7 734 MB 6 MB βœ…
2048 52 ms 34.4 ms/tok 29.1 731 MB 24 MB βœ…
4096 52 ms 71.6 ms/tok 14.0 734 MB 48 MB βœ…
  • TTFT is O(1) (~52–54 ms) β€” same batched-prefill graph; constant in prompt length (S=6 β†’ 52 ms, S=260 β†’ 61 ms; vs ~3.9 s for the old decode-over-prompt).
  • Decode is flat across position (2048: 34.4 β†’ 37.1 ms/tok over 4Γ— more tokens; 4096: no growth) β€” per-token latency is set by the graph's fixed attention width, not by how many tokens already exist.
  • KV cache = 6 attn layers Γ— max_ctx Γ— 512 Γ— 2 B Γ— 2(K,V) (only 6 of 16 layers are attention; the 10 short-conv layers add a negligible 61 KB). It is DDR-streamed, not VTCM-resident β€” which is why peak RSS stays flat (732 MB, weight-dominated) even at 4096.
  • Long-range recall verified @4096: recalls a number stated before a distractor sentence β†’ attention genuinely retrieves from earlier KV positions, not just local conv.

Notes

  • Arch: v79 only β€” context binaries are dsp-arch-pinned.
  • No custom op-package β€” pure-native HTP graph (the conv1d short-conv is a native op; QK-norm + GQA + 1D RoPE ΞΈ=1e6, head_dim 64). The host does only embed lookup, the full-dim RoPE table, the cache mask, and the tied lm-head argmax.
  • Base model (not instruction-tuned) β€” it continues text rather than chatting.
  • Three compiled context windows (512 / 2048 / 4096); a sliding-window KV ring lets generation continue past the window (keeping the most recent MAXCTX tokens). Beyond 4096 needs a re-export.
  • Source: LiquidAI/LFM2.5-350M-Base, compiled with QAIRT 2.45 for qualcomm-snapdragon-8-elite-for-galaxy.

v81 (SM8850 / soc_model 87)

The v81/ bundle is device-validated on SM8850: coherent fp16 generation, decode ~14 ms/tok, prefill TTFT ~49 ms (MAXCTX=2048). Greedy tracks the fp32 HF gold for the first 6 tokens then makes the same kind of fp16 near-tie the v79 bundle does (e.g. "A) Paris" vs "A: Paris") and continues correctly β€” a second prompt ("Photosynthesis is the process by which…") returns a fluent, factually-correct continuation. Built via the config-driven LFM2 export recipe (decode 8/8 + prefill cosine 1.000000 vs the lfm_net oracle) and compiled with the model-lib f16 + {O:3,vtcm_mb:8,dlbc:1} route.

Files (v81/) β€” separate prefill/decode/lmhead bins (not weight-shared)

file what
lfm2-5-350m-2048.json QHexRT manifest (MAXCTX=2048; lfm_generate over the 3 graphs below)
lfm_pf_f16.bin batched prefill graph (AR=512), fp16
lfm_dec_f16.bin autoregressive decode graph (MAXCTX 2048, GQA-native), fp16
lfm_lmh_f16.bin NPU lm-head hidden[1,1024]β†’logits[1,65536] (tied), fp16
lfm_embed_f16.bin token embedding table [65536,1024] f16 (host lookup)
tokenizer.json LFM2 tokenizer
Downloads last month
277
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for runanywhere/lfm2_5_350m_HNPU

Finetuned
(13)
this model