Token Classification
Transformers
Safetensors
lfm2
liquid
lfm2.5
bidirectional
masked-lm
encoder
pii
ner
privacy
multilingual
custom_code
Instructions to use LiquidAI/LFM2.5-Encoder-350M-PII-Detector with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use LiquidAI/LFM2.5-Encoder-350M-PII-Detector with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="LiquidAI/LFM2.5-Encoder-350M-PII-Detector", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("LiquidAI/LFM2.5-Encoder-350M-PII-Detector", trust_remote_code=True) model = AutoModelForTokenClassification.from_pretrained("LiquidAI/LFM2.5-Encoder-350M-PII-Detector", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Upload pii_hybrid_decode.py with huggingface_hub
Browse files- pii_hybrid_decode.py +31 -1
pii_hybrid_decode.py
CHANGED
|
@@ -142,7 +142,37 @@ def hybrid_spans(text: str, model_spans: list[dict]) -> list[dict]:
|
|
| 142 |
k = (sp["start"], sp["end"], sp["type"])
|
| 143 |
if k in seen: continue
|
| 144 |
seen.add(k); final.append(sp)
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
def model_spans(text: str, tok, model):
|
| 148 |
import torch
|
|
|
|
| 142 |
k = (sp["start"], sp["end"], sp["type"])
|
| 143 |
if k in seen: continue
|
| 144 |
seen.add(k); final.append(sp)
|
| 145 |
+
# GROUP-B cue tier: amount/date/phone/postal where the model stayed silent but a
|
| 146 |
+
# field-cue+shape is present (authoritative for those 4 types; AUTH wins; address excluded).
|
| 147 |
+
try:
|
| 148 |
+
from context_cued import group_b_cue_spans
|
| 149 |
+
except Exception:
|
| 150 |
+
return final
|
| 151 |
+
gb = [c for c in group_b_cue_spans(text)
|
| 152 |
+
if c["type"] in ("financial.amount","identity.date_of_birth","contact.phone","contact.postal_code")]
|
| 153 |
+
if not gb:
|
| 154 |
+
return final
|
| 155 |
+
aclaim = [False] * len(text)
|
| 156 |
+
for sp in final:
|
| 157 |
+
if sp["type"] in _AUTH_TYPES:
|
| 158 |
+
for i in range(sp["start"], sp["end"]): aclaim[i] = True
|
| 159 |
+
keptb = []
|
| 160 |
+
for c in gb:
|
| 161 |
+
if any(aclaim[c["start"]:c["end"]]): continue
|
| 162 |
+
s, e = c["start"], c["end"]
|
| 163 |
+
if c["type"] == "financial.amount":
|
| 164 |
+
while e > s and text[e-1] in ".,;": e -= 1
|
| 165 |
+
keptb.append({"start": s, "end": e, "type": c["type"], "text": text[s:e]})
|
| 166 |
+
rb = [(c["start"], c["end"]) for c in keptb]
|
| 167 |
+
def _ovb(sp): return any(min(e, sp["end"]) > max(s, sp["start"]) for s, e in rb)
|
| 168 |
+
GB = {"financial.amount","identity.date_of_birth","contact.phone","contact.postal_code"}
|
| 169 |
+
merged2 = [sp for sp in final if not (sp["type"] in GB and _ovb(sp))] + keptb
|
| 170 |
+
seen, out2 = set(), []
|
| 171 |
+
for sp in sorted(merged2, key=lambda s: (s["start"], s["end"])):
|
| 172 |
+
k = (sp["start"], sp["end"], sp["type"])
|
| 173 |
+
if k in seen: continue
|
| 174 |
+
seen.add(k); out2.append(sp)
|
| 175 |
+
return out2
|
| 176 |
|
| 177 |
def model_spans(text: str, tok, model):
|
| 178 |
import torch
|