Token Classification
Transformers
ONNX
xlm-roberta
pii
privacy
redaction
accessibility-tree
ocr
computer-use
agentic
screen-capture
screenpipe
Instructions to use screenpipe/pii-redactor with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use screenpipe/pii-redactor with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="screenpipe/pii-redactor")# Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("screenpipe/pii-redactor") model = AutoModelForTokenClassification.from_pretrained("screenpipe/pii-redactor") - Notebooks
- Google Colab
- Kaggle
docs: rewrite card — screenpipe's own model (not OpenAI Privacy Filter), ScreenLeak numbers, demo link
Browse files
README.md
CHANGED
|
@@ -7,7 +7,7 @@ language:
|
|
| 7 |
- it
|
| 8 |
- es
|
| 9 |
- nl
|
| 10 |
-
library_name:
|
| 11 |
pipeline_tag: token-classification
|
| 12 |
tags:
|
| 13 |
- pii
|
|
@@ -19,8 +19,6 @@ tags:
|
|
| 19 |
- agentic
|
| 20 |
- screen-capture
|
| 21 |
- screenpipe
|
| 22 |
-
base_model:
|
| 23 |
-
- openai/privacy-filter
|
| 24 |
metrics:
|
| 25 |
- f1
|
| 26 |
- recall
|
|
@@ -35,25 +33,24 @@ extra_gated_prompt: >-
|
|
| 35 |
|
| 36 |
> A [screenpipe](https://screenpi.pe) project.
|
| 37 |
|
| 38 |
-
|
| 39 |
-
sees a user's machine through**:
|
| 40 |
|
| 41 |
1. **Accessibility-tree dumps** — the structured AX hierarchy macOS /
|
| 42 |
-
Windows expose to assistive tech. Short, structured,
|
| 43 |
-
|
| 44 |
-
2. **OCR'd screen text** — what tools like screenpipe extract from
|
| 45 |
-
|
| 46 |
-
|
| 47 |
3. **Computer-use traces** — what an agentic model (Claude Computer Use,
|
| 48 |
-
GPT
|
| 49 |
|
| 50 |
These surfaces are short, sparse-context, and full of identifiers that
|
| 51 |
-
slip past redactors trained on chat-style prose. This
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
(1.5B parameters, 50M active).
|
| 57 |
|
| 58 |
> **License: CC BY-NC 4.0** (non-commercial). For commercial use —
|
| 59 |
> production redaction, SaaS / API embedding, AI-agent privacy
|
|
@@ -62,44 +59,31 @@ Built on top of the [OpenAI Privacy Filter](https://github.com/openai/privacy-fi
|
|
| 62 |
|
| 63 |
## Headline numbers
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
|
| 71 |
-
|
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
[ScreenCapture 09:14] Slack — #compai-tessera (12 unread)
|
| 86 |
-
```
|
| 87 |
-
|
| 88 |
-
These are 30-character strings with one or two PII tokens and almost
|
| 89 |
-
no surrounding context. A model trained on chat corpora will conflate
|
| 90 |
-
brand names with people, miss `Arc | Marcus Chen` because it expects
|
| 91 |
-
sentence context, and tag `Raycast` and `Claude` as people.
|
| 92 |
-
|
| 93 |
-
If you're building an **agentic system that reads screen state** — a
|
| 94 |
-
desktop-control agent, a memory layer for browsing, anything that
|
| 95 |
-
streams accessibility / OCR / screen-capture data into an LLM — this
|
| 96 |
-
is the redactor designed for that pipe.
|
| 97 |
|
| 98 |
## What it does
|
| 99 |
|
| 100 |
-
Span-level redaction. Given a string, returns
|
| 101 |
-
|
| 102 |
-
of 12 canonical categories:
|
| 103 |
|
| 104 |
```
|
| 105 |
private_person, private_email, private_phone, private_address,
|
|
@@ -110,80 +94,90 @@ private_channel, private_id, private_date, secret
|
|
| 110 |
`secret` covers passwords, API keys, JWTs, DB connection strings,
|
| 111 |
PRIVATE-KEY block markers, etc.
|
| 112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
## Inference
|
| 114 |
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
out =
|
| 121 |
-
|
| 122 |
-
print(f" [{span.start}:{span.end}] {span.label} = {span.text!r}")
|
| 123 |
-
# -> [10:21] private_person = 'Marcus Chen'
|
| 124 |
```
|
| 125 |
|
| 126 |
-
|
| 127 |
-
covering window titles, long-form text, and secrets.
|
| 128 |
|
| 129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
-
|
| 132 |
-
|
|
|
|
| 133 |
|
| 134 |
-
|
| 135 |
-
|---|---:|
|
| 136 |
-
| English | 76.8% (70.1–83.1) |
|
| 137 |
-
| Spanish | 73.2% (66.5–79.3) |
|
| 138 |
-
| Italian | 70.8% (64.3–77.4) |
|
| 139 |
-
| German | 70.6% (63.5–77.1) |
|
| 140 |
-
| French | 68.1% (61.5–75.3) |
|
| 141 |
-
| Dutch | 56.1% (48.9–63.3) |
|
| 142 |
|
| 143 |
-
|
| 144 |
-
|
|
|
|
| 145 |
|
| 146 |
## Limitations
|
| 147 |
|
| 148 |
-
1. **Sudo / login password prompts leak.**
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
deployments; flag if you need clean OCR text downstream.
|
| 161 |
-
5. **Strict label-space evaluation.** The numbers above use a
|
| 162 |
-
12-class taxonomy and a strict per-example zero-leak metric.
|
| 163 |
-
Absolute values depend on the evaluator's label taxonomy and metric
|
| 164 |
-
choice; macro-F1 is a more lenient point of comparison.
|
| 165 |
-
|
| 166 |
-
## Reproducing inference
|
| 167 |
-
|
| 168 |
-
```bash
|
| 169 |
-
git clone https://huggingface.co/screenpipe/pii-redactor
|
| 170 |
-
cd pii-redactor
|
| 171 |
-
git lfs pull
|
| 172 |
-
pip install git+https://github.com/openai/privacy-filter.git
|
| 173 |
-
python examples/inference.py
|
| 174 |
-
```
|
| 175 |
-
|
| 176 |
-
Reproducing the eval scores requires our held-out benchmark, which is
|
| 177 |
-
not redistributed. Contact **louis@screenpi.pe** for benchmark access
|
| 178 |
-
or commercial licensing.
|
| 179 |
|
| 180 |
## License
|
| 181 |
|
| 182 |
-
[CC BY-NC 4.0](LICENSE) — non-commercial use only.
|
| 183 |
-
|
| 184 |
|
| 185 |
-
For commercial licensing (production deployment, redistribution
|
| 186 |
-
|
| 187 |
|
| 188 |
## Citation
|
| 189 |
|
|
|
|
| 7 |
- it
|
| 8 |
- es
|
| 9 |
- nl
|
| 10 |
+
library_name: transformers
|
| 11 |
pipeline_tag: token-classification
|
| 12 |
tags:
|
| 13 |
- pii
|
|
|
|
| 19 |
- agentic
|
| 20 |
- screen-capture
|
| 21 |
- screenpipe
|
|
|
|
|
|
|
| 22 |
metrics:
|
| 23 |
- f1
|
| 24 |
- recall
|
|
|
|
| 33 |
|
| 34 |
> A [screenpipe](https://screenpi.pe) project.
|
| 35 |
|
| 36 |
+
screenpipe's own PII redactor, purpose-built for the **three surfaces an
|
| 37 |
+
AI agent actually sees a user's machine through**:
|
| 38 |
|
| 39 |
1. **Accessibility-tree dumps** — the structured AX hierarchy macOS /
|
| 40 |
+
Windows expose to assistive tech. Short, structured, full of labels
|
| 41 |
+
like `AXButton[Send to marcus@helios-ai.io]`.
|
| 42 |
+
2. **OCR'd screen text** — what tools like screenpipe extract from screen
|
| 43 |
+
recordings: window-title-shaped artifacts, app chrome, and the
|
| 44 |
+
occasional long-form email or doc.
|
| 45 |
3. **Computer-use traces** — what an agentic model (Claude Computer Use,
|
| 46 |
+
GPT operators, etc.) reads when it drives a desktop.
|
| 47 |
|
| 48 |
These surfaces are short, sparse-context, and full of identifiers that
|
| 49 |
+
slip past redactors trained on chat-style prose. This is a compact,
|
| 50 |
+
multilingual token classifier trained in-house specifically for them.
|
| 51 |
+
**It is not OpenAI's Privacy Filter, and it is not a fine-tune of one** —
|
| 52 |
+
it's screenpipe's own model. 278 MB INT8 ONNX, ~9 ms p50 on CPU, runs
|
| 53 |
+
fully offline.
|
|
|
|
| 54 |
|
| 55 |
> **License: CC BY-NC 4.0** (non-commercial). For commercial use —
|
| 56 |
> production redaction, SaaS / API embedding, AI-agent privacy
|
|
|
|
| 59 |
|
| 60 |
## Headline numbers
|
| 61 |
|
| 62 |
+
On [**ScreenLeak**](https://github.com/screenpipe/screenleak), our open
|
| 63 |
+
benchmark for PII redaction on screen telemetry — n=422 hand-labelled
|
| 64 |
+
desktop-telemetry strings, 13 categories, strict per-string zero-leak
|
| 65 |
+
(every PII span in the string must be caught):
|
| 66 |
+
|
| 67 |
+
| Model | Zero-leak | |
|
| 68 |
+
|---|---:|---|
|
| 69 |
+
| Gemini 3.1 Pro | 91.0% | cloud API |
|
| 70 |
+
| GPT-5.5 | 90.7% | cloud API |
|
| 71 |
+
| Claude Opus 4.7 | 87.8% | cloud API |
|
| 72 |
+
| **this model** ⭐ | **86.7%** | **local · 278 MB · ~9 ms CPU · $0/call** |
|
| 73 |
+
| Google Cloud DLP | 37.7% | cloud API |
|
| 74 |
+
| Microsoft Presidio | 35.4% | local OSS |
|
| 75 |
+
|
| 76 |
+
Within a few points of the frontier APIs, ~50 points above the flagship
|
| 77 |
+
commercial PII products — at zero per-call cost, fully offline. Full
|
| 78 |
+
methodology, confidence intervals, and per-framework (HIPAA / GDPR /
|
| 79 |
+
PCI DSS / …) breakdowns:
|
| 80 |
+
[github.com/screenpipe/screenleak](https://github.com/screenpipe/screenleak).
|
| 81 |
+
**Try it in your browser:** [screenpipe.github.io/screenleak/demo](https://screenpipe.github.io/screenleak/demo/).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
|
| 83 |
## What it does
|
| 84 |
|
| 85 |
+
Span-level redaction. Given a string, returns the regions it thinks are
|
| 86 |
+
PII, each classified into one of **12 canonical categories**:
|
|
|
|
| 87 |
|
| 88 |
```
|
| 89 |
private_person, private_email, private_phone, private_address,
|
|
|
|
| 94 |
`secret` covers passwords, API keys, JWTs, DB connection strings,
|
| 95 |
PRIVATE-KEY block markers, etc.
|
| 96 |
|
| 97 |
+
> **Tip:** screenpipe redacts **each captured fragment independently**
|
| 98 |
+
> (one AX node / OCR line / window title at a time) — that's the
|
| 99 |
+
> distribution the model is tuned for. Feeding a giant multi-entity blob
|
| 100 |
+
> in a single call degrades recall; split on natural boundaries first.
|
| 101 |
+
|
| 102 |
## Inference
|
| 103 |
|
| 104 |
+
**Browser (transformers.js):**
|
| 105 |
+
|
| 106 |
+
```js
|
| 107 |
+
import { pipeline } from "@huggingface/transformers";
|
| 108 |
+
const pii = await pipeline("token-classification", "screenpipe/pii-redactor", { dtype: "q8" });
|
| 109 |
+
const out = await pii("export OPENAI_API_KEY=sk-proj-Ab12Cd34Ef56Gh78");
|
| 110 |
+
// out: per-token tags; group consecutive B-/I- tags into spans
|
|
|
|
|
|
|
| 111 |
```
|
| 112 |
|
| 113 |
+
**Python (transformers):**
|
|
|
|
| 114 |
|
| 115 |
+
```python
|
| 116 |
+
# pip install transformers torch
|
| 117 |
+
from transformers import AutoTokenizer, AutoModelForTokenClassification
|
| 118 |
+
import torch
|
| 119 |
+
|
| 120 |
+
tok = AutoTokenizer.from_pretrained("screenpipe/pii-redactor")
|
| 121 |
+
model = AutoModelForTokenClassification.from_pretrained("screenpipe/pii-redactor").eval()
|
| 122 |
+
id2label = model.config.id2label
|
| 123 |
+
|
| 124 |
+
def redact(text):
|
| 125 |
+
enc = tok(text, return_offsets_mapping=True, return_tensors="pt", truncation=True)
|
| 126 |
+
offsets = enc.pop("offset_mapping")[0].tolist()
|
| 127 |
+
with torch.no_grad():
|
| 128 |
+
pred = model(**enc).logits.argmax(-1)[0].tolist()
|
| 129 |
+
# decode BIO from offsets + argmax (aggregation_strategy is unreliable
|
| 130 |
+
# for this tokenizer — walk the offsets yourself)
|
| 131 |
+
spans, cur = [], None
|
| 132 |
+
for (s, e), p in zip(offsets, pred):
|
| 133 |
+
if s == e: # special token
|
| 134 |
+
cur = None; continue
|
| 135 |
+
lab = id2label[p]
|
| 136 |
+
if lab == "O":
|
| 137 |
+
cur = None; continue
|
| 138 |
+
base = lab.split("-", 1)[-1]
|
| 139 |
+
if cur and cur["label"] == base and not lab.startswith("B-"):
|
| 140 |
+
cur["end"] = e
|
| 141 |
+
else:
|
| 142 |
+
cur = {"start": s, "end": e, "label": base}; spans.append(cur)
|
| 143 |
+
return [(d["start"], d["end"], d["label"], text[d["start"]:d["end"]]) for d in spans]
|
| 144 |
+
|
| 145 |
+
print(redact("export OPENAI_API_KEY=sk-proj-Ab12Cd34Ef56Gh78"))
|
| 146 |
+
# -> [(..., ..., 'secret', 'sk-proj-Ab12Cd34Ef56Gh78')]
|
| 147 |
+
```
|
| 148 |
|
| 149 |
+
Production INT8 ONNX weights are in [`onnx/`](onnx/) — load with
|
| 150 |
+
`onnxruntime` on any platform (CoreML / DirectML / CUDA / CPU baseline);
|
| 151 |
+
the same file ships everywhere.
|
| 152 |
|
| 153 |
+
## Multilingual
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
|
| 155 |
+
Handles 6 languages (en, fr, de, it, es, nl). English is strongest;
|
| 156 |
+
Dutch is the weakest and is flagged as a known gap. Validate on your
|
| 157 |
+
locale before deploying.
|
| 158 |
|
| 159 |
## Limitations
|
| 160 |
|
| 161 |
+
1. **Sudo / login password prompts can leak.** `[sudo] password for
|
| 162 |
+
alice: hunter2` may redact the username but survive the password.
|
| 163 |
+
Pair with an OS-level keystroke-suppression policy.
|
| 164 |
+
2. **Multi-entity blobs degrade recall** — redact per captured fragment
|
| 165 |
+
(see tip above), not one giant concatenated string.
|
| 166 |
+
3. **Synthetic training data only.** No real user data was used. Validate
|
| 167 |
+
on YOUR data before deploying.
|
| 168 |
+
4. **Over-redaction (oversmash).** The model errs toward redacting — good
|
| 169 |
+
for privacy-first deployments; flag it if you need clean text
|
| 170 |
+
downstream.
|
| 171 |
+
5. **Strict zero-leak metric.** Absolute numbers depend on the
|
| 172 |
+
evaluator's taxonomy and metric; macro-F1 is a more lenient lens.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
|
| 174 |
## License
|
| 175 |
|
| 176 |
+
[CC BY-NC 4.0](LICENSE) — non-commercial use only. See [`NOTICE`](NOTICE)
|
| 177 |
+
for third-party component attributions.
|
| 178 |
|
| 179 |
+
For commercial licensing (production deployment, redistribution, SaaS /
|
| 180 |
+
API embedding, custom fine-tunes for your domain): **louis@screenpi.pe**.
|
| 181 |
|
| 182 |
## Citation
|
| 183 |
|