yungisimon commited on
Commit
48d34f1
·
verified ·
1 Parent(s): 50f364e

Upload pii_hybrid_decode.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. 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
- return uniq
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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