Views
No views yet
OpenMed/privacy-filter-nemotron-v2, affine-quantized to 8-bit for faster and smaller Apple Silicon PII detection with OpenMed. For the unquantized BF16 reference, see OpenMed/privacy-filter-nemotron-v2-mlx.Family at a glance:
- PyTorch source:
OpenMed/privacy-filter-nemotron-v2- MLX BF16:
OpenMed/privacy-filter-nemotron-v2-mlx- Apple Silicon,2.6 GiBweights- MLX 8-bit (this repo): Apple Silicon,
1.4 GiBweights, ~1.8x faster than BF16 in the local golden-sample run
| BF16 sibling | This repo (Q8) | |
|---|---|---|
weights.safetensors size | 2.6 GiB | 1.4 GiB |
| Average forward pass | 14.2 ms | 7.9 ms (~1.8x faster) |
| Average argmax agreement vs. BF16 | reference | 99.55% |
| Entity-span preservation | reference | identical on all 10 golden samples |
scripts/export/verify_privacy_filter_nemotron_mlx.py over 10 golden PII samples (email, phone, ssn, credit card, name, ipv4, address, date_of_birth, url, mixed). Minimum per-sample argmax agreement was 95.5%; decoded spans still matched the BF16 reference on every sample.| Field | Value |
|---|---|
| Bits | 8 |
| Group size | 64 |
| Mode | affine MLX weight-only quantization |
| Quantized modules | embedding, attention projections, MoE router/expert matrices, output head |
| Kept in BF16 | RMSNorm scales and attention sinks |
OpenMed/privacy-filter-nemotron-v2, the second-generation Nemotron-schema checkpoint with a broader training mix and a more recall-oriented adaptation recipe than the first Nemotron branch. It uses OpenAI's Privacy Filter architecture and predicts 221 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.id2label.json.| 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 -> 221) with bias |
| File | Size | Purpose |
|---|---|---|
weights.safetensors | 1.4 GiB | MLX weights |
config.json | 19.6 KiB | Model and OpenMed MLX runtime config |
id2label.json | 5.4 KiB | Numeric ID to BIOES label mapping |
openmed-mlx.json | 0.8 KiB | OpenMed MLX artifact manifest |
tokenizer.json | 27 MiB | Tokenizer asset kept with the artifact |
tokenizer_config.json | 0.2 KiB | Tokenizer metadata |
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.pip install -U "openmed[mlx]"1from openmed import extract_pii, deidentify
2from openmed.core import OpenMedConfig
3
4model_name = "OpenMed/privacy-filter-nemotron-v2-mlx-8bit"
5text = (
6 "Patient Sarah Johnson (DOB 03/15/1985), MRN 4872910, "
7 "phone 415-555-0123, email sarah.johnson@example.com."
8)
9
10result = extract_pii(
11 text,
12 model_name=model_name,
13 config=OpenMedConfig(backend="mlx"),
14)
15for ent in result.entities:
16 print(ent.label, ent.text, round(ent.confidence, 4))
17
18masked = deidentify(
19 text,
20 method="mask",
21 model_name=model_name,
22 config=OpenMedConfig(backend="mlx"),
23)
24print(masked.deidentified_text)OpenMed/privacy-filter-nemotron-v2.1from huggingface_hub import snapshot_download
2from openmed.mlx.inference import PrivacyFilterMLXPipeline
3
4model_path = snapshot_download("OpenMed/privacy-filter-nemotron-v2-mlx-8bit")
5pipe = PrivacyFilterMLXPipeline(model_path)
6
7print(pipe("Email me at alice.smith@example.com after 5pm."))1from openmed.mlx.models import load_model
2import mlx.core as mx
3
4model = load_model("/path/to/privacy-filter-nemotron-v2-mlx-8bit")
5ids = mx.array([[1, 100, 200, 300]], dtype=mx.int32)
6mask = mx.ones((1, 4), dtype=mx.bool_)
7logits = model(ids, attention_mask=mask)
8print(logits.shape)pip install -U "openmed[mlx]".OpenMed/privacy-filter-nemotron-v2 by OpenMedopenai/privacy-filter and OpenAI's opf training/evaluation toolinglicense: other; this MLX packaging follows that source license metadata. Review the source model card before redistribution.