PITTI commited on
Commit
dc9e965
·
verified ·
1 Parent(s): a72637d

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +201 -1
README.md CHANGED
@@ -11,4 +11,204 @@ library_name: transformers
11
  tags:
12
  - MLX
13
  - NER
14
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  tags:
12
  - MLX
13
  - NER
14
+ - openai_privacy_filter
15
+ ---
16
+
17
+ ## Usage with mlx-raclate
18
+
19
+ This model can be used with [mlx-raclate](https://github.com/pappitti/mlx-raclate) for native inference on Apple Silicon.
20
+
21
+ ```python
22
+ from mlx_raclate.utils.utils import load
23
+ from mlx_raclate.utils.token_classification import (
24
+ postprocess_token_classification_output,
25
+ viterbi_transition_biases_from_calibration,
26
+ )
27
+
28
+ # Load model and tokenizer
29
+ model_path = "PITTI/privacy-filter-nemotron"
30
+ model, tokenizer = load(
31
+ model_path,
32
+ pipeline="token-classification"
33
+ )
34
+
35
+ # Prepare input texts
36
+ texts = ['John works at Apple in California.', 'Microsoft was founded by Bill Gates.']
37
+
38
+ # Tokenize
39
+ max_length = getattr(model.config, "max_position_embeddings", 512)
40
+ tokens = tokenizer._tokenizer(
41
+ texts,
42
+ return_tensors="mlx",
43
+ padding=True,
44
+ truncation=True,
45
+ max_length=max_length,
46
+ return_offsets_mapping=True,
47
+ )
48
+ offset_mapping = tokens.pop("offset_mapping")
49
+
50
+ # Run inference
51
+ outputs = model(
52
+ input_ids=tokens["input_ids"],
53
+ attention_mask=tokens["attention_mask"],
54
+ return_dict=True
55
+ )
56
+
57
+ # Get predictions
58
+ logits = outputs["logits"]
59
+ id2label = model.config.id2label
60
+ transition_biases = viterbi_transition_biases_from_calibration(
61
+ getattr(model, "viterbi_calibration", None)
62
+ )
63
+ processed = postprocess_token_classification_output(
64
+ logits=logits,
65
+ probabilities=outputs["probabilities"],
66
+ id2label=id2label,
67
+ texts=texts,
68
+ offsets=offset_mapping.tolist(),
69
+ transition_biases=transition_biases,
70
+ )
71
+
72
+ # Process and print grouped spans
73
+ for i, text in enumerate(texts):
74
+ print(f"Text: {text}")
75
+ print("Grouped spans:")
76
+ for span in processed["grouped_spans"][i]:
77
+ print(f" {span['entity_group']}: {span['word']!r} [{span['start']}, {span['end']}] score={span['score']:.3f}")
78
+ print()
79
+ ```
80
+
81
+ ## Usage with Transformers
82
+
83
+ OpenAI Privacy Filter models finetuned with Raclate are natively supported by Transformers. However, post-processing is necessary.
84
+
85
+ With `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.
86
+
87
+ ```python
88
+ import torch
89
+ from transformers import AutoModelForTokenClassification, AutoTokenizer
90
+
91
+
92
+ def decode_bioes_spans(text, offsets, label_ids, scores, id2label):
93
+ spans = []
94
+ current = None
95
+
96
+ def emit(span):
97
+ if span is None:
98
+ return
99
+
100
+ start = span["start"]
101
+ end = span["end"]
102
+ while start < end and text[start].isspace():
103
+ start += 1
104
+ while end > start and text[end - 1].isspace():
105
+ end -= 1
106
+
107
+ if end <= start:
108
+ return
109
+
110
+ span_scores = span["scores"]
111
+ spans.append(
112
+ {
113
+ "entity_group": span["entity_group"],
114
+ "score": sum(span_scores) / len(span_scores),
115
+ "word": text[start:end],
116
+ "start": start,
117
+ "end": end,
118
+ }
119
+ )
120
+
121
+ for offset, label_id, score in zip(offsets, label_ids, scores):
122
+ start, end = int(offset[0]), int(offset[1])
123
+ if end <= start:
124
+ continue
125
+
126
+ label = id2label[int(label_id)]
127
+ if label == "O":
128
+ emit(current)
129
+ current = None
130
+ continue
131
+
132
+ prefix, entity_group = label.split("-", 1) if "-" in label else ("S", label)
133
+ if prefix == "S":
134
+ emit(current)
135
+ emit(
136
+ {
137
+ "entity_group": entity_group,
138
+ "start": start,
139
+ "end": end,
140
+ "scores": [float(score)],
141
+ }
142
+ )
143
+ current = None
144
+ continue
145
+
146
+ if prefix == "B" or current is None or current["entity_group"] != entity_group:
147
+ emit(current)
148
+ current = {
149
+ "entity_group": entity_group,
150
+ "start": start,
151
+ "end": end,
152
+ "scores": [float(score)],
153
+ }
154
+ continue
155
+
156
+ current["end"] = end
157
+ current["scores"].append(float(score))
158
+ if prefix == "E":
159
+ emit(current)
160
+ current = None
161
+
162
+ emit(current)
163
+ return spans
164
+
165
+
166
+ model_id = 'PITTI/privacy-filter-nemotron'
167
+ texts = ['John works at Apple in California.', 'Microsoft was founded by Bill Gates.']
168
+
169
+ tokenizer = AutoTokenizer.from_pretrained(model_id, fix_mistral_regex=True)
170
+ model = AutoModelForTokenClassification.from_pretrained(model_id)
171
+ model.eval()
172
+
173
+ encoded = tokenizer(
174
+ texts,
175
+ return_tensors="pt",
176
+ padding=True,
177
+ truncation=True,
178
+ return_offsets_mapping=True,
179
+ )
180
+ offset_mapping = encoded.pop("offset_mapping")
181
+
182
+ with torch.no_grad():
183
+ logits = model(**encoded).logits
184
+
185
+ probabilities = torch.softmax(logits, dim=-1)
186
+ label_ids = probabilities.argmax(dim=-1)
187
+ label_scores = probabilities.max(dim=-1).values
188
+
189
+ for text, offsets, ids, scores in zip(
190
+ texts,
191
+ offset_mapping.tolist(),
192
+ label_ids.tolist(),
193
+ label_scores.tolist(),
194
+ ):
195
+ print(f"Text: {text}")
196
+ print("Grouped spans:")
197
+ spans = decode_bioes_spans(text, offsets, ids, scores, model.config.id2label)
198
+ for span in spans:
199
+ print(
200
+ f" {span['entity_group']}: {span['word']!r} "
201
+ f"[{span['start']}, {span['end']}] score={span['score']:.3f}"
202
+ )
203
+ print()
204
+ ```
205
+
206
+ ### Model Details
207
+
208
+ - **Base Model**: [openai/privacy-filter](https://huggingface.co/openai/privacy-filter)
209
+ - **Pipeline**: `token-classification`
210
+ - **Framework**: [mlx-raclate](https://github.com/pappitti/mlx-raclate) (MLX) or transformers
211
+
212
+ ### Inspiration
213
+
214
+ [OpenMed/privacy-filter-nemotron](https://huggingface.co/OpenMed/privacy-filter-nemotron), an amazing project led by Maziyar Panahi