docs: add examples/ (live demo + RESULTS) and slim the README examples

- examples/demo.mjs: live demo (5 single messages up to 5 people with rare
  auto-coined attributes + 5 escalating multi-turn conversations with
  long-range back-references); self-references the package via exports
- examples/RESULTS.md: its generated output (10 examples)
- examples/.env.example + examples/README.md; `npm run example` script
- README: replace the long examples section with two representative examples
  (dense 5-person message + 6-turn conversation) and a badge/link to
  examples/RESULTS.md for the full set
- eslint ignores examples/**, prettier ignores generated examples/RESULTS.md,
  .gitignore un-ignores .env.example

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mobiletic
2026-07-01 15:22:00 +01:00
parent d119c366b7
commit dcb0a3a448
9 changed files with 771 additions and 124 deletions

145
README.md
View File

@@ -252,141 +252,40 @@ Three distinct outputs, with different sensitivities:
## Examples
Real learner ↔ platform chat messages, anonymized **live by Gemma 4** (via Infomaniak) with no regex
fallback. All personal data below is **fictional**. `mapping` is the secret re-identification key (kept by
the operator); `legend` is safe to send to the downstream model. Every case restores identically.
Two examples produced **live by Gemma 4** on fictional Swiss e-learning data. `mapping` is the secret
re-identification key (kept by the operator); `legend` is safe to send downstream. The model even **coins
its own abbreviations** for attributes not in the base prompt (passport, permit, blood type, …).
| # | Scenario | Sensitive data detected | Notable capability | Round-trip |
| --- | ----------------------- | --------------------------------------------------- | ----------------------------------------- | ---------- |
| 1 | Course signup | name, e-mail | baseline detection | ✅ |
| 2 | Login problem | + username, phone, signup date | coins `[PER_1.ID_USER:LOGIN]` on the fly | ✅ |
| 3 | Billing / IBAN change | + address, **two IBANs**, AVS | old vs new IBAN kept **distinct** | ✅ |
| 4 | HR enrolls staff | **3 people** + org, e-mails, phones, DOB, IBAN | coreference (same person → same id) + org | ✅ |
| 5 | Parent + minor + health | 3 people, DOB, address, contacts, IBAN, maiden name | minor/guardian/doctor kept distinct | ✅ |
[![See all examples](https://img.shields.io/badge/examples-see_all-6f42c1)](./examples/RESULTS.md) &nbsp;
5 single messages of rising complexity **+** 5 multi-turn conversations, with full mappings & legends.
### Case 1 — course signup (baseline)
### A dense single message — 5 people + rare attributes
**User message:**
> Bonjour, je suis Jean Dupont et mon adresse e-mail est jean.dupont@yopmail.com. Je viens de m'inscrire à la formation « Bureautique de base » et je voulais confirmer que tout est en ordre. Merci d'avance !
> Note de dossier complète : le patient mineur Noah Baumann (né le 12.06.2013, groupe sanguin B+, numéro d'assuré maladie 756.2211.9988.77, allergique aux arachides) … Ses parents, Delphine Rieder (mère, permis de séjour C, 021 555 12 34) et Marco Baumann (père, passeport italien YA9087654), cosignent … Le Dr Farah Haddad (n° RCC V123456) a ouvert le dossier médical DM-2025-0417 … l'agent Kevin Zbinden de la caisse Helvetia … Noah utilise l'identifiant biométrique BIO-7729.
**Anonymized — what the model sees:**
**Anonymized — what the model sees** (5 distinct people `PER_1…PER_5` + `ORG_1`; `Noah` reused at the end):
> Bonjour, je suis [PER_1.PRENOM:M] [PER_1.NOM:M] et mon adresse e-mail est [PER_1.EMAIL:PERSO]. Je viens de m'inscrire à la formation « Bureautique de base » et je voulais confirmer que tout est en ordre. Merci d'avance !
> Note de dossier complète : le patient mineur [PER_1.PRENOM:U] [PER_1.NOM:U] (né le [PER_1.DATE_NAISSANCE:2013], groupe sanguin B+, numéro d'assuré maladie [PER_1.ASSUR_ID:U], allergique aux arachides) … Ses parents, [PER_2.PRENOM:F] [PER_2.NOM:F] (mère, permis de séjour [PER_2.PERMIS:C], [PER_2.TELEPHONE:U]) et [PER_3.PRENOM:M] [PER_3.NOM:M] (père, passeport italien [PER_3.PASSPORT:U]), cosignent … Le Dr [PER_4.PRENOM:F] [PER_4.NOM:F] (n° RCC [PER_4.RCC:U]) a ouvert le dossier médical DM-2025-0417 … l'agent [PER_5.PRENOM:M] [PER_5.NOM:M] de la caisse [ORG_1.NOM:Assurance] … [PER_1.PRENOM:U] utilise l'identifiant biométrique [PER_1.BIO_ID:U].
| `mapping` 🔒 (secret) | value | | `legend` 🏷️ (shareable) | meaning |
| --------------------- | ----------------------- | --- | ----------------------- | ------------------ |
| `[PER_1.PRENOM:M]` | Jean | | `PER` | Personne |
| `[PER_1.NOM:M]` | Dupont | | `PRENOM` / `NOM` | Prénom / Nom |
| `[PER_1.EMAIL:PERSO]` | jean.dupont@yopmail.com | | `EMAIL` · `M` · `PERSO` | E-mail · M · Perso |
Attributes **coined by the model** (not in the prompt): `ASSUR_ID`, `PERMIS`, `PASSPORT`, `RCC`, `BIO_ID`.
Note the course name « Bureautique de base » is **left intact** — it isn't personal data.
### A multi-turn conversation — 4 people; blood group recalled turn 1 → turn 6
### Case 4 — HR enrolls staff (coreference + organization)
| Turn | User message | Anonymized (model sees) |
| ---- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| 1 | …mon fils mineur, Noah Baumann, né le 12.06.2013, groupe sanguin B+. | …mon fils mineur, [PER_1.PRENOM:U] [PER_1.NOM:U], né le [PER_1.DATE_NAISSANCE:2013], groupe sanguin [PER_1.SANG:B+]. |
| 3 | Moi, sa mère Delphine Rieder … permis de séjour de type C. | Moi, sa mère [PER_2.PRENOM:F] [PER_2.NOM:F] … permis de séjour de type [PER_2.PERMIS:C]. |
| 4 | Son père, Marco Baumann, passeport italien YA9087654, … | Son père, [PER_3.PRENOM:M] [PER_1.NOM:U], passeport italien [PER_3.PASSPORT:ITA], … |
| 5 | Le Dr Farah Haddad a ouvert le dossier médical DM-2025-0417 pour Noah. | Le [PER_4.TITRE:MED] [PER_4.PRENOM:F] [PER_4.NOM:F] a ouvert le dossier médical [PER_1.DOSSIER:MED] pour [PER_1.PRENOM:U]. |
| 6 | Rappel : le groupe sanguin B+ de Noah doit figurer sur son badge… | Rappel : le groupe sanguin [PER_1.SANG:B+] de [PER_1.PRENOM:U] doit figurer… |
**User message:**
Noah stays `PER_1` across all six turns, and **his blood group `[PER_1.SANG:B+]` from turn 1 is reused in
turn 6** — long-range coreference holds. (The father shares the surname, so `[PER_1.NOM:U]` is reused for
it — the same value maps to the same token.)
> Bonjour, je suis Sophie Meyer, responsable formation chez Nestlé Suisse (sophie.meyer@nestle.com, +41 21 924 11 11). Je souhaite inscrire deux collaborateurs à la formation « Sécurité au travail » qui débute le 03/03/2026 : Marc Rossi, né le 12.03.1990 (marc.rossi@nestle.com), et Amélie Girard, joignable au 078 321 65 43. La facture est à adresser à notre comptabilité, IBAN CH93 0076 2011 6238 5295 7. Marc Rossi avait déjà suivi une formation l'an dernier — pouvez-vous réactiver son ancien compte plutôt que d'en créer un nouveau ?
**Anonymized — what the model sees** (note **Marc Rossi → `PER_2` in both mentions**, and the org as `ORG_1`):
> Bonjour, je suis [PER_1.PRENOM:F] [PER_1.NOM:F], responsable formation chez [ORG_1.NOM:Entreprise] ([PER_1.EMAIL:F], [PER_1.TELEPHONE:F]). Je souhaite inscrire deux collaborateurs à la formation « Sécurité au travail » qui débute le 03/03/2026 : [PER_2.PRENOM:M] [PER_2.NOM:M], né le [PER_2.DATE_NAISSANCE:1990] ([PER_2.EMAIL:M]), et [PER_3.PRENOM:F] [PER_3.NOM:F], joignable au [PER_3.TELEPHONE:F]. La facture est à adresser à notre comptabilité, IBAN [ORG_1.IBAN:Comptabilite]. [PER_2.PRENOM:M] [PER_2.NOM:M] avait déjà suivi une formation l'an dernier — pouvez-vous réactiver son ancien compte plutôt que d'en créer un nouveau ?
**`mapping` 🔒 (secret — kept on your side):**
| Placeholder | Real value |
| ----------------------------- | -------------------------- |
| `[PER_1.PRENOM:F]` | Sophie |
| `[PER_1.NOM:F]` | Meyer |
| `[ORG_1.NOM:Entreprise]` | Nestlé Suisse |
| `[PER_1.EMAIL:F]` | sophie.meyer@nestle.com |
| `[PER_1.TELEPHONE:F]` | +41 21 924 11 11 |
| `[PER_2.PRENOM:M]` | Marc |
| `[PER_2.NOM:M]` | Rossi |
| `[PER_2.DATE_NAISSANCE:1990]` | 12.03.1990 |
| `[PER_2.EMAIL:M]` | marc.rossi@nestle.com |
| `[PER_3.PRENOM:F]` | Amélie |
| `[PER_3.NOM:F]` | Girard |
| `[PER_3.TELEPHONE:F]` | 078 321 65 43 |
| `[ORG_1.IBAN:Comptabilite]` | CH93 0076 2011 6238 5295 7 |
**`legend` 🏷️ (shareable — sent to the downstream model):** `PER`=Personne, `PRENOM`=Prénom, `NOM`=Nom de
famille, `F`=Féminin, `M`=Masculin, `ORG`=Organisation, `EMAIL`=Adresse e-mail, `TELEPHONE`=Numéro de
téléphone, `DATE_NAISSANCE`=Date de naissance, `IBAN`=Numéro de compte bancaire.
<details>
<summary><b>More examples — Case 2 (login), Case 3 (two IBANs), Case 5 (minor + health)</b></summary>
#### Case 2 — login problem (coins an abbreviation for the username)
**User message:**
> Salut, moi c'est Marie Favre. J'ai créé mon compte avec l'e-mail marie.favre@bluewin.ch le 15/02/2026 mais je n'arrive plus à me connecter. Mon identifiant est mfavre et vous pouvez me joindre au 079 456 78 90. Pouvez-vous réinitialiser mon accès à la formation « Machiniste » ?
**Anonymized:**
> Salut, moi c'est [PER_1.PRENOM:F] [PER_1.NOM:F]. J'ai créé mon compte avec l'e-mail [PER_1.EMAIL:PERSO] le [PER_1.DATE_CREATION:2026] mais je n'arrive plus à me connecter. Mon identifiant est [PER_1.ID_USER:LOGIN] et vous pouvez me joindre au [PER_1.TELEPHONE:MOBILE]. Pouvez-vous réinitialiser mon accès à la formation « Machiniste » ?
| Placeholder | Real value |
| ---------------------------- | ---------------------- |
| `[PER_1.PRENOM:F]` | Marie |
| `[PER_1.NOM:F]` | Favre |
| `[PER_1.EMAIL:PERSO]` | marie.favre@bluewin.ch |
| `[PER_1.DATE_CREATION:2026]` | 15/02/2026 |
| `[PER_1.ID_USER:LOGIN]` | mfavre |
| `[PER_1.TELEPHONE:MOBILE]` | 079 456 78 90 |
`ID_USER` and `DATE_CREATION` are **coined by the model** — not in the base vocabulary — and documented in
the legend.
#### Case 3 — billing / IBAN change (two different IBANs kept distinct)
**User message:**
> Bonjour, je m'appelle Luc Berset, domicilié au 14 avenue de la Gare, 1700 Fribourg. J'ai un souci avec le paiement de la formation « Comptabilité PME » (CHF 1'200.) : mon IBAN CH93 0076 2011 6238 5295 7 n'est plus valide, je souhaite le remplacer par CH56 0483 5012 3456 7800 9. Si besoin, mon numéro AVS est le 756.1234.5678.90. Merci de mettre à jour mon dossier.
**Anonymized** (old and new IBAN get **distinct** placeholders via context):
> Bonjour, je m'appelle [PER_1.PRENOM:M] [PER_1.NOM:M], domicilié au [PER_1.ADRESSE:Rue], [PER_1.ADRESSE:NPA] [PER_1.ADRESSE:Ville]. J'ai un souci avec le paiement de la formation « Comptabilité PME » (CHF 1'200.) : mon IBAN [PER_1.IBAN:Ancien] n'est plus valide, je souhaite le remplacer par [PER_1.IBAN:Nouveau]. Si besoin, mon numéro AVS est le [PER_1.AVS:Suisse]. Merci de mettre à jour mon dossier.
| Placeholder | Real value |
| ----------------------- | -------------------------- |
| `[PER_1.PRENOM:M]` | Luc |
| `[PER_1.NOM:M]` | Berset |
| `[PER_1.ADRESSE:Rue]` | 14 avenue de la Gare |
| `[PER_1.ADRESSE:NPA]` | 1700 |
| `[PER_1.ADRESSE:Ville]` | Fribourg |
| `[PER_1.IBAN:Ancien]` | CH93 0076 2011 6238 5295 7 |
| `[PER_1.IBAN:Nouveau]` | CH56 0483 5012 3456 7800 9 |
| `[PER_1.AVS:Suisse]` | 756.1234.5678.90 |
#### Case 5 — parent, minor child and health (dense coreference)
**User message:**
> Bonjour, je vous écris au sujet de mon fils, Lucas Favre, né le 04.07.2011, que j'aimerais inscrire à la formation junior « Robotique » à Lausanne. Étant mineur, c'est moi, sa mère Camille Favre, qui gère le dossier — vous pouvez me joindre au 021 555 12 34 ou à camille.favre@bluewin.ch, nous habitons au 8 chemin des Vignes, 1009 Pully. Lucas est asthmatique ; son médecin, le Dr Nadia Benali (cabinet à Renens), a établi un certificat le 15.05.2024. Par ailleurs, j'avais moi-même suivi la formation « Photographie » en 2023 sous mon nom de jeune fille, Camille Rochat — mes deux comptes peuvent-ils être fusionnés ? Le paiement se fera depuis mon IBAN CH56 0483 5012 3456 7800 9.
**Anonymized** (son = `PER_1`, mother = `PER_2` incl. her maiden name, doctor = `PER_3`):
> Bonjour, je vous écris au sujet de mon fils, [PER_1.PRENOM:M] [PER_1.NOM:M], né le [PER_1.DATE_NAISSANCE:2011], que j'aimerais inscrire à la formation junior « Robotique » à [LOC_1.VILLE:Lausanne]. Étant mineur, c'est moi, sa mère [PER_2.PRENOM:F] [PER_2.NOM:F], qui gère le dossier — vous pouvez me joindre au [PER_2.TELEPHONE:Fixe] ou à [PER_2.EMAIL:Privé], nous habitons au [PER_2.ADRESSE:Rue], [PER_2.ADRESSE:NPA] [PER_2.ADRESSE:Ville]. [PER_1.PRENOM:M] est asthmatique ; son médecin, le Dr [PER_3.PRENOM:F] [PER_3.NOM:F] (cabinet à [LOC_2.VILLE:Renens]), a établi un certificat le 15.05.2024. Par ailleurs, j'avais moi-même suivi la formation « Photographie » en 2023 sous mon nom de jeune fille, [PER_2.PRENOM:F] [PER_2.NOM_JEUNE_FILLE:F] — mes deux comptes peuvent-ils être fusionnés ? Le paiement se fera depuis mon IBAN [PER_2.IBAN:Principal].
| Placeholder | Real value |
| ------------------------------------------------- | ---------------------------------- |
| `[PER_1.PRENOM:M]` / `[PER_1.NOM:M]` | Lucas / Favre |
| `[PER_1.DATE_NAISSANCE:2011]` | 04.07.2011 |
| `[PER_2.PRENOM:F]` / `[PER_2.NOM:F]` | Camille / Favre |
| `[PER_2.NOM_JEUNE_FILLE:F]` | Rochat |
| `[PER_2.TELEPHONE:Fixe]` | 021 555 12 34 |
| `[PER_2.EMAIL:Privé]` | camille.favre@bluewin.ch |
| `[PER_2.ADRESSE:Rue/NPA/Ville]` | 8 chemin des Vignes / 1009 / Pully |
| `[PER_3.PRENOM:F]` / `[PER_3.NOM:F]` | Nadia / Benali |
| `[LOC_1.VILLE:Lausanne]` / `[LOC_2.VILLE:Renens]` | Lausanne / Renens |
| `[PER_2.IBAN:Principal]` | CH56 0483 5012 3456 7800 9 |
The health detail ("asthmatique") is kept as non-identifying context, and the reference chain
("mon fils" / "sa mère" / "son médecin") is resolved into three distinct entities.
</details>
**[→ See all 10 examples, with full `mapping` and `legend` tables](./examples/RESULTS.md)**
## How this helps with the nLPD