memaudit v0.1 · audit doc
Evidence ·
not compliance

memaudit — training-data memorization auditor

pytest for
training-data privacy.

A local plugin that plants canaries in your fine-tune and reports whether the finished model leaks membership or regurgitates training text.

0.100 10/100
Leak rate at 1% FPR
95% CI [0.049, 0.176]
0.837
Member / control rank
AUC, secondary
0/100
Secrets spat back
Regurgitation rate

Repetition-tier curve at the same 1% FPR threshold: 1x 0/34 (single-exposure) · 4x 1/33 (moderate) · 16x 9/33 (high-exposure). The pooled 10% is substantially a duplication/exposure stress signal, not a 10% detection probability for a single-exposure record.

TinyLlama-1.1B-Chat · Alpaca · LoRA r=8 · 1 epoch · 100 canaries / 200 controls · budget 0.874% · model-scored high_ppl · 20,000 host rows · Apple M3 Pro / MPS · 2026-08-30

GitHub ↗ Case study

Membership

Can logprobs reveal a training row? TPR at 1% FPR, thresholded on held-out controls, with a Clopper–Pearson interval. High with a tight CI means leakage. Zero with a tight CI means this LoRA did not leak at that operating point.

Regurgitation

Does the model emit the secret from a prefix? A separate attack. Membership and regurgitation routinely disagree — a regurgitation-only test can file a leaky model as clean.

Measured · n=100 / 200 Honest ≤1% canary budget · Apple MPS · 2026-08-27/30
Stack Config n / controls Budget TPR @ 1% FPR 95% CI AUC Regurg
TinyLlama + Alpaca HF Trainer · LoRA r=8 · 1 ep · 20k rows 100 / 200 0.874% 0.100 (10/100) [0.049, 0.176] 0.837 0/100
TinyLlama + Alpaca (v0.1 appendix) same stack · uniform_vocab canaries 100 / 200 0.907% 0.180 (18/100) [0.110, 0.269] 0.776 0/100
distilgpt2 LoRA HF Trainer · 1 ep · r=8 · host 80k 100 / 200 0.77% 0.000 [0.000, 0.036] 0.586 0/100
distilgpt2 · risky HF Trainer · 5 ep · r=16 · lr 1e-3 100 / 200 0.77% 0.000 [0.000, 0.036] 0.848 0/100

Reproduce the TinyLlama flagship: python examples/alpaca_case_study.py. Powered canaries: requested family high_ppl, actual generator model_scored_high_ppl (TinyLlama rejection sampling). Tier curve at the shipped threshold: 1x 0/34, 4x 1/33, 16x 9/33 — the pooled 10% is mostly a 16x exposure-stress signal. Prior v0.1 run (uniform_vocab fallback, no model at generation): TPR 0.180 [0.110, 0.269]. Write-up: case-study.html. distilgpt2 rows are the already-measured n=100/200 benches — tight CIs, not hidden. A 12-canary first look (TPR 0.500, CI [0.211, 0.789]) is in the case-study appendix; it is not the headline.

¶ 01The two-verdict audit

Membership and regurgitation routinely disagree. You need both numbers.

Models trained with the goldfish loss show near-zero verbatim extraction yet remain highly detectable by likelihood attacks; head-only fine-tunes maximize membership signal with almost no extractable text. A loss-only audit is wrong in both directions — so memaudit never ships one. Every audit reports two separate verdicts, side by side.

Verdict 1

Membership leakage

"Can an attacker with log-prob access tell what was trained on?"

attack   base-calibrated Min-K%++, secret-span only
cost     2 forward passes per sequence (target + base)
controls thresholds set on held-out, never-inserted canaries
TPR @ 1% FPR + Clopper–Pearson 95% CI + log-log ROC · AUC demoted to secondary
Verdict 2

Regurgitation

"Does the model emit training content when prompted with a prefix?"

attack   greedy prefix-prompted completion, prefix grid
scoring  exact match · BLEU > 0.75 · sliding-window NED ≤ 0.1
targets  canaries per repetition tier + flagged real records
Regurgitation rate per exposure tier (1× / 4× / 16×) · negative-control rate always printed

Honesty is the feature: the report names what it does not cover — model inversion, reconstruction, attribute inference — because under EDPB Opinion 28/2024 ¶55, test results are evidence only for the attacks actually run.

¶ 02Quickstart

Five lines in your training script. One report out.

Injection happens before training (transformers builds the dataloader before any callback fires — so memaudit gives you a pre-train inject() helper and a thin callback). The same engine runs post-hoc from the CLI.

