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 +23 -1
pii_hybrid_decode.py
CHANGED
|
@@ -120,7 +120,29 @@ def hybrid_spans(text: str, model_spans: list[dict]) -> list[dict]:
|
|
| 120 |
if k in seen: continue
|
| 121 |
if len(text[sp["start"]:sp["end"]].strip()) < 3: continue # drop fragments
|
| 122 |
seen.add(k); uniq.append(sp)
|
| 123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
def model_spans(text: str, tok, model):
|
| 126 |
import torch
|
|
|
|
| 120 |
if k in seen: continue
|
| 121 |
if len(text[sp["start"]:sp["end"]].strip()) < 3: continue # drop fragments
|
| 122 |
seen.add(k); uniq.append(sp)
|
| 123 |
+
# CONTEXT tier: cue-gated alphanumeric IDs (Passport No:/Policy #/MRN: ...) — recovers
|
| 124 |
+
# the structure-less IDs the model can't learn. Authoritative for their types; AUTH wins.
|
| 125 |
+
try:
|
| 126 |
+
from context_cued import context_cued_spans, CONTEXT_TYPES
|
| 127 |
+
except Exception:
|
| 128 |
+
return uniq
|
| 129 |
+
cued = context_cued_spans(text)
|
| 130 |
+
if not cued:
|
| 131 |
+
return uniq
|
| 132 |
+
auth_claim = [False] * len(text)
|
| 133 |
+
for sp in uniq:
|
| 134 |
+
if sp["type"] in _AUTH_TYPES:
|
| 135 |
+
for i in range(sp["start"], sp["end"]): auth_claim[i] = True
|
| 136 |
+
kept = [c for c in cued if not any(auth_claim[c["start"]:c["end"]])]
|
| 137 |
+
rng = [(c["start"], c["end"]) for c in kept]
|
| 138 |
+
def _ov(sp): return any(min(e, sp["end"]) > max(s, sp["start"]) for s, e in rng)
|
| 139 |
+
merged = [sp for sp in uniq if not (sp["type"] in CONTEXT_TYPES and _ov(sp))] + kept
|
| 140 |
+
seen, final = set(), []
|
| 141 |
+
for sp in sorted(merged, key=lambda s: (s["start"], s["end"])):
|
| 142 |
+
k = (sp["start"], sp["end"], sp["type"])
|
| 143 |
+
if k in seen: continue
|
| 144 |
+
seen.add(k); final.append(sp)
|
| 145 |
+
return final
|
| 146 |
|
| 147 |
def model_spans(text: str, tok, model):
|
| 148 |
import torch
|