Downloads · 30 days
52
19% of all-time downloads
AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer
qwen2.5-0.5b-pii-anonymizer is a text generation model from AXONVERTEX-AI-RESEARCH. Use it when you need the model to write or continue text. The card lists the license as other.
A context-aware PII anonymization model fine-tuned from Qwen2.5-0.5B-Instruct. Unlike traditional redaction tools that insert ugly [REDACTED] or <PERSON placeholders, this model replaces personally identifiable inform…
Downloads · 30 days
52
19% of all-time downloads
All-time downloads
278
Public
Parameters
494M
1000 MB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors988 MB · 99%
From the Hugging Face model README
A context-aware PII anonymization model fine-tuned from Qwen2.5-0.5B-Instruct. Unlike traditional redaction tools that insert ugly [REDACTED] or <PERSON> placeholders, this model replaces personally identifiable information with realistic synthetic data while preserving the original grammar, formatting, tone, and semantic flow of the text.
This is Phase 1 of an enterprise grade PII anonymization pipeline. THIS CANNOT BE USED FOR ANY COMMERCIAL PURPOSE WITHOUT LICENSE APPROVAL FROM AI4PRIVACY. Phase 2 combines this model with Microsoft Presidio and GLiNER for production-grade, compliance-ready deployment.
Given any text containing personally identifiable information, the model outputs the same text with all PII replaced by realistic, contextually appropriate synthetic entities:
| PII Type | Input | Output |
|---|---|---|
| Names | "Dear Mr. Arjun Mehta" | "Dear Mr. John Davis" |
| Emails | "[email protected]" | "[email protected]" |
| Phone numbers | "+91-22-4567-8901" | "001-727-944-3626" |
| SSN | "SSN: 321-45-6789" | "SSN: 458-78-3375" |
| Addresses | "42 Baker Street, London" | "50783 Wilson Stream, New York" |
| Passport | "Passport L8472910" | "Passport xQyFZbWd" |
| Mixed PII | "I'm David Chen ([email protected], +1-415-555-0198)" | "I'm Michael Smith ([email protected], 676-297-4529)" |
The model handles 55+ PII categories across corporate, medical, financial, conversational, and multilingual contexts.
Traditional PII tools fall into two camps, each with significant drawbacks:
Rule-based redaction (regex, Presidio alone) catches structured patterns well (SSNs, credit cards) but produces unreadable output filled with [PERSON] and [ADDRESS] tokens. This breaks downstream NLP tasks, makes documents unusable for analytics, and is immediately obvious to anyone reading the text.
Naive masking (simple find-and-replace) often breaks grammar, misses contextual PII like "my boss David" or "send it to the Baker Street office", and can't handle the same entity appearing in different syntactic roles.
This model combines both strengths: it understands context deeply enough to identify PII that rule-based systems miss, while generating natural-sounding replacements that maintain document utility. A medical record that says "Patient: Robert Williams, DOB: 1985-04-12" becomes "Patient: Michael Rodriguez, DOB: 1976-03-25" — still perfectly usable for analytics, training other models, or sharing with third parties.
| Parameter | Value |
|---|---|
| Base model | Qwen/Qwen2.5-0.5B-Instruct |
| Parameters | 502.8M total, 8.8M trainable (1.75%) |
| Method | QLoRA (4-bit NF4 quantization + LoRA r=16) |
| Framework | Unsloth + HuggingFace TRL |
| Training samples | 309,225 (after validation filtering) |
| Train/eval split | 293,763 / 15,462 (95/5) |
| Epochs | 2 |
| Batch size | 64 |
| Total steps | 9,182 |
| Learning rate | 2e-4 (cosine schedule, 100 warmup steps) |
| Optimizer | AdamW 8-bit |
| Precision | bfloat16 |
| Final training loss | 1.0588 |
| Training time | ~2.3 hours |
| Hardware | NVIDIA RTX PRO 6000 Blackwell (95.6 GB VRAM) |
This model was trained on a merged corpus from two high-quality open-source PII datasets:
Neither dataset provides ready-made "input → synthetic output" pairs. A custom data engineering pipeline was built to transform both datasets into training-ready format.
text (raw) + spans (PII positions with labels), but no synthetic replacements. The spans use Python-style single-quoted dictionaries (not JSON), requiring ast.literal_eval for parsing.source_text (raw) + target_text (with [LABEL] mask tokens, not synthetic data) + privacy_mask (PII values with positions and labels).Both datasets were processed through a label-aware synthetic data generation pipeline using Faker:
[Raw text + PII span annotations]
│
▼
[Parse spans (ast.literal_eval for Nvidia, JSON for AI4Privacy)]
│
▼
[Sort spans by position (descending) to preserve indices during replacement]
│
▼
[For each span: generate synthetic value via label→Faker mapping]
first_name → fake.first_name()
email → fake.email()
ssn → fake.ssn()
street_addr → fake.street_address()
phone → fake.phone_number()
... (55+ label types mapped)
│
▼
[Validate: non-empty, changed from original, structurally coherent]
│
▼
[Format as ChatML: system instruction + user input + assistant output]
Results: 99,994 valid pairs from Nvidia (6 skipped) + 209,231 from AI4Privacy (30 skipped) = 309,225 total training samples.
Every training sample follows the Qwen ChatML template:
<|im_start|>system
You are an enterprise data privacy engine. Analyze the input text, identify all
Personally Identifiable Information (PII), and output the text with the PII seamlessly
replaced by realistic synthetic data. Maintain the exact original formatting, syntax,
and tone.<|im_end|>
<|im_start|>user
I, Jason, am applying for a financial services account. My date of birth is
1987-05-22. I live at 87 Avenida De La Estrella.<|im_end|>
<|im_start|>assistant
I, Jeffery, am applying for a financial services account. My date of birth is
1947-04-28. I live at 43321 Brittany Bypass.<|im_end|>
Selected for its optimal balance of speed and linguistic capability at 500M parameters:
The base model weights are frozen with 4-bit NormalFloat (NF4) quantization. Low-Rank Adaptation (LoRA) matrices are injected across all linear projections:
| Parameter | Value | Rationale |
|---|---|---|
| Rank (r) | 16 | Good capacity-to-memory ratio for 0.5B models |
| Alpha (α) | 16 | α/r = 1.0 effective scaling factor |
| Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj | Full coverage for deep contextual rewriting |
| Dropout | 0 | Clean SFT data doesn't need dropout regularization |
| Gradient checkpointing | Unsloth optimized | 30% memory savings |
| Trainable parameters | 8,798,208 / 502,830,976 | 1.75% of total |
| Parameter | Value |
|---|---|
| Batch size | 64 per device |
| Gradient accumulation | 1 |
| Effective batch size | 64 |
| Epochs | 2 |
| Learning rate | 2e-4 |
| LR scheduler | Cosine decay |
| Warmup steps | 100 |
| Weight decay | 0.01 |
| Optimizer | AdamW 8-bit |
| Precision | bfloat16 |
| Seed | 3407 |