1 · install
$ pip install memaudit
$ pip install "memaudit[peft]"        # LoRA / adapter-toggle
$ pip install "memaudit[peft,trl]"   # LoRA + SFTTrainer
3 · or post-hoc, from the CLI
$ memaudit audit --model ./out \
    --canary-set ./out/memaudit-manifest.json \
    --dataset train.jsonl --ref auto
# --ref auto: disable_adapter() on unmerged LoRA,
#             else pass a base checkpoint path
2 · inside your training script
from memaudit import generate_canaries, inject, MemorizationAuditCallback

canaries = generate_canaries(tokenizer, n=200, n_controls=200, family="high_ppl", seed=0)
train_ds, manifest = inject(train_ds, canaries, fmt="auto", seed=0)
trainer.add_callback(MemorizationAuditCallback(trainer=trainer, manifest=manifest))
trainer.train()  # writes <output_dir>/memaudit-report.json

Canary placement is format-aware and verified: the secret always lands on the trainable side of the record (completion / assistant turn / text body). A prompt-side canary would be loss-masked to labels=-100 and silently zero the audit — inject() refuses that placement, and the callback re-scans at on_train_begin to prove every canary survived tokenization, masking, and packing.

¶ 03The LoRA / PEFT pre-flight

The pre-flight router no other tool has.

Most fine-tunes are LoRA fine-tunes — and PEFT configs silently invalidate naive audits. The published example: new-token canary audits collapse when embeddings are frozen, which is exactly what standard LoRA does. memaudit checks embedding trainability before training and routes canary families accordingly — a router, not a blocker.

0.74 0.05

Audit signal collapse with frozen embeddings — new-token canary audit under DP-LoRA, Panda et al., ICLR 2025 (Table 14). The default high-perplexity regular-token family survives: TPR@1%FPR 0.94–0.99 under LoRA r=4 (Meeus et al., ICML 2025).

Claim scope: "no other tool" per our August 2026 landscape scan of open-source and commercial offerings — no OSS tool, no enterprise platform's public materials, and no announced regulator library addresses frozen-embedding × canary-family interaction. See ¶ 06.

  • Embedding-trainability router — gates the new-token family; memaudit never resizes your vocab
  • modules_to_save=[embed_tokens, lm_head] flagged as raising the membership-risk tier
  • Reference model for free: disable_adapter() scores base + fine-tune from one model copy; merged adapters and bias≠"none" detected, base checkpoint fallback
  • Loss-masking & packing checkscompletion_only_loss, assistant-only templates, packing truncation: placements that would silently zero canaries are caught
  • Survival scan at on_train_begin — token-level proof each canary exists in the actual batches
  • Refuses to fabricate: fewer than 100 held-out controls → no TPR@1%FPR headline, by design
¶ 04Other measured surfaces

The instrument check, and the smaller LM.

The hero numbers are the powered TinyLlama + Alpaca run (100 / 200). Below: a TinyDemoLM positive-control that proves the pipeline can detect, then the same distilgpt2 n=100/200 rows from the compact table with their stability seeds.

TinyDemoLM
validation

examples/demo.py · randomly-initialized TinyDemoLM (hidden=64, vocab=256) · full FT · positive control · seed 0

1.000
TPR @ 1% FPR
16 canaries / 100 controls
CI95 [0.794,1.000]
15/16
Regurgitated at 16× tier
exact / BLEU>0.75 / NED≤0.1
0.000
Negative-control
regurgitation (n=100)
~30 s
End-to-end on a laptop
7.0 s train + 20.3 s audit

Scale: TinyDemoLM positive control — canaries deliberately dominate tokens so the pipeline can show a clear hit and a clean control side. If a model doesn't memorize, memaudit refuses the TPR@1%FPR headline rather than inventing one.

Measured · pretrained LoRA distilgpt2 · Apple MPS · 2026-08-27 · budget ≤1% of host tokens
Run Config n / controls Budget TPR @ 1% FPR 95% CI AUC Stability (seeds 0,1,2)
SFT trl.SFTTrainer · 1 ep · r=8 · lr 2e-4 16 / 100 0.93% 0.000 [0, 0.206] 0.516 0.000 / 0.000 / 0.000
C HF Trainer · 1 ep · r=8 · lr 2e-4 · host auto-grown 80k 100 / 200 0.77% 0.000 [0, 0.036] 0.586 0.000 / 0.010 / 0.010
D · risky HF Trainer · 5 ep · r=16 · lr 1e-3 · host auto-grown 80k 100 / 200 0.77% 0.000 primary [0, 0.036] 0.848 0.000 / 0.090 / 0.090 (9/100 on 2 of 3 seeds)

