CoolFace
Modelpublic

binga/privacy-filter-multitask

sourceHugging Faceapache-2.0updated 5mo agoView on Hugging Face
1likes14downloads
Model Card

Privacy Filter Multi-Task 🔒📄

A single model for simultaneous PII Detection (NER) and Document Classification (10 categories).

Adapted from openai/privacy-filter — a 1.4B Sparse MoE transformer with only ~50M active parameters per token.

Architecture

Input → BPE Tokenizer (o200k_base, 200K vocab)
  ↓
8-layer Sparse MoE Transformer
  • 128 experts, top-4 routing (~50M active params/token)
  • Banded sliding-window attention (window=128)
  • GQA: 14 query heads, 2 KV heads, head_dim=64
  • Hidden size: 640
  ↓                          ↓
NER Head (640→33)        Doc Head (mean-pool → 640→10)
  ↓                          ↓
BIOES PII tags            10-class document category

Results

PII Detection (NER)

MetricValue
F1 (strict span-level)0.493
Precision0.697
Recall0.381
Token Accuracy0.944

8 entity types: private_person · private_email · private_phone · private_address · private_date · private_url · account_number · secret

Document Classification (10 classes)

SplitAccuracy
Val0.470
Test0.478

Per-class test accuracy:

CategoryAccuracy
Computers & Internet0.688
Family & Relationships0.615
Science & Mathematics0.556
Health0.524
Sports0.523
Politics & Government0.493
Entertainment & Music0.444
Society & Culture0.363
Education & Reference0.310
Business & Finance0.263

🚀 Production Inference Guide

All numbers below are measured on real hardware with both task heads (NER + doc classification) executing on every call. Benchmark script: single forward pass produces PII entity tags and document category simultaneously.

Resource Requirements

ResourceValue
Model weights (bf16)2.8 GB GPU VRAM / RAM
Model weights (fp32)5.6 GB RAM
ONNX variants available upstreamfp16, int8, q4 (see openai/privacy-filter)
Min GPU VRAM (bs=1, seq≤512)2.9 GB
Min GPU VRAM (bs=64, seq=512)6.2 GB
Fits onT4 (16 GB), L4 (24 GB), A10G (24 GB), A100, any ≥8 GB GPU

GPU — Single-Document Latency (NVIDIA A10G, bf16)

Time from raw text to both NER tags + document category:

Sequence LengthLatency (mean)Latency (p95)Latency (p99)
64 tokens113 ms117 ms122 ms
128 tokens106 ms110 ms115 ms
256 tokens106 ms111 ms113 ms
512 tokens106 ms113 ms116 ms
Latency is dominated by a fixed ~105 ms kernel-launch overhead from the Sparse MoE routing — it barely changes with sequence length up to 512 tokens.

GPU — Batched Throughput (NVIDIA A10G, bf16)

Batch SizeSeq 64Seq 128Seq 256Seq 512
18.9 docs/s9.4 docs/s9.4 docs/s9.4 docs/s
436 docs/s37 docs/s37 docs/s32 docs/s
873 docs/s73 docs/s69 docs/s53 docs/s
16139 docs/s138 docs/s114 docs/s73 docs/s
32265 docs/s238 docs/s165 docs/s89 docs/s
64460 docs/s348 docs/s207 docs/s101 docs/s

GPU — Batched Latency Detail (NVIDIA A10G, bf16)

<details> <summary>Full latency table (click to expand)</summary>

BatchSeq LenBatch Latency (ms)Per-Doc (ms)p95 (ms)p99 (ms)
164113112.7117122
46411127.8116118
86411013.8114126
16641157.2121125
32641213.8127135
64641392.2144144
1128106105.9110115
412810726.9112115
812811013.7115116
161281167.3121128
321281344.2139143
641281842.9189191
1256106106.1111113
425610927.2114115
825611714.6123126
162561408.8145147
322561946.1199202
642563094.8314315
1512106106.5113116
451212531.2129130
851215219.0158165
1651221913.7223225
3251235811.2361364
645126369.9639641

</details>

GPU — Peak VRAM Usage (bf16)

