best_engine_ai_helper.privacy module
privacy — local pseudonymization for cloud calls (Phase 6.4).
Replace personal data with realistic same-type surrogates before text
leaves the machine for a cloud provider, and restore the originals on the way
back. Marie -> Claudine, Lyon -> Paris: the prose stays natural (no
PERSON_1 tokens), so the cloud model reasons over coherent text and quality
is intact. The reverse map stays local.
Detection + surrogate proposal are done by a local LLM (via a resolved engine
— Ollama/vLLM), asked for schema-constrained JSON. Being local, it never ships
the raw text anywhere, and being an LLM it is context-aware: it catches
quasi-identifiers (role + city + employer) and special-category facts (health,
beliefs, …) that a pure PII regex misses. An optional deterministic layer
(Microsoft Presidio + Faker + spaCy, the privacy extra) can augment it; see
augment_with_presidio().
Honesty (GDPR Recital 26): pseudonymized data is still personal data. This is risk-reduction, not anonymization, and does not take cloud processing out of GDPR scope. Label outputs “pseudonymized”, never “anonymous”.
- best_engine_ai_helper.privacy.augment_with_presidio(text, entities)[source]
Deterministic backstop (optional
cloudextra): add Presidio+Faker hits.Presidio (PII detection) + Faker (same-type surrogates) catch structured identifiers (emails, phones, card/IBAN, IPs) the LLM may miss, and add them to the entity list. Requires
presidio-analyzer,presidio-anonymizerandFaker(thecloudextra) plus spaCy models; a no-op with a warning when they are absent. Full wiring lands in a later 6.4 step.
- best_engine_ai_helper.privacy.pseudonymize(text, engine, *, locale=None, min_len=2)[source]
Replace personal data in
textwith same-type surrogates using a local LLM.- Parameters:
text (str) – The text to scrub before it leaves the machine.
engine (dict | str) – A resolved engine descriptor (or path). Use a LOCAL engine — for a cloud brief pass
engine["fallback"]so scrubbing never touches the cloud.locale (str or None) – Optional locale hint (e.g.
"fr_FR") so surrogates match the language.min_len (int) – Ignore detected spans shorter than this (avoids mangling stray letters).
- Returns:
mappingis{surrogate: original}— keep it LOCAL and feed it torestore()on the response.- Return type:
(scrubbed_text, mapping)