Privacy mode¶
Privacy mode adds a multi-agent privacy pipeline between MMORE’s retriever and the answer model, so only cleaned and checked context ever reaches the LLM.
It runs at query time only: the vector DB keeps the raw corpus unchanged, and the pipeline works on the top-k chunks retrieved for each request.
Command:
mmore rag --config-file examples/rag/config.yaml --privacy examples/rag/privacy.yaml
We recommend using the mmore TUI, where privacy mode is available in both RAG and RAG CLI.

Description¶
The pipeline runs this chain over the retrieved chunks:
analyzer -> detector -> sanitizer -> leakage_adversary -> (HITL gate) -> answer -> verifier -> report
The analyzer picks the privacy domain and creates a policy for that request.
The detector runs the policy’s PII engine over each raw chunk.
The sanitizer rewrites the chunks using the chosen strategy.
The leakage adversary attacks the sanitized context. If it finds a leak, it loops back to the analyzer to tighten the policy (limited by
leakage_adversary.max_iterations). When an escalation changes only the sanitization side, detection is skipped and the previous spans are reused. If the loop exhausts its iterations without the adversary clearing the context, the request is aborted as unsafe by default; setleakage_adversary.abort_on_exhaustion: falseto instead proceed to the gate with the best-effort sanitized context.The HITL gate is the trust boundary. With
interactive: falseit approves automatically and the graph finishes in one pass. Withinteractive: trueit pauses before any context leaves for the answer model: inlocalmode a terminal prompt shows the PII-free summary and asks to approve, revise (with optional feedback), or reject; inapimode the gate auto-approves with a startup warning. Revise feedback can be descriptive: the analyzer maps it onto the available tools (detection engine, sanitization strategy, threshold level, presidio anonymization operator, a custom rewrite instruction for the synthetic-rewrite LLM, or a custom detection instruction for the LLM detector).The answer model sees only the sanitized context, the sanitized query, and the domain prompt. It never reads the raw chunks or the raw query.
The verifier checks the answer for leftover PII and faithfulness, and raises type and count warnings to guide the user.
Configuration¶
privacy.yaml is loaded directly as PrivacyConfig, so its fields sit at the top level (no privacy: wrapper). See examples/rag/privacy.yaml for a full example. Main fields:
domain:global,healthcare, orhumanitarian. Leave it out to let the analyzer guess it.context_analyzer.llm: the analyzer’s LLM. The detector, sanitizer, adversary, and verifier fall back to it when they don’t set their own.interactive: the HITL gate. Inlocalmode it prompts in the terminal (queries run one at a time); inapimode it auto-approves with a warning. Setfalsefor unattended runs.detection.engine: one engine, eitherpresidio,gliner,llm, oropenai_filter. When usingpresidio, MMORE relies on spaCy’sen_core_web_lgmodel; if it is missing, the Presidio engine may download it on first use.sanitization.strategy:token_masking,entity_replacement,synthetic_rewrite, orpresidio.sanitization.encryption_key: AES key used when thepresidiostrategy runs itsencryptoperator (e.g. after gate feedback asks for encryption). Unlike masking or hashing, encryption is reversible: whoever holds this key can decrypt the values in the sanitized context later. Without it a random key is generated per run and discarded, so the encrypted values are as unrecoverable as a hash.leakage_adversary.strategies: which attack vectors the adversary probes. Omit to run all (residual_span,quasi_identifier,structural_reid,context_reconstruction,membership_inference). Pass a subset (e.g.[residual_span, quasi_identifier]) to narrow and speed up the probe.leakage_adversary.abort_on_exhaustion: whether to abort the request as unsafe when the adversary never clears the context withinmax_iterations(defaulttrue). Setfalseto proceed to the gate with the best-effort sanitized context instead.answer.llm: anyLLMConfigbackend (API or self-hosted/vLLM).verifier.checksandverifier.warn_threshold: the advisory checks run over the answer. Omitchecksto run all (residual_leakage,faithfulness). You can also pass a subset.
Code layout¶
Everything lives under src/mmore/privacy/:
Path |
Role |
|---|---|
|
|
|
the graph wiring |
|
runs the compiled graph for one query |
|
terminal front-end for the HITL gate (raw/sanitized difference) |
|
turns the final graph state into a |
|
one module per graph node: |
|
the data formats in the pipeline: |
|
the PII detection engines, each registered as an agent tool |
|
the sanitization strategies, each registered as an agent tool |
|
the per-domain profiles (label set, prompts, and defaults) |
|
pipeline cache so engines and agents share loaded models |
|
DSPy backend: builds an LM from an |
|
reports each agent’s stage to the RAG progress display |
Report schema¶
Each request adds one ReportRecord, shown on the RAG output as privacy_report:
Field |
Meaning |
|---|---|
|
request identity |
|
resolved privacy domain |
|
engine used |
|
span count and per-entity-type counts |
|
strategy applied |
|
policy escalations triggered by the adversary agent vs. by the user |
|
|
|
which model answered |
|
verifier warnings as kind and count |
|
which advisory checks ran and which errored |
|
list of gate interactions, one per human decision (each with its decision and any written revise feedback) |
|
the query after sanitization |
|
time spent per agent |
|
|