PrivaParse
Local PII detection and pseudonymisation for text sent to an LLM — nothing leaves the machine.
A local privacy layer for text you want to send to an LLM. It detects personally identifiable information, replaces it with deterministic placeholders, keeps the mapping in a local database, and restores the original values in the model's answer.
Nothing leaves the machine. Phase 1 calls no external service at all.
Hallo, Hallo,
mein Name ist Max Mustermann. mein Name ist [[PERSON_A1]].
Sie erreichen mich unter ──▶ Sie erreichen mich unter
max@test.de [[EMAIL_A2]]
oder +49 170 1234567. oder [[PHONE_A3]].
The LLM only ever sees the right-hand side. reverse puts the left-hand side
back into whatever the model replies.
Install
pipx install "privaparse[gateway]"
That gives you the CLI and the local gateway. Person detection needs the model backend, which pulls in PyTorch — roughly 2 GB:
pipx install "privaparse[gateway,model]"
GPU setup, Docker, and installing from source are in docs/install.md.
Try it
Save this as brief.md:
Mein Name ist Max Mustermann, erreichbar unter max@test.de.
privaparse --detector regex demo brief.md
demo runs the whole round trip and prints every stage. Person detection
needs the [model] extra; without it (the plain [gateway] install above),
--detector regex keeps detection to email and phone — drop it once
[model] is installed. The real workflow is two commands:
privaparse pseudonymize brief.md -o brief.pseudo.md
privaparse reverse antwort.md -o antwort.klar.md
More commands, and the Python library, are in docs/quickstart.md.
Gateway
Point any OpenAI-compatible client at PrivaParse and it pseudonymises requests going out, restores answers coming back — no code changes on the client side.
privaparse run -- aider
Without the [model] extra, run privaparse --detector regex serve —
otherwise the server starts fine but every request that reaches detection
returns a 500.
Which clients this works with today, what it costs, and its known gaps are in docs/gateway.md.
Evidence
Phase 1 ships a 25-type entity catalogue — 21 enabled by default, three disabled on measured false positives and one (COUNTRY) on judgement rather than evidence (see docs/benchmarks/labels.md) — for plain text and Markdown, as a CLI and a Python library. No OCR, no PDF, no cloud models.
Does GLiNER2 need fine-tuning for German? No.
Measured on the German gold set in eval/gold/ — 124 documents, 33 of them
containing no PII at all (a corpus of nothing but real PII can never produce
a false positive, which is exactly where a wider catalogue turns out to
struggle) — scored at the shipped catalogue's 21 enabled types. The threshold
was fixed before this run: fine-tuning is warranted if PERSON partial-match
recall drops below 0.90 or precision below 0.85.
| Type | Precision (partial) | Recall (partial) | F1 | Support |
|---|---|---|---|---|
| PERSON | 0.969 | 0.960 | 0.964 | 99 |
| 1.000 | 1.000 | 1.000 | 21 | |
| PHONE | 0.818 | 1.000 | 0.900 | 18 |
| IBAN | 1.000 | 1.000 | 1.000 | 6 |
PERSON clears both floors comfortably — fine-tuning not warranted — and
has at every catalogue width measured, including an older, narrower one
that scored it higher (see
why that isn't the better number).
fastino/gliner2-privacy-filter-PII-multi is built on
microsoft/mdeberta-v3-base, so German is not a special case for it. EMAIL
and PHONE come from rules, not the model, so they are the control group:
EMAIL is clean, PHONE is not — its 0.818 precision and TAX_ID's 0.000 recall
are the same defect, counted from opposite ends; see
One defect, two numbers
for the mechanism.
The rest of the catalogue is measured too, and it is not uniformly clean. Eight types rest on three gold entities each — thin. Seven more, measured for the first time this run, were not all clean either: LICENSE_NUMBER and ROUTING_NUMBER measured 0.000 recall — they detect nothing — and CARD_CVV measured 0.167 precision. Full tables, the per-label breakdown, and every missed or spurious detection are in docs/benchmarks/detection-quality.md.
Reproduce with privaparse eval (needs GLiNER2 — see
Install). Chunk size as a recall setting is in
docs/benchmarks/performance-notes.md;
throughput is in docs/benchmarks/throughput.md.
Documentation
| Page | Covers |
|---|---|
| Install | pipx and source installs, CPU/GPU, Docker |
| Quickstart | privaparse demo, the CLI, the Python library |
| Gateway | The local OpenAI-compatible gateway |
| Configuration | Every PRIVAPARSE_* setting |
| Architecture | The pipeline, the vault, Markdown handling |
| Testing | Running the suite, coverage |
| Benchmarks | Every measured number, with the command that reproduces it |
Contributing
See CONTRIBUTING.md for issues and pull requests. The rule that matters most: no real PII in examples, tests, or gold documents, ever.
Licence
Apache 2.0. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file privaparse-0.1.0.tar.gz.
File metadata
- Download URL: privaparse-0.1.0.tar.gz
- Upload date:
- Size: 182.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
127c89403662c96887531cf0beca671d410dfd0bc80aa12232ac154d1915b2d5
|
|
| MD5 |
94e808c475907aba06fcd2b4886aa718
|
|
| BLAKE2b-256 |
e251c7bdc93e91326915be637bdeca2c0c21445db5f90d51426e5ce8be58c2bb
|
Provenance
The following attestation bundles were made for privaparse-0.1.0.tar.gz:
Publisher:
release.yml on Jhiynn/PrivaParse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
privaparse-0.1.0.tar.gz -
Subject digest:
127c89403662c96887531cf0beca671d410dfd0bc80aa12232ac154d1915b2d5 - Sigstore transparency entry: 2464249956
- Sigstore integration time:
-
Permalink:
Jhiynn/PrivaParse@a2ebb874b8353d450ac205d8cae58f973e0d9fea -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Jhiynn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a2ebb874b8353d450ac205d8cae58f973e0d9fea -
Trigger Event:
push
-
Statement type:
File details
Details for the file privaparse-0.1.0-py3-none-any.whl.
File metadata
- Download URL: privaparse-0.1.0-py3-none-any.whl
- Upload date:
- Size: 140.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d61edb2f6853caf86c921015384dc3d4ba235f02302aa5f250d90a1181fe9b2e
|
|
| MD5 |
f2f7ab4879ce4186e46c24ea91f7136a
|
|
| BLAKE2b-256 |
26550e876de4629a666af420a7f80cd304db1b9eedf7536933dc3e3e1f81abbb
|
Provenance
The following attestation bundles were made for privaparse-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Jhiynn/PrivaParse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
privaparse-0.1.0-py3-none-any.whl -
Subject digest:
d61edb2f6853caf86c921015384dc3d4ba235f02302aa5f250d90a1181fe9b2e - Sigstore transparency entry: 2464250073
- Sigstore integration time:
-
Permalink:
Jhiynn/PrivaParse@a2ebb874b8353d450ac205d8cae58f973e0d9fea -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Jhiynn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a2ebb874b8353d450ac205d8cae58f973e0d9fea -
Trigger Event:
push
-
Statement type: