rulesentry-io/ettin-32m-nemotron-pii-onnx
ettin-32m-nemotron-pii-onnx
fp32 ONNX export of [`kalyan-ks/ettin-32m-nemotron-pii`](https://huggingface.co/kalyan-ks/ettin-32m-nemotron-pii) | 32M Parameters | 55 PII Entity Types | ~128 MB (122.6 MiB)
This is an ONNX export of the ettin-32m-nemotron-pii model, sized for browser and edge deployment via onnxruntime-web. Produced by Mycos Technologies, Co., Ltd. for use in RuleSentry as the NER companion to its in-browser deterministic-rule engine. For server-side or higher-recall deployments, see the larger sibling `rulesentry-io/ettin-68m-nemotron-pii-onnx`.
Overview
ettin-32m-nemotron-pii is a ModernBERT-based encoder fine-tuned on NVIDIA's synthetic Nemotron-PII dataset. This is an fp32 (unquantized) ONNX export of that model. Refer to the upstream model card for evaluation numbers.
Intended use case: contextual entity detection (names, locations, demographics, dates) to complement deterministic PII rules — not as a standalone PII redactor. Structured PII types (SSNs, credit cards, IPs, MACs, emails, phone numbers, API keys, IBANs, etc.) have well-defined formats and are better handled by regex/format validation. This model excels at the fuzzy linguistic categories where rules cannot reach.
Why ONNX at 32M?
- Browser-deployable — ~128 MB (122.6 MiB) fp32 download fits within reasonable browser-cache budgets and runs in
onnxruntime-web(WASM) on the client. The 68M sibling at ~270 MB is heavier than needed for browser/edge use; the 32M is the size that keeps the linguistic categories sharp while staying light. - Modest CPU speedup over PyTorch via ONNX Runtime graph optimizations
- No PyTorch dependency at runtime
- Native integration with non-Python runtimes (Rust, C#, Java, Go, JavaScript via WebAssembly, etc.)
The graph takes two inputs (input_ids, attention_mask) and exposes one output (logits). It was exported with optimum-cli using the ModernBERT-specific ONNX configuration, so token_type_ids are omitted from both the graph and the bundled tokenizer config.
Usage
With Optimum + ONNX Runtime (Python)
from optimum.onnxruntime import ORTModelForTokenClassification
from transformers import AutoTokenizer, pipeline
model_id = "rulesentry-io/ettin-32m-nemotron-pii-onnx"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = ORTModelForTokenClassification.from_pretrained(model_id)
ner = pipeline(
"token-classification",
model=model,
tokenizer=tokenizer,
aggregation_strategy="simple",
device=-1, # pin to CPU
)
text = "Sarah Chen lives in San Francisco, California. She works at Acme Corp."
entities = ner(text)
print(entities)In the browser (onnxruntime-web)
import * as ort from "onnxruntime-web";
const session = await ort.InferenceSession.create(
"https://huggingface.co/rulesentry-io/ettin-32m-nemotron-pii-onnx/resolve/main/model.onnx",
{ executionProviders: ["wasm"] }
);
// Tokenize input separately (e.g. via @huggingface/transformers tokenizer module
// or a hand-written tokenizer that reads tokenizer.json from the same repo), then:
const outputs = await session.run({ input_ids, attention_mask });
const logits = outputs.logits.data; // [batch, seq_len, num_labels] flatThe model file is ~128 MB (122.6 MiB). Browser caching (HTTP cache, IndexedDB, or OPFS) makes the second-load instant.
With ONNX Runtime directly (Python)
import onnxruntime as ort
from transformers import AutoTokenizer
import numpy as np
model_id = "rulesentry-io/ettin-32m-nemotron-pii-onnx"
tokenizer = AutoTokenizer.from_pretrained(model_id)
sess_options = ort.SessionOptions()
sess_options.intra_op_num_threads = 4
session = ort.InferenceSession("model.onnx", sess_options=sess_options,
providers=["CPUExecutionProvider"])
text = "John Smith lives at 42 Elm Street, Boston."
inputs = tokenizer(text, return_tensors="np")
outputs = session.run(None, dict(inputs))
logits = outputs[0]Using GPU (Python)
pip install "optimum[onnxruntime-gpu]" transformersThen pass device=0 to the pipeline, or set providers=["CUDAExecutionProvider", "CPUExecutionProvider"] on a direct InferenceSession. The trailing CPUExecutionProvider lets ORT degrade gracefully if CUDA initialization fails at runtime.
Install (CPU): pip install "optimum[onnxruntime]" transformersEvaluation
Export fidelity
The published ONNX artifact reproduces its PyTorch parent. On 10,000 nvidia/Nemotron-PII test samples the fp32 ONNX export and the PyTorch source produce identical scores to the displayed precision — exact-span per-entity Δ is +0.00 across 31 of 32 entities, with a single +0.09 on date_time (floating-point argmax tie-break, not a defect). ONNX Runtime also ran ~20% faster than PyTorch on CPU.
Exact-span requires (start, end, label) to match the gold annotation exactly (no partial credit). Character-level overlap gives partial credit per correctly-labeled character. PyTorch scores identically on both.
What is being scored: the active entity set
These numbers cover the 32 linguistic PII categories RuleSentry surfaces in-browser (names, locations, demographics, dates, employment) — not all 55 the model can emit. RuleSentry suppresses 23 structured categories (SSN, credit card, IP, MAC, email, API key, SWIFT/BIC, …) by default and routes them to a deterministic rule engine that detects format-bound identifiers more reliably than a neural model. The evaluation reflects that deployment configuration. (Scoring all 55 lowers the aggregate, because the model's exact-span recall on structured types is poor — e.g. national_id scores 0.00 here even with partial credit — which is exactly why those types are delegated to rules.)
Why this differs from the upstream ~95.7
The upstream model card and article report F1 ~95.7. The difference is scoring methodology and entity scope, not export quality — the same PyTorch model scores the same as the ONNX export here:
- Entity scope — we score only the 32 active (linguistic) types; several excluded structured types are among the model's highest-scoring entities upstream, so excluding them lowers the aggregate by design.
- Exact-span strictness — our primary metric gives no partial credit. The char-level number (89.43) is the partial-credit view; on multi-token entities it closes most of the gap (e.g.
coordinate61→94,occupation30→61). - Entity-only scoring — both our metrics exclude the "O" (non-PII) class, reflecting only entity spans rather than the bulk of ordinary non-PII text.
The takeaway: on the fuzzy linguistic categories this model is meant for, it performs well; on structured identifiers, deterministic rules are categorically more reliable — so RuleSentry uses each where it is strongest rather than relying on the NER model alone.
Always evaluate on representative samples of your own data before deploying. Full per-entity numbers and the character-level partial-credit cross-check are in `EVAL_RESULTS_32M.md` in the evaluation repo.
How this model sizes up against its sibling
The 32M model is published here as the sweet spot for browser/edge deployment — small enough to download in a few seconds, large enough to handle the linguistic categories. For server-side or higher-recall deployments, use the 68M sibling.
Supported PII Entity Types
This model detects 55 PII entity types across structured and unstructured text:
For applications where structured identifiers (ipv4, mac_address, credit_debit_card, ssn, etc.) must be detected with very high recall, supplement this model with deterministic regex/format validation. These entity types have well-defined formats that pattern matching handles more reliably than any neural model. RuleSentry uses this hybrid approach: deterministic rules own the structured categories, and this NER model covers the linguistic ones.
Model Lineage & Credits
This repository contains an ONNX export produced by RuleSentry.IO. The original model and all training were done upstream:
All upstream components are licensed under MIT.
Limitations
Limitations below are inherited from the upstream PyTorch model. Refer to the upstream model card for full evaluation numbers and known caveats.
- English only — the model is trained on English-language text and performs poorly on other languages.
- Occupation entity —
occupationhas a known low F1 score in upstream evaluations and should be treated with caution. - Synthetic training data — trained on NVIDIA's synthetic Nemotron-PII dataset; real-world distributions (especially niche domains) may yield lower performance. Evaluate on representative samples of your own data before deploying.
- Context length — very long documents should be chunked before inference.
- Not a legal compliance tool — PII detection is probabilistic. Do not use as a sole control for regulatory compliance (GDPR, HIPAA, CCPA) without human review.
About
This model is maintained by [Mycos Technologies, Co., Ltd.](https://www.mycostech.com), a Thai software company building privacy and data governance tooling. It is part of the RuleSentry platform, which provides automated PII detection and data compliance infrastructure.
- 🌐 Product: rulesentry.io
- 🤗 HuggingFace org: rulesentry-io
- 🛠️ Evaluation tooling: github.com/rulesentry/ettin-pii-onnx
Citation
If you use this model, please cite the upstream fine-tuned model and dataset:
@misc{ettin-32m-pii-2026,
title = {ettin-32m-nemotron-pii-2026: PII Detection Model},
author = {Kalyan KS},
year = {2026},
publisher = {Hugging Face},
url = {https://huggingface.co/kalyan-ks/ettin-32m-nemotron-pii}
}
@misc{nvidia2025nemotronpii,
title = {Nemotron-PII: Synthesized Data for Privacy-Preserving AI},
author = {NVIDIA},
year = {2025},
url = {https://huggingface.co/datasets/nvidia/Nemotron-PII}
}This ONNX export:
@misc{rulesentry2026ettin32m-onnx,
title = {ettin-32m-nemotron-pii-onnx: Browser-Deployable ONNX Export for In-Browser PII NER},
author = {RuleSentry.IO},
year = {2026},
publisher = {Hugging Face},
url = {https://huggingface.co/rulesentry-io/ettin-32m-nemotron-pii-onnx}
}