Scale: pretrained distilgpt2 + LoRA at an honest canary budget (separate from the TinyDemoLM positive control above). Primary TPR stays 0.000 on every row; Run D is reported exactly as measured: AUC 0.848 with stability 0.000 / 0.090 / 0.090 (9/100 canaries on seeds 1 and 2). No fabricated headline TPR. Reproduce via benchmarks/run_lora_benchmark.py and benchmarks/run_sft_benchmark.py. Measured wall-clock on Apple MPS: Run C train 753 s / audit 173 s; SFT train 192 s / audit 52 s.

¶ 05Regulatory mapping

The report regulators describe, generated where you train.

EDPB Opinion 28/2024 made documented, state-of-the-art testing against membership inference and regurgitation the operative GDPR evidence standard for AI models. memaudit's report is designed field-by-field against those paragraphs. It produces test evidence — it does not make you compliant.

EDPB Opinion 28/2024 · ¶ 55 — the testing paragraph
"…successful testing which covers widely known, state-of-the-art attacks can only be evidence for the resistance to those attacks… this could include, among others, structured testing against: (i) attribute and membership inference; (ii) exfiltration; (iii) regurgitation of training data; (iv) model inversion; or (v) reconstruction attacks."
EDPB Opinion 28/2024 · ¶ 43 — the anonymity test
"…both (i) the likelihood of direct (including probabilistic) extraction of personal data… as well as (ii) the likelihood of obtaining, intentionally or not, such personal data from queries, should be insignificant for any data subject."
RequirementWhat it asks forWhere it lives in memaudit's report
¶ 55 (i)/(iii) Structured testing against membership inference and regurgitation The two verdicts — canary MIA at TPR@1%FPR with CI; prefix-prompted regurgitation per exposure tier. Attribute inference, model inversion, reconstruction: named out of scope.
¶ 55 Scope, frequency, quantity and quality of tests Canary counts, repetition grid, seeds, run date, tool version, negative-control results — all in the versioned JSON. Multi-seed stability block included when you pass multiple seeds.
¶ 58 (c) Threat model and risk assessments behind the measures Per-canary-family threat-model fields: attacker access level (log-probs vs. text), knowledge assumptions.
¶ 58 (e) Controls "to limit or assess the success and impact of main attacks (regurgitation, membership inference attacks, exfiltration, etc.)" Quantified results with confidence intervals; negative controls always run; per-record list redacted by default.
¶ 46 Release context (public model vs. internal) changes expected testing level Release-context field: user declares public API / internal / open-weights; the report states the implied attack surface.
¶ 58 Documentation an SA can inspect Provenance: schema version, config, seeds, model/dataset fingerprint hashes. Shipped compliance_annex in every report — render with memaudit report --annex.
CNIL Documented model-status analysis; re-identification attack tests; producible on demand The report is that artifact for the attacks it runs. CNIL's own caveat is encoded: a negative quick regurgitation test alone proves nothing — memaudit pairs it with calibrated MIA and says so.
Where the AI Act fits: it never mandates memorization testing by name — EDPB 28/2024 and CNIL guidance are the operative hooks today. High-risk obligations apply from 2 December 2027 (Annex III) and 2 August 2028 (Annex I embedded) per Regulation (EU) 2026/1744; GPAI documentation duties have applied since 2 August 2025. If you've read about an "August 2026 high-risk deadline," that date moved. For US framing: NIST AI 600-1 names data memorization as a generative-AI risk.
¶ 06Landscape

Where memaudit sits — factually.

As of August 2026, no shipped tool — open or commercial — does trainer-integrated, canary-based, PEFT-aware memorization auditing. Here is the honest comparison, from public materials.

memaudit v0.1 Closed enterprise platforms
(DynamoEval-class)
Regulator libraries
(e.g. PANAME)
Research attack code
(MIMIR, ML Privacy Meter)
Availability pip install · Apache-2.0 · free Custom-quote enterprise sales; SaaS / VPC Announced / in development by CNIL+ANSSI+Inria Free research code; sparse maintenance as of Aug 2026
Your model & data Never leave your machine Uploaded to the vendor platform Intended as a local library Local scripts
When it audits Inside the training loop (callback) + post-hoc CLI Post-hoc, on an already-trained model Post-hoc Post-hoc
Canaries + negative controls Yes — pre-registered, coin-flipped, controls in every audit No published canary methodology None announced No (post-hoc MIA on real records only)
Headline statistic TPR @ 1% FPR + Clopper–Pearson CI AUC / ROC-first (per public materials) Unknown Varies by script; typically AUC
LoRA / PEFT handling Pre-flight router: frozen-embedding detection, adapter-toggle reference, family gating Adapters accepted as an upload format; no published PEFT-aware test design Not in public materials Limited configs; no pre-flight
Compliance artifact Versioned JSON designed against EDPB 28/2024 ¶55/¶58; hashes & seeds Auto-generated PDF audit reports GDPR-oriented by design (CNIL / ANSSI / Inria) None

