File size: 2,996 Bytes
92a1c3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
---
license: other
license_name: lfm1.0
license_link: LICENSE
base_model: LiquidAI/LFM2.5-Encoder-350M-PII-Detector
pipeline_tag: token-classification
library_name: litert
tags:
- litert
- tflite
- on-device
- edge
- encoder
- pii
- ner
- privacy
- liquid
- lfm2
- lfm2.5
---

# LFM2.5-Encoder-350M-PII-Detector — LiteRT

[LiquidAI/LFM2.5-Encoder-350M-PII-Detector](https://huggingface.co/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](https://huggingface.co/spaces/LiquidAI/pii-detection)).

| File | Recipe | Size | |
|---|---|---|---|
| `LFM2.5-Encoder-350M-PII-Detector_wi8fc.tflite` | int8 dynamic-range (linears + embedding, convs float) | 364 MB | mobile + desktop (iPhone-verified bit-exact, 52 ms) |
| `LFM2.5-Encoder-350M-PII-Detector_fp16.tflite` | fp16 weights, float compute | 712 MB | desktop — full fidelity; phone memory limits (XNNPACK per-signature fp32 unpacking) |

## Signatures

`pii_128` / `pii_512` (S = 128 / 512, batch 1, right-padded): `input_ids` int32 `[1, S]`, `attention_mask` int32 `[1, S]` → BIOES logits float32 `[1, S, 161]`, zeroed at padded positions. Argmax per token, then decode BIOES spans; the label id ↔ entity mapping ships in `label_schema.json`.

```python
import numpy as np
from ai_edge_litert.interpreter import Interpreter
from tokenizers import Tokenizer

tok = Tokenizer.from_file("tokenizer.json")
it = Interpreter(model_path="LFM2.5-Encoder-350M-PII-Detector_wi8fc.tflite")
run = it.get_signature_runner("pii_128")
ids = tok.encode("My email is jane@example.com.").ids
x = np.zeros((1, 128), np.int32); m = np.zeros((1, 128), np.int32)
x[0, :len(ids)] = ids; m[0, :len(ids)] = 1
lg = list(run(input_ids=x, attention_mask=m).values())[0]
labels = lg[0, :len(ids)].argmax(-1)   # 0 = O; see label_schema.json
```

## Verification

Task-level parity vs the PyTorch reference (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 our test — an entity-end token whose fp32 decision margin was only 0.53 logits (a genuinely borderline call). If you need maximum recall on borderline tokens, use the fp16 file on desktop; on phones the int8 file is the artifact.

On an iPhone 17 Pro the int8 file reproduces the desktop outputs **bit-exactly** (cosine 1.000000, max diff 0.0) at 52 ms per `pii_128` pass (6 threads, XNNPACK).

## License

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](https://www.liquid.ai/).