rampart-mlx / demo.py
rcn787's picture
initial mlx conversion of rampart pii ner
8000b36 verified
Raw
History Blame Contribute Delete
1.61 kB
"""
Minimal Rampart-MLX demo: tokenize, run the model, decode BIO spans.
python demo.py "My name is John Smith, email john@example.com"
"""
import sys
import mlx.core as mx
from tokenizers import Tokenizer
from rampart_mlx import load
def decode_spans(tokens, offsets, label_ids, id2label):
"""Merge B-/I- runs into (entity_type, text, start, end) spans."""
spans, cur = [], None
for (start, end), lid in zip(offsets, label_ids):
if start == end: # special token
continue
label = id2label[lid]
if label == "O":
cur = None
continue
tag, etype = label[0], label[2:]
if tag == "B" or cur is None or cur["type"] != etype:
cur = {"type": etype, "start": start, "end": end}
spans.append(cur)
else:
cur["end"] = end
return spans
def main():
text = sys.argv[1] if len(sys.argv) > 1 else \
"My name is John Smith and my email is john.smith@example.com"
model, cfg = load(".")
tok = Tokenizer.from_file("tokenizer.json")
enc = tok.encode(text)
input_ids = mx.array([enc.ids])
attention_mask = mx.array([enc.attention_mask])
logits = model(input_ids, attention_mask)
label_ids = mx.argmax(logits[0], axis=-1).tolist()
spans = decode_spans(enc.tokens, enc.offsets, label_ids, cfg.id2label)
print(f"\nText: {text}\n")
if not spans:
print("No PII detected.")
for s in spans:
print(f" {s['type']:16s} {text[s['start']:s['end']]!r} [{s['start']}:{s['end']}]")
if __name__ == "__main__":
main()