Fair-play notes: DynamoEval-class platforms cover attack types memaudit doesn't (PII extraction and inference tests) and unadvertised features can't be ruled out — this table reflects public materials as of August 2026. Regulator libraries (CNIL / ANSSI / Inria and peers) are complements: memaudit's report is designed so vocabulary can stay aligned with emerging regulator taxonomies. Deployment scanners like garak solve a different problem (what your deployed model says) and pair well with training-side evidence.

¶ 07Questions, answered plainly

Frequently asked.

Does memaudit phone home?
No. No telemetry, no account, no SaaS backend. The audit runs on your machine, next to your training job; the report is a local JSON file. Local execution is the product — that's a structural guarantee a hosted service can't match, and it's why the license is Apache-2.0.
Does a passing report make me GDPR-compliant?
No — and be suspicious of any tool that says yes. memaudit produces the documented, state-of-the-art test evidence that EDPB Opinion 28/2024 ¶55/¶58 describe, scoped honestly to the attacks it actually runs (membership inference and regurgitation). Per ¶55, that is evidence of resistance to those attacks — not a compliance certificate. Your lawful basis, DPIA, and the rest of your file remain yours.
Does it support LoRA / PEFT fine-tunes?
Yes — by construction, not as an afterthought. The pre-flight router checks embedding trainability (gating canary families that frozen embeddings would silently break), flags modules_to_save configs that raise membership risk, and uses disable_adapter() so one model copy provides both fine-tuned and base scores. Merged adapters are detected; you pass a base checkpoint instead. Full fine-tunes work too — the reference model is loaded separately.
Will 200 canaries hurt my model?
Defaults target ≤ 0.1% of training tokens. At that budget, published audits report ≤ 1 perplexity point of utility cost (Panda et al., ICLR 2025) — and the cost shows up in your eval metrics if it happens, so you'd see it. Canaries are short standalone records, mutually diverse to limit interference.
Didn't MIMIR show membership inference doesn't work on LLMs?
MIMIR (Duan et al., 2024) showed MIAs are near-random at pretraining scale — huge deduplicated corpora seen for about one epoch. Fine-tuning is the opposite regime: small datasets, multiple epochs, large models. Capacity analysis (Morris et al., 2025) and LoRA fine-tune head-to-heads (LoRA-Leak, 2025; Meeus et al., ICML 2025 — TPR@1%FPR 0.94+ with canaries under LoRA r=4) put fine-tunes squarely where the signal exists. memaudit also never trusts raw scores: every audit calibrates on its own held-out controls and reports confidence intervals.
My model is already trained. Too late?
Use the post-hoc CLI: set-level membership testing on a sample of your real records against held-out data, plus prefix-prompted regurgitation checks. It's labeled weaker evidence in the report — without pre-registered canaries and controls, post-hoc MIA is exactly the setup the research community has shown to be misleading (Aerni et al., 2024). Best practice: inject canaries in your next training run.
What scale was tested?
The flagship is TinyLlama-1.1B-Chat + Alpaca LoRA, 100 inserted / 200 controls, 20,000 host rows, 0.874% canary budget, model-scored high_ppl canaries — see the hero and case study. Also shipped: a TinyDemoLM positive-control (memaudit demo) and pretrained distilgpt2 + LoRA n=100/200 (TPR 0.000, CI [0, 0.036]; risky-config AUC 0.848). A 12-canary first look exists as an appendix only. Production audits run against your model and data; every report carries its own scale and provenance fields.
¶ 08Design partners

Fine-tuning on data you'd have to explain to a regulator?

We're onboarding a small number of design partners — teams fine-tuning on confidential or regulated data with Hugging Face Trainer / TRL — to harden the audit against real pipelines. A pilot includes:

  • Guided integration into your existing training loop
  • Custom canary families for your data formats
  • Multi-seed runs and variance review
  • A working session walking your compliance owner through the report
  • Priority engineering attention on your PEFT configs and canary families
  • We ask for: honest feedback, and (negotiable) anonymized case-study rights
Email us about a pilot →

memaudit produces test evidence; it does not make you compliant. We'll say that in the pilot too.