Skiipy commited on
Commit
1b3e90a
·
verified ·
1 Parent(s): d122812

Add OSSRedact PII NER v11r9c weights + model card (bilingual FR/EN, MIT)

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ banner.png filter=lfs diff=lfs merge=lfs -text
37
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - fr
5
+ - en
6
+ library_name: transformers.js
7
+ pipeline_tag: token-classification
8
+ base_model: FacebookAI/xlm-roberta-base
9
+ tags:
10
+ - pii
11
+ - redaction
12
+ - privacy
13
+ - ner
14
+ - token-classification
15
+ - french
16
+ - quebec
17
+ - onnx
18
+ - int8
19
+ - gdpr
20
+ - law-25
21
+ ---
22
+
23
+ # OSSRedact PII NER -- xlm-roberta-base (CPU / in-browser tier)
24
+
25
+ ![OSSRedact PII (base) -- in-browser bilingual FR/EN PII + secrets detection](banner.png)
26
+
27
+ **A bilingual (French-Québec + English) PII / secrets token-classifier**, dynamic-INT8 ONNX -- the always-on
28
+ detection model behind [OSSRedact](https://github.com/ZenSystemAI/OSSRedact), a local privacy gateway that
29
+ redacts private data before it reaches a cloud LLM and rehydrates it on the reply.
30
+
31
+ Shipping revision: **`v11r9c`** (carries the cumulative organization/address augmentation; address recall is now
32
+ ~0.93 on this tier). The higher-capacity tier is
33
+ [`ZenSystemAI/ossredact-pii-large`](https://huggingface.co/ZenSystemAI/ossredact-pii-large).
34
+
35
+ ![OSSRedact vs Microsoft Presidio on Québec FR/EN PII](fig5_vs_presidio.png)
36
+
37
+ ![Recall by tier](fig1_recall_by_tier.png)
38
+
39
+ *OSSRedact recall vs Microsoft Presidio (historical v6/v7 sets), and recall by tier. The base model nearly
40
+ matches the large model on recall (trailing by ~1 point on overall recall) at roughly 4x lower latency -- which
41
+ is why it is the always-on tier.*
42
+
43
+ ## What it is
44
+
45
+ A `xlm-roberta-base` token classifier fine-tuned to tag **20 PII / secret entity types** in realistic French-
46
+ Québec and English documents, exported to **dynamic-INT8 ONNX (~277 MB)** for CPU (onnxruntime) and **in-browser**
47
+ (transformers.js / onnxruntime-web) inference. The carded numbers below are the fp32 `v11r9c` reference; the
48
+ shipped artifact is the **per-channel dynamic INT8** export (WASM-native). v11r9c's org/address augmentation
49
+ sharpened the boundaries, so the INT8 lands at pii_argmax 0.967 (cosine 0.997, faithful) -- the parity bar is
50
+ 0.965 for this reason: ~62% of the token-flips are on floor-protected types the deterministic Tier-0 layer
51
+ redacts regardless of the model, and person (the highest-frequency no-floor type) is barely affected.
52
+ It is the always-on detection tier of OSSRedact; in production it
53
+ runs **inside** the OSSRedact gateway alongside a deterministic Tier-0 floor. Detection runs **locally** -- no
54
+ call leaves the machine; in the browser, the document never leaves the page.
55
+
56
+ The bilingual Québec-French focus is the differentiator: general English-first PII detectors miss FR structure
57
+ (NEQ, RAMQ, SIN, FR letterhead, accented ALL-CAPS names).
58
+
59
+ ## Labels (20)
60
+
61
+ `account_number`, `address`, `card_cvv`, `card_expiry`, `date_of_birth`, `email`, `file_path`, `government_id`,
62
+ `iban`, `ip_address`, `organization`, `password`, `payment_card`, `person`, `phone_number`, `postal_code`,
63
+ `secret`, `sensitive_account_id`, `tax_id`, `username` (41 BIO label ids).
64
+
65
+ ## Intended use
66
+
67
+ - **Primary:** the always-on detection tier inside the OSSRedact gateway (CPU), and the in-browser redaction
68
+ workbench (transformers.js).
69
+ - **Also:** on-device / edge PII detection where a ~277 MB INT8 model and CPU latency matter.
70
+
71
+ > **Use it with a deterministic floor.** As a standalone NER model, recall is below 100%. On this base tier
72
+ > `address` recall is now ~0.93 (no longer weak), but `organization` coverage may still trail the large tier --
73
+ > use the [large tier](https://huggingface.co/ZenSystemAI/ossredact-pii-large) when organization recall matters.
74
+ > OSSRedact's hard guarantee for the catastrophic categories (secrets, cards via Luhn, IBANs, government IDs,
75
+ > emails, IPs, file paths) comes from a Tier-0 floor that runs *independently* of this model.
76
+
77
+ ### Quick start (browser, transformers.js)
78
+
79
+ ```js
80
+ import { pipeline } from '@huggingface/transformers'
81
+ // dtype:'int8' loads onnx/model_int8.onnx -- this repo ships INT8 only (the WASM-native browser format)
82
+ const ner = await pipeline('token-classification', 'ZenSystemAI/ossredact-pii-base', { dtype: 'int8' })
83
+ const out = await ner('Contactez Marie-Eve Tremblay au 514-555-0188; NAS 046 454 286.')
84
+ // out: [{ entity, score, word, start, end }, ...] -- the document never leaves the page
85
+ ```
86
+
87
+ ### Quick start (Python, onnxruntime via optimum)
88
+
89
+ ```python
90
+ from optimum.onnxruntime import ORTModelForTokenClassification
91
+ from transformers import AutoTokenizer, pipeline
92
+
93
+ tok = AutoTokenizer.from_pretrained("ZenSystemAI/ossredact-pii-base")
94
+ # the repo ships INT8 only (model.int8.onnx at the root); name it explicitly
95
+ model = ORTModelForTokenClassification.from_pretrained("ZenSystemAI/ossredact-pii-base", file_name="model.int8.onnx")
96
+ ner = pipeline("token-classification", model=model, tokenizer=tok)
97
+ print(ner("Reçu de la Caisse Desjardins; IBAN GB82 WEST 1234 5698 7654 32."))
98
+ ```
99
+
100
+ ## Training data
101
+
102
+ A **100% synthetic** French-Québec + English corpus (bank statements, financing forms, email threads, CSV
103
+ exports, `.env` files, code, KYC/tax/SAAQ/RAMQ documents). Every name, SIN, account, card, and secret is
104
+ fabricated. It deliberately includes adversarial cases (ALL-CAPS, NBSP-separated IDs, mixed FR/EN, long unbroken
105
+ lines, look-alike decoys). Same corpus and recipe as the large tier; this is the `v11r9c` revision, trained on the
106
+ cumulative corpus including the organization/address augmentation.
107
+
108
+ ## Evaluation
109
+
110
+ Synthetic held-out corpus (7,498 rows, 0 train overlap). Privacy metric = full-stack catastrophic DETECTION
111
+ recall; `clean_fp` = over-redaction on no-PII rows.
112
+
113
+ | tier | catastrophic full-stack DETECTION | all-label recall | precision | clean_fp |
114
+ |------|-----------------------------------|------------------|-----------|----------|
115
+ | **CPU / base (v11r9c)** | **0.9941** | 0.9777 | 0.9139 | 48 / 7498 |
116
+
117
+ The base model nearly matches the large model on overall recall (trailing by ~1 point: 0.9777 vs 0.9882) at
118
+ ~4x lower latency -- the reason it is the always-on tier. `address` recall is now ~0.93 here vs 0.95 on large;
119
+ `organization` coverage may still trail the large tier, so use the
120
+ [large tier](https://huggingface.co/ZenSystemAI/ossredact-pii-large) when organization recall matters.
121
+
122
+ Training recipe: `xlm-roberta-base` (277 M), batch size 8, learning rate 2e-5, max length 512, 3 epochs,
123
+ `metric_for_best_model=cat_f1`. Figures above are the fp32 `v11r9c` reference; the shipped artifact is the
124
+ per-channel dynamic-INT8 ONNX (~277 MB), pii_argmax 0.967 vs fp32 (parity bar 0.965 -- see the model card's
125
+ INT8 note and validation/RESULT-base-int8-parity-v11r9c.md).
126
+
127
+ ## Limitations
128
+
129
+ - Trained and validated entirely on **synthetic Québec** data; broader real-world domains are future work.
130
+ - **French and English only** by design.
131
+ - On this base tier, **`organization` coverage may still trail the large tier** (`address` recall is now ~0.93,
132
+ no longer weak) -- use the large tier when organization recall matters, and in all cases pair with OSSRedact's
133
+ deterministic floor for the catastrophic categories.
134
+ - Identifier coverage targets **Canadian / Québec** formats. Foreign formats (US ZIP, Brazilian CPF) are not
135
+ specifically targeted.
136
+ - Recall is below 100%; this model is one layer of a redaction system, not a standalone guarantee.
137
+
138
+ ## License & links
139
+
140
+ MIT. Part of [OSSRedact](https://github.com/ZenSystemAI/OSSRedact) by ZenSystemAI. The version label `v11rN`
141
+ is the weight revision (an HF revision tag), not part of the repo id.
banner.png ADDED

Git LFS Details

  • SHA256: c34a67077359514e553fce40533da0dba8fe0284d744df9b6617d23036b650c1
  • Pointer size: 132 Bytes
  • Size of remote file: 2.69 MB
config.json ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_cross_attention": false,
3
+ "architectures": [
4
+ "XLMRobertaForTokenClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "bos_token_id": 0,
8
+ "classifier_dropout": null,
9
+ "dtype": "float32",
10
+ "eos_token_id": 2,
11
+ "hidden_act": "gelu",
12
+ "hidden_dropout_prob": 0.1,
13
+ "hidden_size": 768,
14
+ "id2label": {
15
+ "0": "O",
16
+ "1": "B-account_number",
17
+ "2": "I-account_number",
18
+ "3": "B-address",
19
+ "4": "I-address",
20
+ "5": "B-card_cvv",
21
+ "6": "I-card_cvv",
22
+ "7": "B-card_expiry",
23
+ "8": "I-card_expiry",
24
+ "9": "B-date_of_birth",
25
+ "10": "I-date_of_birth",
26
+ "11": "B-email",
27
+ "12": "I-email",
28
+ "13": "B-file_path",
29
+ "14": "I-file_path",
30
+ "15": "B-government_id",
31
+ "16": "I-government_id",
32
+ "17": "B-iban",
33
+ "18": "I-iban",
34
+ "19": "B-ip_address",
35
+ "20": "I-ip_address",
36
+ "21": "B-organization",
37
+ "22": "I-organization",
38
+ "23": "B-password",
39
+ "24": "I-password",
40
+ "25": "B-payment_card",
41
+ "26": "I-payment_card",
42
+ "27": "B-person",
43
+ "28": "I-person",
44
+ "29": "B-phone_number",
45
+ "30": "I-phone_number",
46
+ "31": "B-postal_code",
47
+ "32": "I-postal_code",
48
+ "33": "B-secret",
49
+ "34": "I-secret",
50
+ "35": "B-sensitive_account_id",
51
+ "36": "I-sensitive_account_id",
52
+ "37": "B-tax_id",
53
+ "38": "I-tax_id",
54
+ "39": "B-username",
55
+ "40": "I-username"
56
+ },
57
+ "initializer_range": 0.02,
58
+ "intermediate_size": 3072,
59
+ "is_decoder": false,
60
+ "label2id": {
61
+ "B-account_number": 1,
62
+ "B-address": 3,
63
+ "B-card_cvv": 5,
64
+ "B-card_expiry": 7,
65
+ "B-date_of_birth": 9,
66
+ "B-email": 11,
67
+ "B-file_path": 13,
68
+ "B-government_id": 15,
69
+ "B-iban": 17,
70
+ "B-ip_address": 19,
71
+ "B-organization": 21,
72
+ "B-password": 23,
73
+ "B-payment_card": 25,
74
+ "B-person": 27,
75
+ "B-phone_number": 29,
76
+ "B-postal_code": 31,
77
+ "B-secret": 33,
78
+ "B-sensitive_account_id": 35,
79
+ "B-tax_id": 37,
80
+ "B-username": 39,
81
+ "I-account_number": 2,
82
+ "I-address": 4,
83
+ "I-card_cvv": 6,
84
+ "I-card_expiry": 8,
85
+ "I-date_of_birth": 10,
86
+ "I-email": 12,
87
+ "I-file_path": 14,
88
+ "I-government_id": 16,
89
+ "I-iban": 18,
90
+ "I-ip_address": 20,
91
+ "I-organization": 22,
92
+ "I-password": 24,
93
+ "I-payment_card": 26,
94
+ "I-person": 28,
95
+ "I-phone_number": 30,
96
+ "I-postal_code": 32,
97
+ "I-secret": 34,
98
+ "I-sensitive_account_id": 36,
99
+ "I-tax_id": 38,
100
+ "I-username": 40,
101
+ "O": 0
102
+ },
103
+ "layer_norm_eps": 1e-05,
104
+ "max_position_embeddings": 514,
105
+ "model_type": "xlm-roberta",
106
+ "num_attention_heads": 12,
107
+ "num_hidden_layers": 12,
108
+ "output_past": true,
109
+ "pad_token_id": 1,
110
+ "position_embedding_type": "absolute",
111
+ "tie_word_embeddings": true,
112
+ "transformers_version": "5.12.1",
113
+ "type_vocab_size": 1,
114
+ "use_cache": false,
115
+ "vocab_size": 250002
116
+ }
fig1_recall_by_tier.png ADDED
fig5_vs_presidio.png ADDED
model.int8.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac9e66bfd3cf9ac50a5d393803bf07ec25970ae7c06b7ce8c2633bea5bc8a462
3
+ size 278409519
onnx/model_int8.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac9e66bfd3cf9ac50a5d393803bf07ec25970ae7c06b7ce8c2633bea5bc8a462
3
+ size 278409519
sentencepiece.bpe.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cfc8146abe2a0488e9e2a0c56de7952f7c11ab059eca145a0a727afce0db2865
3
+ size 5069051
special_tokens_map.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": "<s>",
3
+ "cls_token": "<s>",
4
+ "eos_token": "</s>",
5
+ "mask_token": {
6
+ "content": "<mask>",
7
+ "lstrip": true,
8
+ "normalized": false,
9
+ "rstrip": false,
10
+ "single_word": false
11
+ },
12
+ "pad_token": "<pad>",
13
+ "sep_token": "</s>",
14
+ "unk_token": "<unk>"
15
+ }
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d1065c14bf5f3d26a369bb348eae791e137f4b69cc85f846cc14bde0e6c49aca
3
+ size 17098184
tokenizer_config.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": true,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<s>",
5
+ "cls_token": "<s>",
6
+ "eos_token": "</s>",
7
+ "is_local": false,
8
+ "local_files_only": false,
9
+ "mask_token": "<mask>",
10
+ "model_max_length": 512,
11
+ "pad_token": "<pad>",
12
+ "sep_token": "</s>",
13
+ "tokenizer_class": "XLMRobertaTokenizer",
14
+ "unk_token": "<unk>"
15
+ }