LiquidAI/LFM2.5-Encoder-350M-PII-Detector converted to LiteRT (.tflite) for on-device inference. Detects ~40 kinds of personal information across 16 languages, fully offline — a natural fit for on-device redaction where the text must never leave the phone (demo Space).
Two signatures, pii_128 and pii_512 (S = 128 / 512, batch 1, right-padded):
Tensor
Shape
Meaning
input_ids
int32 [1, S]
token ids (the tokenizer prepends <|startoftext|>)
attention_mask
int32 [1, S]
1 = real token, 0 = pad
output_0
float32 [1, S, 161]
BIOES logits, zeroed at padded positions
Take the argmax per token, then decode the BIOES spans. The logit axis is 161 wide but only ids 0–108 are defined — label_schema.json carries the 109-entry id2label map (id 0 = O, "not personal information"); the remaining slots are unused. Restricting the argmax to the first 109 columns is the safe reading.
On Android/iOS use the LiteRT runtime's SignatureRunner APIs with the same signature names; the tokenizer is the standard Hugging Face tokenizer.json, which the Rust/Swift/Kotlin tokenizers bindings all read.
Performance
One pass over a padded sequence with the int8 (wi8fc) file, CPU only.
Device
Threads
pii_128
pii_512
Apple M4 Max (macOS)
8
34.9 ms
111.9 ms
iPhone 17 Pro
6
52 ms
not measured
Mac figures are the median of 20 warm runs (ai-edge-litert 2.1.6, XNNPACK, otherwise idle machine). The iPhone figure comes from the on-device gate (TFLite C API + SignatureRunner + XNNPACK) and is a single run, not a median.
Budget for one slow first call. The first inference after loading pays a one-time graph preparation: on the Mac it took 376 ms against a 34.9 ms steady state. Later signatures on the same loaded model do not pay it again — pii_512 measured 110 ms cold against 112 ms warm. Model load itself was 0.38 s on the iPhone.
The signatures are fixed-shape, so the input language or content does not change the time — warm, pii_128 measures 36.4 / 37.3 / 36.6 ms on English, Japanese and Arabic sentences of 17, 21 and 27 tokens.
Accuracy note
Task-level parity against the PyTorch reference on a name + email + phone sentence: fp32 and fp16 reproduce the reference entity tags exactly. int8 keeps all multi-token spans (email, phone) intact and dropped exactly one tag in that test — an entity-end token whose fp32 decision margin was only 0.53 logits, a genuinely borderline call. That is the extent of what was checked; it is a single-sentence spot check, not a benchmark over a labelled corpus. If you need maximum recall on borderline tokens, use the fp16 file on desktop; on phones the int8 file is the artifact.
On the iPhone 17 Pro the int8 file reproduces the desktop outputs bit-exactly — cosine 1.000000, max absolute difference 0.0 over the full output tensor.
Android (Pixel 8a)
Android figures use the standard TFLite benchmark_model on a Pixel 8a (Tensor G3, Android 16) — 5 warm-up runs then 20 timed runs, the signature selected explicitly with --signature_to_run_for, CPU at 4 threads.
Signature
GPU (OpenCL, previous export)
CPU (XNNPACK, 4 threads)
pii_128
342 ms
110 ms
pii_512
1656 ms
603 ms
GPU status (2026-08-13 re-export): still CPU on mobile. The re-export respells the one idiom mobile GPU delegates refuse — transformers' rank-5 repeat_kv expand — into an equivalent rank-4 matmul (outputs bitwise-identical on CPU) — removing the family-wide GPU blocker — but this model's int8 file still does not compile on mobile GPU delegates: its 161-label classification head hits a runtime kernel limit ("failed to initialize kernel"), consistently on Metal and OpenCL. CPU remains the mobile path (bit-exact on device). The fp16 file does run under the GPU delegates with the head falling back to CPU and matches the fp32 reference (cosine 1.000000, desktop-verified) — a desktop option on GPU. On a Snapdragon it is the one file here that reaches an accelerator at all: 175.4 ms on a Galaxy S26 Hexagon NPU, from an ahead-of-time compile rather than the published file (see Snapdragon NPU (Hexagon) below).
Snapdragon NPU (Hexagon)
LFM2.5-Encoder-350M-PII-Detector_fp16.tflite — the NPU runs it at 175.4 ms. The GPU does not — LiteRtException: Failed to compile model.
LFM2.5-Encoder-350M-PII-Detector_wi8fc.tflite — neither accelerator produced a usable row on the S26. Both ended the same way: LiteRtException: Failed to compile model.
file
backend
compiled
inference (median / min)
load
LFM2.5-Encoder-350M-PII-Detector_fp16.tflite
NPU (Hexagon v81)
AOT (SM8850)
175.4 ms / 171.8 ms
445 ms
Measured on a Samsung Galaxy S26 (Snapdragon 8 Elite Gen 5 / SM8850, Hexagon v81, Android 16) with LiteRT CompiledModel 2.2.0, one accelerator per process, 5 warm-up runs then N=50 timed runs, median reported. The run held thermal status NONE throughout. Headroom 0.76–0.80, where 1.0 is the throttling threshold.
The NPU row marked AOT ran an artifact compiled ahead of time for SM8850 (ai-edge-litert 2.2.0 + QAIRT 2.47.0), not the published file. That artifact is not distributed here; the compile is one command in the NPU guide.
LFM Open License v1.0 (see LICENSE, unchanged from the base model). Note the license's commercial-use threshold (Section 5). This repository redistributes converted Derivative Works of LiquidAI/LFM2.5-Encoder-350M-PII-Detector with modification notices per Section 4; all credit for the model to Liquid AI.