Batch SizeSeq 128Seq 256Seq 512
12,817 MB2,824 MB2,862 MB
82,857 MB2,936 MB3,237 MB
323,000 MB3,309 MB4,522 MB
643,189 MB3,809 MB6,236 MB
The model is extremely memory-efficient. Even at batch=64, seq=512, it uses only 6.2 GB — comfortably fits on a T4 (16 GB). This is because the Sparse MoE only activates 4 of 128 experts per token.

CPU — Latency & Throughput (AMD EPYC 7R32, 8 cores, fp32)

BatchSeq 64Seq 128Seq 256Seq 512
1152 ms (6.6/s)193 ms (5.2/s)302 ms (3.3/s)569 ms (1.8/s)
4278 ms (14.4/s)468 ms (8.6/s)935 ms (4.3/s)2,464 ms (1.6/s)
8467 ms (17.1/s)862 ms (9.3/s)1,728 ms (4.6/s)4,745 ms (1.7/s)
16837 ms (19.1/s)1,624 ms (9.9/s)3,814 ms (4.2/s)9,143 ms (1.7/s)
On CPU the model runs at ~152 ms/doc for short texts (seq=64, bs=1) — suitable for low-volume or batch-offline pipelines.

Daily Throughput Projections

Sustained throughput for a single device, running 24/7 at the optimal batch size:

Sequence LengthGPU (A10G, bf16)CPU (8-core, fp32)
64 tokens39.8M docs/day (460/s, bs=64)1.7M docs/day (19/s, bs=16)
128 tokens30.1M docs/day (348/s, bs=64)855K docs/day (10/s, bs=16)
256 tokens17.9M docs/day (207/s, bs=64)397K docs/day (4.6/s, bs=8)
512 tokens8.7M docs/day (101/s, bs=64)156K docs/day (1.8/s, bs=1)
Multi-GPU Scaling Estimates
Configseq=128seq=256seq=512
1× A10G (24 GB, ~$1/hr)30M/day18M/day8.7M/day
1× A100 (80 GB, ~$3/hr)~70M/day¹~42M/day¹~20M/day¹
4× A10G data-parallel120M/day72M/day35M/day
8× A10G data-parallel240M/day143M/day70M/day

<sub>¹ A100 estimates are linearly extrapolated from A10G numbers using A100's ~2.3× higher memory bandwidth and larger batch capacity. Actual numbers will vary — benchmark on your target hardware.</sub>

Serving Recommendations

Deployment ScenarioRecommended ConfigExpected Perf
Real-time API (SLA <200ms)1× GPU, bs=1, seq≤512~106 ms p50, ~113 ms p95
Near-real-time (SLA <500ms)1× GPU, bs=8–16, seq≤51253–73 docs/s, p95 <225 ms
High-throughput batch1× GPU, bs=64, seq=256207 docs/s, 17.9M/day
Max throughput batch1× GPU, bs=64, seq=64²460 docs/s, 39.8M/day
CPU offline / devCPU, bs=1, seq≤2563–7 docs/s

<sub>² At seq=64 most documents will be truncated. Use seq=128–256 for production balance.</sub>

Key observations:

  • The model has a fixed ~105 ms overhead per forward pass regardless of sequence length (MoE routing + expert dispatch). Batching amortizes this cost across documents — the per-doc cost drops from 106 ms (bs=1) to under 10 ms (bs=64).
  • Memory is not the bottleneck — even at bs=64/seq=512 the model uses only 6.2 GB. You can run this on a T4 (16 GB) with room to spare.
  • Optimal batch size for throughput: bs=64 for all sequence lengths on A10G.
  • Optimal batch size for latency-constrained: bs=8–16 gives a good per-doc latency (13–19 ms) while keeping batch latency under 225 ms.

Training Strategy

Two-phase training approach:

  1. 1.Phase 1 — Multi-task fine-tuning: Partially unfroze last 4 MoE layers + both task heads. Trained on 20K NER examples (ai4privacy) + 20K doc examples (Yahoo Answers). Multi-task loss (NER×1.0 + Doc×0.5). 2 epochs, LR=2e-5.
  1. 1.Phase 2 — Doc head retraining (head-only): Froze entire backbone + NER head. Pre-computed 640-dim pooled features for 100K Yahoo Answers examples. Trained fresh Linear(640→10) classifier for 10 epochs, LR=1e-3, cosine decay. This approach:
  2. 2.Preserves NER performance exactly (backbone untouched)
  3. 3.Is extremely fast (~seconds per epoch on cached features)
  4. 4.Achieves 47.8% test accuracy (up from 24.8% in phase 1)

