Views
No views yet
1from mlx_raclate.utils.utils import load
2from mlx_raclate.utils.token_classification import (
3 postprocess_token_classification_output,
4 viterbi_transition_biases_from_calibration,
5)
6
7# Load model and tokenizer
8model_path = "PITTI/privacy-filter-nemotron"
9model, tokenizer = load(
10 model_path,
11 pipeline="token-classification"
12)
13
14# Prepare input texts
15texts = ['John works at Apple in California.', 'Microsoft was founded by Bill Gates.']
16
17# Tokenize
18max_length = getattr(model.config, "max_position_embeddings", 512)
19tokens = tokenizer._tokenizer(
20 texts,
21 return_tensors="mlx",
22 padding=True,
23 truncation=True,
24 max_length=max_length,
25 return_offsets_mapping=True,
26)
27offset_mapping = tokens.pop("offset_mapping")
28
29# Run inference
30outputs = model(
31 input_ids=tokens["input_ids"],
32 attention_mask=tokens["attention_mask"],
33 return_dict=True
34)
35
36# Get predictions
37logits = outputs["logits"]
38id2label = model.config.id2label
39transition_biases = viterbi_transition_biases_from_calibration(
40 getattr(model, "viterbi_calibration", None)
41)
42processed = postprocess_token_classification_output(
43 logits=logits,
44 probabilities=outputs["probabilities"],
45 id2label=id2label,
46 texts=texts,
47 offsets=offset_mapping.tolist(),
48 transition_biases=transition_biases,
49)
50
51# Process and print grouped spans
52for i, text in enumerate(texts):
53 print(f"Text: {text}")
54 print("Grouped spans:")
55 for span in processed["grouped_spans"][i]:
56 print(f" {span['entity_group']}: {span['word']!r} [{span['start']}, {span['end']}] score={span['score']:.3f}")
57 print()transformers>=5.8.1, this checkpoint uses the standard Hugging Face openai_privacy_filter architecture. AutoModelForTokenClassification returns token logits; the helper below greedily decodes BIOES labels into character spans.1import torch
2from transformers import AutoModelForTokenClassification, AutoTokenizer
3
4
5def decode_bioes_spans(text, offsets, label_ids, scores, id2label):
6 spans = []
7 current = None
8
9 def emit(span):
10 if span is None:
11 return
12
13 start = span["start"]
14 end = span["end"]
15 while start < end and text[start].isspace():
16 start += 1
17 while end > start and text[end - 1].isspace():
18 end -= 1
19
20 if end <= start:
21 return
22
23 span_scores = span["scores"]
24 spans.append(
25 {
26 "entity_group": span["entity_group"],
27 "score": sum(span_scores) / len(span_scores),
28 "word": text[start:end],
29 "start": start,
30 "end": end,
31 }
32 )
33
34 for offset, label_id, score in zip(offsets, label_ids, scores):
35 start, end = int(offset[0]), int(offset[1])
36 if end <= start:
37 continue
38
39 label = id2label[int(label_id)]
40 if label == "O":
41 emit(current)
42 current = None
43 continue
44
45 prefix, entity_group = label.split("-", 1) if "-" in label else ("S", label)
46 if prefix == "S":
47 emit(current)
48 emit(
49 {
50 "entity_group": entity_group,
51 "start": start,
52 "end": end,
53 "scores": [float(score)],
54 }
55 )
56 current = None
57 continue
58
59 if prefix == "B" or current is None or current["entity_group"] != entity_group:
60 emit(current)
61 current = {
62 "entity_group": entity_group,
63 "start": start,
64 "end": end,
65 "scores": [float(score)],
66 }
67 continue
68
69 current["end"] = end
70 current["scores"].append(float(score))
71 if prefix == "E":
72 emit(current)
73 current = None
74
75 emit(current)
76 return spans
77
78
79model_id = 'PITTI/privacy-filter-nemotron'
80texts = ['John works at Apple in California.', 'Microsoft was founded by Bill Gates.']
81
82tokenizer = AutoTokenizer.from_pretrained(model_id, fix_mistral_regex=True)
83model = AutoModelForTokenClassification.from_pretrained(model_id)
84model.eval()
85
86encoded = tokenizer(
87 texts,
88 return_tensors="pt",
89 padding=True,
90 truncation=True,
91 return_offsets_mapping=True,
92)
93offset_mapping = encoded.pop("offset_mapping")
94
95with torch.no_grad():
96 logits = model(**encoded).logits
97
98probabilities = torch.softmax(logits, dim=-1)
99label_ids = probabilities.argmax(dim=-1)
100label_scores = probabilities.max(dim=-1).values
101
102for text, offsets, ids, scores in zip(
103 texts,
104 offset_mapping.tolist(),
105 label_ids.tolist(),
106 label_scores.tolist(),
107):
108 print(f"Text: {text}")
109 print("Grouped spans:")
110 spans = decode_bioes_spans(text, offsets, ids, scores, model.config.id2label)
111 for span in spans:
112 print(
113 f" {span['entity_group']}: {span['word']!r} "
114 f"[{span['start']}, {span['end']}] score={span['score']:.3f}"
115 )
116 print()token-classification