File size: 7,004 Bytes
11061d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
---
license: apache-2.0
base_model: OpenMed/privacy-filter-multilingual-v2
datasets:
  - ai4privacy/pii-masking-200k
  - ai4privacy/pii-masking-400k
  - ai4privacy/open-pii-masking-500k-ai4privacy
  - ai4privacy/pii-masking-openpii-1m
  - nvidia/Nemotron-PII
  - gretelai/gretel-pii-masking-en-v1
  - piimb/privy
pipeline_tag: token-classification
library_name: openmed
tags:
  - openmed
  - mlx
  - apple-silicon
  - token-classification
  - pii
  - de-identification
  - medical
  - clinical
  - privacy-filter
  - multilingual
  - bf16
  - full-precision
language:
  - ar
  - bn
  - de
  - en
  - es
  - fr
  - hi
  - it
  - ja
  - ko
  - nl
  - pt
  - te
  - tr
  - vi
  - zh
---

# OpenMed Privacy Filter Multilingual v2 - MLX BF16

A native [MLX](https://github.com/ml-explore/mlx) port of [`OpenMed/privacy-filter-multilingual-v2`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2) for Apple Silicon PII detection and de-identification with OpenMed. This is the unquantized BF16 reference artifact. For the 8-bit sibling, see [`OpenMed/privacy-filter-multilingual-v2-mlx-8bit`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2-mlx-8bit).

> Family at a glance:
> - PyTorch source: [`OpenMed/privacy-filter-multilingual-v2`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2)
> - MLX BF16 (this repo): Apple Silicon, full precision, `2.6 GiB` weights
> - MLX 8-bit: [`OpenMed/privacy-filter-multilingual-v2-mlx-8bit`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2-mlx-8bit) - Apple Silicon, `1.4 GiB` weights

## At a glance

- Source checkpoint: [`OpenMed/privacy-filter-multilingual-v2`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2)
- OpenMed MLX repo: [`OpenMed/privacy-filter-multilingual-v2-mlx`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2-mlx)
- Label schema: 54 fine-grained multilingual PII categories
- Output space: 217 BIOES classes (O plus B/I/E/S for each category)
- Languages: 16 languages from the source card: ar, bn, de, en, es, fr, hi, it, ja, ko, nl, pt, te, tr, vi, zh
- Weight format: `safetensors`
- Quantization: none (BF16 reference)

## Q8 sibling validation

The 8-bit sibling was compared against this BF16 artifact on 10 golden PII samples. Decoded entity spans matched across all samples. Average Q8/BF16 argmax agreement was 100.00% with average logit MAE 0.1902; average local forward time was 15.1 ms for BF16 vs 8.4 ms for Q8.

## What it does

This model is an MLX packaging of [`OpenMed/privacy-filter-multilingual-v2`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2), the second-generation multilingual checkpoint for fine-grained PII extraction across 16 languages. It uses OpenAI's Privacy Filter architecture and predicts 217 BIOES classes (O plus B/I/E/S for each category). The OpenMed `PrivacyFilterMLXPipeline` runs BIOES-aware Viterbi decoding so callers receive grouped spans instead of raw token tags.

Label coverage highlights:

- Identity: FIRSTNAME, MIDDLENAME, LASTNAME, AGE, GENDER, USERNAME, OCCUPATION, ORGANIZATION
- Contact and address: EMAIL, PHONE, URL, STREET, BUILDINGNUMBER, CITY, COUNTY, STATE, ZIPCODE
- Financial and crypto: BANKACCOUNT, IBAN, BIC, CREDITCARD, CVV, PIN, BITCOINADDRESS, ETHEREUMADDRESS
- Vehicle, digital, and auth: VIN, VRM, IPADDRESS, MACADDRESS, IMEI, PASSWORD
- Date and amount labels such as DATE, DATEOFBIRTH, TIME, AMOUNT, CURRENCY, and CURRENCYCODE

The full label map is included in `id2label.json`.

## Architecture

| Field | Value |
| --- | --- |
| Source model type | `openai_privacy_filter` |
| Source architecture | `OpenAIPrivacyFilterForTokenClassification` |
| Hidden size | 640 |
| Transformer layers | 8 |
| Attention | Grouped-query attention (14 query heads / 2 KV heads, head_dim=64) with attention sinks |
| FFN | Sparse Mixture-of-Experts - 128 experts, top-4 routing, SwiGLU |
| Position encoding | YARN-scaled RoPE (`rope_theta=150000`, factor=32) |
| Context length | 131,072 tokens (initial 4,096) |
| Tokenizer | `o200k_base` / tiktoken-compatible tokenizer assets, vocab 200,064 |
| Output head | Linear(640 -> 217) with bias |

## File set

| File | Size | Purpose |
| --- | --- | --- |
| `weights.safetensors` | 2.6 GiB | MLX weights |
| `config.json` | 17.6 KiB | Model and OpenMed MLX runtime config |
| `id2label.json` | 4.8 KiB | Numeric ID to BIOES label mapping |
| `openmed-mlx.json` | 0.7 KiB | OpenMed MLX artifact manifest |
| `tokenizer.json` | 27 MiB | Tokenizer asset kept with the artifact |
| `tokenizer_config.json` | 0.2 KiB | Tokenizer metadata |

The MLX runtime uses the tiktoken-compatible `o200k_base` tokenizer path. `tokenizer.json` and `tokenizer_config.json` are bundled so consumers can inspect the tokenizer assets and keep the artifact self-contained.

## Quick start

### With OpenMed

```bash
pip install -U "openmed[mlx]"
```

```python
from openmed import extract_pii, deidentify
from openmed.core import OpenMedConfig

model_name = "OpenMed/privacy-filter-multilingual-v2-mlx"
text = (
    "Patient Sarah Johnson (DOB 03/15/1985), MRN 4872910, "
    "phone 415-555-0123, email sarah.johnson@example.com."
)

result = extract_pii(
    text,
    model_name=model_name,
    config=OpenMedConfig(backend="mlx"),
)
for ent in result.entities:
    print(ent.label, ent.text, round(ent.confidence, 4))

masked = deidentify(
    text,
    method="mask",
    model_name=model_name,
    config=OpenMedConfig(backend="mlx"),
)
print(masked.deidentified_text)
```

For non-MLX hosts, use the source PyTorch checkpoint [`OpenMed/privacy-filter-multilingual-v2`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2).

### Direct MLX usage

```python
from huggingface_hub import snapshot_download
from openmed.mlx.inference import PrivacyFilterMLXPipeline

model_path = snapshot_download("OpenMed/privacy-filter-multilingual-v2-mlx")
pipe = PrivacyFilterMLXPipeline(model_path)

print(pipe("Email me at alice.smith@example.com after 5pm."))
```

### Loading from a local snapshot

```python
from openmed.mlx.models import load_model
import mlx.core as mx

model = load_model("/path/to/privacy-filter-multilingual-v2-mlx")
ids = mx.array([[1, 100, 200, 300]], dtype=mx.int32)
mask = mx.ones((1, 4), dtype=mx.bool_)
logits = model(ids, attention_mask=mask)
print(logits.shape)
```

## Hardware notes

- Designed for Apple Silicon with MLX.
- CPU inference may work, but GPU-backed MLX on M-series Macs is the intended runtime.
- The Python package path is `pip install -U "openmed[mlx]"`.

## Credits

This artifact builds on:

- [`OpenMed/privacy-filter-multilingual-v2`](https://huggingface.co/OpenMed/privacy-filter-multilingual-v2) by OpenMed
- [`openai/privacy-filter`](https://huggingface.co/openai/privacy-filter) and OpenAI's `opf` training/evaluation tooling
- The datasets listed in the model-card metadata above
- Apple's [MLX](https://github.com/ml-explore/mlx) framework

## License

Apache 2.0, matching the source checkpoint metadata.