louis030195 commited on
Commit
3ebbc85
·
verified ·
1 Parent(s): 8c5dbde

docs: rewrite card — screenpipe's own model (not OpenAI Privacy Filter), ScreenLeak numbers, demo link

Browse files
Files changed (1) hide show
  1. README.md +105 -111
README.md CHANGED
@@ -7,7 +7,7 @@ language:
7
  - it
8
  - es
9
  - nl
10
- library_name: opf
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
- A fine-tuned PII redactor for the **three surfaces an AI agent actually
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, often containing
43
- labels like `AXButton[Send to marcus@helios-ai.io]`.
44
- 2. **OCR'd screen text** — what tools like screenpipe extract from
45
- screen recordings. Mix of window-title-shaped artifacts, app chrome,
46
- and occasional long-form (emails, docs).
47
  3. **Computer-use traces** — what an agentic model (Claude Computer Use,
48
- GPT operator, etc.) reads when it controls a desktop.
49
 
50
  These surfaces are short, sparse-context, and full of identifiers that
51
- slip past redactors trained on chat-style prose. This model is fine-tuned
52
- specifically for them while still handling long-form text at
53
- competitive accuracy.
54
-
55
- Built on top of the [OpenAI Privacy Filter](https://github.com/openai/privacy-filter)
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
- | | base OPF | **this model** |
66
- |---|---:|---:|
67
- | Accessibility / window-title PII zero-leak | 38.6% (33.6–43.8) | **79.1% (74.8–83.5)** |
68
- | Long-form PII zero-leak (English) | 14.0% (11.7–16.2) | **77.5% (74.5–80.3)** |
69
- | Long-form PII macro-F1 (English) | 0.591 | **0.934** |
70
- | Targeted secret-redaction (34 realistic shapes) | not measured | **31/34** |
71
- | p50 inference latency (CUDA) | ~23 ms | ~23 ms |
72
-
73
- 95% bootstrap CIs in brackets. Zero-leak: % of cases where the model
74
- caught all gold spans (the metric that matters for privacy).
75
-
76
- ## Why this exists (vs the base Privacy Filter)
77
-
78
- The OpenAI Privacy Filter (and most other public PII redactors) is
79
- trained on prose-shaped data. A typical accessibility-tree node, OCR'd
80
- window title, or computer-use log line looks nothing like that:
81
-
82
- ```
83
- AXButton[Send to marcus@helios-ai.io]
84
- Welcome | Acme Corp | xAI Console
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 `[(start, end, label, text)]`
101
- where each span is a region the model thinks is PII, classified into one
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
- ```python
116
- # pip install opf (currently from source: github.com/openai/privacy-filter)
117
- from opf import OPF
118
-
119
- filt = OPF(model="./model", device="cuda") # or "cpu"
120
- out = filt.redact("Welcome | Marcus Chen — Confluence")
121
- for span in out.detected_spans:
122
- print(f" [{span.start}:{span.end}] {span.label} = {span.text!r}")
123
- # -> [10:21] private_person = 'Marcus Chen'
124
  ```
125
 
126
- See [`examples/inference.py`](examples/inference.py) for a longer example
127
- covering window titles, long-form text, and secrets.
128
 
129
- ## Multilingual
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
- This model handles 6 languages. Performance on a public long-form PII
132
- benchmark (n=200 per language):
 
133
 
134
- | Language | zero-leak |
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
- Romance + Germanic languages drop −3 to −9 pp from English.
144
- **Dutch is the weakest** flagged as a known gap.
 
145
 
146
  ## Limitations
147
 
148
- 1. **Sudo / login password prompts leak.** Pattern like `[sudo]
149
- password for alice: hunter2` results in the username being redacted
150
- but the password surviving. One known hard miss in the targeted
151
- secret probe; mitigate with an OS-level keystroke-suppression policy
152
- alongside this model.
153
- 2. **Dutch is the weakest language** at −20.7 pp from English. Indic,
154
- Asian, African, Cyrillic scripts not evaluated at meaningful sample
155
- sizes don't deploy without a locale-specific eval pass.
156
- 3. **Synthetic training data only.** No real user data was used during
157
- fine-tuning. Validate on YOUR data before deploying.
158
- 4. **Oversmash.** 7.8% on accessibility / window titles, 16.5% on
159
- long-form text. The model over-redacts. Acceptable for privacy-first
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. The base model is
183
- Apache-2.0; obligations are preserved (see [`NOTICE`](NOTICE)).
184
 
185
- For commercial licensing (production deployment, redistribution rights,
186
- SaaS / API embedding, custom fine-tunes for your domain): **louis@screenpi.pe**.
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