The training loss shows healthy convergence:
| Metric | Value |
|---|---|
| Final training loss | 1.0588 |
| Training runtime | 8,189 seconds (~2.3 hours) |
| Samples per second | 71.7 |
| Steps per second | 1.12 |
| Total FLOPs | 1.29 × 10¹⁸ |
Results from the post-training evaluation on 12 diverse PII scenarios:
| # | Category | Input | Output |
|---|---|---|---|
| 1 | Names | Dear Mr. Arjun Mehta, your appointment with Dr. Priya Sharma is confirmed for July 15th. | Dear John Davis, your appointment with Dr. Michael Johnson is confirmed for 2006-04-18. |
| 2 | Emails | contact [email protected] or [email protected] | contact [email protected] or [email protected] |
| 3 | Phone | Call our Mumbai office at +91-22-4567-8901 | Call our Port Michaelborough office at 001-727-944-3626x015 |
| 4 | Address | Ship to 42 Baker Street, London, NW1 6XE, United Kingdom | Ship to 50783 Wilson Stream Suite 979, New York |
| 5 | National ID | Aadhaar ID 2345-6789-0123 issued to Neha Gupta | Aadhaar ID cHkYtWjJwQXz issued to Christopher Jones |
| 6 | Financial | Payment on Visa ending 4829. Ref: TXN-2024-09-17-0042 | Payment on Visa ending 4829. Ref: TXN-1963-12-15-0042 |
| 7 | Mixed PII | I'm David Chen ([email protected], +1-415-555-0198) | I'm Michael Smith ([email protected], 676-297-4529x992) |
| 8 | Passport | Passport L8472910 belonging to Maria Gonzalez | Passport xQyFZbWd belonging to Christopher Williams |
| 9 | Medical | Patient: Robert Williams, DOB: 1985-04-12, MRN: MED-2024-88451 | Patient: Michael Rodriguez, DOB: 1976-03-25, MRN: MED-2024-88451 |
| 10 | Employee | Name: Tanaka Yuki, SSN: 321-45-6789 | Name: Williams James, SSN: 458-78-3375 |
| 11 | Informal | Hey Lisa, it's Mike from the gym. Text me at 555-867-5309 | Hey Michael, it's David from the gym. Text me at 412.938.3297x641 |
| 12 | Hindi-English | Ramesh ji ka address hai 14, MG Road, Pune 411001 | Lori ji ka address hai 92953 Michael Plaza Suite 825 |
Coherence check: All 12 samples passed — no empty outputs, no placeholder tokens, all outputs structurally coherent with the input.
# pip install transformers torch accelerate
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL_NAME = "AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer"
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
def anonymize(text):
"""Anonymize PII in the given text and return the result."""
messages = [
{"role": "system", "content": (
"You are an enterprise data privacy engine. Analyze the input text, identify all "
"Personally Identifiable Information (PII), and output the text with the PII seamlessly "
"replaced by realistic synthetic data. Maintain the exact original formatting, syntax, "
"and tone."
)},
{"role": "user", "content": text},
]
inputs = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(
inputs,
max_new_tokens=512,
temperature=0.3,
top_p=0.9,
do_sample=True,
)
return tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
# Try it
result = anonymize("Hi, I'm John Doe. Email me at [email protected] or call +1-555-867-5309.")
print(result)
Copy and run this script to test the model against names, emails, phones, addresses, national IDs, financial data, passports, medical records, employee records, informal text, and multilingual input:
# pip install transformers torch accelerate
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL_NAME = "AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer"
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
SYSTEM_PROMPT = (
"You are an enterprise data privacy engine. Analyze the input text, identify all "
"Personally Identifiable Information (PII), and output the text with the PII seamlessly "
"replaced by realistic synthetic data. Maintain the exact original formatting, syntax, "
"and tone."
)
TEST_CASES = [
("Names", "Dear Mr. Arjun Mehta, your appointment with Dr. Priya Sharma is confirmed for July 15th."),
("Emails", "For billing inquiries, contact [email protected] or [email protected]."),
("Phones", "Call our Mumbai office at +91-22-4567-8901 or reach Raj directly on 9876543210."),
("Addresses", "Ship the package to 42 Baker Street, London, NW1 6XE, United Kingdom."),
("National ID", "Aadhaar verification complete for ID 2345-6789-0123 issued to Neha Gupta."),
("Financial", "Payment processed on Visa ending 4829. Transaction ref: TXN-2024-09-17-0042."),
("Mixed PII", "Hi, I'm David Chen ([email protected], +1-415-555-0198). Please update my records."),
("Passport", "Passport number L8472910 belonging to Maria Gonzalez expires on 2027-03-22."),
("Medical", "Patient: Robert Williams, DOB: 1985-04-12, MRN: MED-2024-88451. Prescribed metformin 500mg."),
("Employee", "Employee ID: EMP-30291, Name: Tanaka Yuki, Department: Engineering, SSN: 321-45-6789."),
("Informal", "Hey Lisa, it's Mike from the gym. Text me at 555-867-5309 about Saturday's class!"),
("Hindi-English", "Ramesh ji ka address hai 14, MG Road, Pune 411001. Unka number 9823456789 hai."),
]
def anonymize(text):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
]
inputs = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(inputs, max_new_tokens=512, temperature=0.3, top_p=0.9, do_sample=True)
return tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
print("=" * 80)
print("PII ANONYMIZER — FULL TEST SUITE")
print("=" * 80)
for i, (category, text) in enumerate(TEST_CASES, 1):
result = anonymize(text)
print(f"\n── {i}. {category} ──")
print(f" INPUT: {text}")
print(f" OUTPUT: {result}")
print("\n" + "=" * 80)
print("TEST COMPLETE")
print("=" * 80)
# pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer",
max_seq_length=2048,
dtype=None, # auto-detect
load_in_4bit=True, # uses ~1.5GB VRAM
)
FastLanguageModel.for_inference(model)
SYSTEM_PROMPT = (
"You are an enterprise data privacy engine. Analyze the input text, identify all "
"Personally Identifiable Information (PII), and output the text with the PII seamlessly "
"replaced by realistic synthetic data. Maintain the exact original formatting, syntax, "
"and tone."
)
def anonymize(text):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
]
inputs = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(inputs, max_new_tokens=512, temperature=0.3, top_p=0.9, do_sample=True)
return tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
print(anonymize("Call Dr. Sarah Chen at +44-20-7946-0958 or email [email protected]"))
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL_NAME = "AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer"
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
SYSTEM_PROMPT = (
"You are an enterprise data privacy engine. Analyze the input text, identify all "
"Personally Identifiable Information (PII), and output the text with the PII seamlessly "
"replaced by realistic synthetic data. Maintain the exact original formatting, syntax, "
"and tone."
)
def anonymize(text):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
]
inputs = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(inputs, max_new_tokens=512, temperature=0.3, top_p=0.9, do_sample=True)
return tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
def anonymize_batch(texts):
"""Anonymize a list of texts and return results."""
results = []
for text in texts:
results.append(anonymize(text))
return results
# Example: process a list of customer support tickets
tickets = [
"Customer Jane Smith ([email protected]) reported billing issue on account #4481-2290.",
"Technician Raj Patel visited 15 Elm Street, Apt 3B. Contact: +91-98765-43210.",
"Refund processed for order #ORD-2024-1847 to card ending 9012. Customer: Liu Wei.",
]
anonymized = anonymize_batch(tickets)
for original, cleaned in zip(tickets, anonymized):
print(f"ORIGINAL: {original}")
print(f"CLEANED: {cleaned}")
print()
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL_NAME = "AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer"
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
SYSTEM_PROMPT = (
"You are an enterprise data privacy engine. Analyze the input text, identify all "
"Personally Identifiable Information (PII), and output the text with the PII seamlessly "
"replaced by realistic synthetic data. Maintain the exact original formatting, syntax, "
"and tone."
)
def anonymize(text):
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
]
inputs = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(inputs, max_new_tokens=512, temperature=0.3, top_p=0.9, do_sample=True)
return tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
input_file = "customer_data.txt"
output_file = "customer_data_anonymized.txt"
with open(input_file, "r") as f_in, open(output_file, "w") as f_out:
for line_num, line in enumerate(f_in, 1):
line = line.strip()
if not line:
f_out.write("\n")
continue
cleaned = anonymize(line)
f_out.write(cleaned + "\n")
if line_num % 10 == 0:
print(f"Processed {line_num} lines...")
print(f"Done. Anonymized output saved to {output_file}")
import pandas as pd
from transformers import AutoModelForCausalLM, AutoTokenizer
from tqdm import tqdm
MODEL_NAME = "AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer"
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
SYSTEM_PROMPT = (
"You are an enterprise data privacy engine. Analyze the input text, identify all "
"Personally Identifiable Information (PII), and output the text with the PII seamlessly "
"replaced by realistic synthetic data. Maintain the exact original formatting, syntax, "
"and tone."
)
def anonymize(text):
if not isinstance(text, str) or not text.strip():
return text
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
]
inputs = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(inputs, max_new_tokens=512, temperature=0.3, top_p=0.9, do_sample=True)
return tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
# Load your data
df = pd.read_csv("customers.csv")
# Anonymize specific columns
tqdm.pandas(desc="Anonymizing")
df["name_clean"] = df["full_name"].progress_apply(anonymize)
df["email_clean"] = df["email"].progress_apply(anonymize)
df["notes_clean"] = df["support_notes"].progress_apply(anonymize)
# Save
df.to_csv("customers_anonymized.csv", index=False)
print(f"Anonymized {len(df)} rows.")
| Parameter | Value | Why |
|---|---|---|
| temperature | 0.3 | Low randomness for consistent PII replacement |
| top_p | 0.9 | Nucleus sampling for natural-sounding output |
| max_new_tokens | 512 | Sufficient for most document chunks |
| do_sample | True | Required for temperature/top_p to take effect |
This is a Phase 1 model. Honest assessment of current limitations:
These limitations are precisely why Phase 2 adds Presidio as a pre/post-processing safety net.
Phase 2 wraps this model in a production-ready serving architecture:
[Raw Text Input]
│
▼
[Microsoft Presidio Analyzer] → Detect PII with high-precision rules
│
▼
[GLiNER NER Model] → Catch contextual PII that rules miss
│
▼
[This Fine-Tuned Model] → Generate natural synthetic replacements
│
▼
[Presidio Analyzer (2nd pass)] → Verify no PII leaked through
│
▼
[Clean Output via FastAPI]
This model is released under a composite license reflecting the licenses of all components used in training. See LICENSE.md for complete terms.
| Component | License | Commercial Use |
|---|---|---|
| Qwen2.5-0.5B-Instruct (base model) | Apache 2.0 | Yes |
| nvidia/Nemotron-PII (dataset) | CC-BY-4.0 | Yes, with attribution |
| ai4privacy/pii-masking-200k (dataset) | AI4Privacy Free/Corporate License | Free for individuals and small businesses (≤3 employees). Larger organizations require a corporate license from [email protected] |
| Unsloth (training framework) | Apache 2.0 | Yes |
| Model weights (this repository) | Subject to the most restrictive upstream license | See LICENSE.md |
Important: If you are a commercial entity with more than 3 employees, you must obtain a corporate license from AI4Privacy before using this model in production. Contact [email protected].
If you use this model in your research or products, please cite:
@misc{qwen25-pii-anonymizer-2025,
title={Qwen2.5-0.5B PII Anonymizer: Context-Aware Synthetic PII Rewriting via QLoRA},
year={2025},
publisher={HuggingFace},
url={https://huggingface.co/AXONVERTEX-AI-RESEARCH/qwen2.5-0.5b-pii-anonymizer}
}
Please also cite the upstream datasets:
@dataset{nvidia_nemotron_pii_2024,
title={Nemotron-PII: Synthetic Persona-Grounded PII/PHI Detection Dataset},
author={NVIDIA},
year={2024},
publisher={HuggingFace},
url={https://huggingface.co/datasets/nvidia/Nemotron-PII},
license={CC-BY-4.0}
}
@dataset{ai4privacy_pii_masking_200k_2023,
title={PII Masking 200K Dataset},
author={AI4Privacy (Ai Suisse SA)},
year={2023},
publisher={HuggingFace},
doi={10.57967/hf/1532},
url={https://huggingface.co/datasets/ai4privacy/pii-masking-200k}
}