Usage

python
import torch
import torch.nn as nn
from transformers import AutoModelForTokenClassification, AutoTokenizer
from huggingface_hub import hf_hub_download

# Load model + tokenizer
tokenizer = AutoTokenizer.from_pretrained("binga/privacy-filter-multitask")
model = AutoModelForTokenClassification.from_pretrained(
    "binga/privacy-filter-multitask", dtype=torch.bfloat16, device_map="auto"
)

# Load document classification head
doc_head = nn.Linear(640, 10)
doc_head.load_state_dict(torch.load(
    hf_hub_download("binga/privacy-filter-multitask", "doc_head.pt"),
    weights_only=True, map_location=model.device
))
doc_head = doc_head.to(dtype=torch.bfloat16, device=model.device)
doc_head.eval()

# Inference
text = "John Smith (SSN: 123-45-6789) emailed john@corp.com about Q3 earnings."
inputs = tokenizer(text, return_tensors="pt").to(model.device)

with torch.no_grad():
    outputs = model(**inputs, output_hidden_states=True)

# === PII Detection ===
print("PII entities:")
for tok, pred in zip(
    tokenizer.convert_ids_to_tokens(inputs["input_ids"][0]),
    outputs.logits.argmax(-1)[0]
):
    label = model.config.id2label[pred.item()]
    if label != "O":
        print(f"  {tok} → {label}")

# === Document Classification ===
categories = [
    "Society & Culture", "Science & Math", "Health", "Education",
    "Computers & Internet", "Sports", "Business & Finance",
    "Entertainment", "Family", "Politics"
]
hidden = outputs.hidden_states[-1]
mask = inputs["attention_mask"].unsqueeze(-1).to(hidden.dtype)
pooled = (hidden * mask).sum(1) / mask.sum(1).clamp(min=1)
probs = torch.softmax(doc_head(pooled)[0].float(), dim=-1)
top = probs.argmax().item()
print(f"\nCategory: {categories[top]} ({probs[top]:.1%})")

Batched Inference (Production)

python
# Process a batch of documents — both tasks in a single forward pass
texts = ["doc1...", "doc2...", "doc3...", ...]
inputs = tokenizer(texts, return_tensors="pt", padding=True,
                   truncation=True, max_length=256).to(model.device)

with torch.no_grad():
    outputs = model(**inputs, output_hidden_states=True)

# NER predictions for all docs: [batch, seq_len]
ner_preds = outputs.logits.argmax(dim=-1)

# Doc class for all docs: [batch]
hidden = outputs.hidden_states[-1]
mask = inputs["attention_mask"].unsqueeze(-1).to(hidden.dtype)
pooled = (hidden * mask).sum(1) / mask.sum(1).clamp(min=1)
doc_preds = doc_head(pooled).argmax(dim=-1)

Example Outputs

InputPII DetectedCategory (confidence)
"My name is John Smith... email john@example.com"✅ John Smith, john@example.com, 123 Main StComputers & Internet (56%)
"Liverpool FC defeated Manchester City 3-1"❌ NoneSports (98%)
"Federal Reserve announced a rate cut"❌ NonePolitics (52%)
"health benefits of meditation and yoga"❌ NoneHealth (38%)
"Patient Jane Doe (SSN: 123-45-6789)"✅ Jane Doe, 123-45-6789, jane.doe@hospital.comEducation (41%)
"learn programming? I want to learn Python"❌ NoneEducation (53%)
"legal to record phone calls in California?"❌ NonePolitics (64%)

Files

FileSizeDescription
model.safetensors2.6 GBBackbone + NER head (1.4B MoE params)
doc_head.pt26 KBDocument classification head (640→10)
config.json3 KBModel architecture config
tokenizer.json27 MBBPE tokenizer (o200k_base)
multitask_config.json349 BMulti-task metadata