--- icon: lucide/code --- # Dé-identifier et restaurer un texte Vous avez un texte contenant des données confidentielles et vous voulez le dé-identifier, l'envoyer à un LLM, puis restaurer les valeurs d'origine dans la réponse. Ce guide fait l'aller-retour avec le seul cœur de `piighost`, sans modèle ni dépendance optionnelle. Les motifs du détecteur viennent du [catalogue piighost](https://catalog.piighost.dev). Ils sont récupérés à chaque construction du détecteur, ce qui demande un accès réseau. Installez le cœur. === "uv" ```bash uv add piighost ``` === "pip" ```bash pip install piighost ``` ## Faire l'aller-retour Un pipeline enchaîne un détecteur, un linker et un anonymiseur. Seul le détecteur est obligatoire. Le linker vaut par défaut `ExactEntityLinker` et l'anonymiseur `Anonymizer(LabelCounterPlaceholderFactory())`. `anonymize` renvoie le texte dé-identifié et le jeton attribué à chaque entité. `deanonymize` rejoue cette correspondance en sens inverse. ```python import asyncio from piighost.components.detector import RegexDetector from piighost.pipeline import AnonymizationPipeline detector = RegexDetector.from_catalog("catalog:piighost/generic") pipeline = AnonymizationPipeline(detector) async def main() -> None: result = await pipeline.anonymize("Contact alice@example.com from 192.168.1.42.") print(result.text) restored = pipeline.deanonymize(result.text, result.tokens) print(restored) asyncio.run(main()) ``` La sortie doit être : ```text Contact <> from <>. Contact alice@example.com from 192.168.1.42. ``` `result.text` porte `<>`{ .placeholder } à la place de `alice@example.com`{ .pii }. `result.tokens` associe chaque entité à son jeton. Passez-le tel quel à `deanonymize` pour retrouver le texte d'origine. ## Restaurer une réponse du LLM `deanonymize` restaure n'importe quel texte portant les jetons, pas seulement celui que le pipeline a produit. Si le LLM répond avec `<>`{ .placeholder }, réinjectez les vraies valeurs avec la même correspondance `result.tokens`. ```python async def main() -> None: result = await pipeline.anonymize("Contact alice@example.com from 192.168.1.42.") llm_reply = "I sent the message to <>." print(pipeline.deanonymize(llm_reply, result.tokens)) asyncio.run(main()) ``` La sortie doit être : ```text I sent the message to alice@example.com. ``` ## Regrouper les occurrences répétées Une même valeur citée plusieurs fois reçoit un seul jeton, donc le LLM garde le fil. `ExactEntityLinker` regroupe les occurrences par valeur et par label. ```python from piighost.components.detector import ExactMatchDetector detector = ExactMatchDetector({"Patrick": "PERSON", "Paris": "LOCATION"}) pipeline = AnonymizationPipeline(detector) async def main() -> None: result = await pipeline.anonymize("Patrick habite à Paris. Patrick aime Paris.") print(result.text) asyncio.run(main()) ``` La sortie doit être : ```text <> habite à <>. <> aime <>. ``` `ExactMatchDetector` détecte des valeurs littérales fixées. L'exemple reste ainsi reproductible sans charger de modèle. Pour du texte libre, remplacez-le par un détecteur NER (reconnaissance d'entités nommées) ou LLM, voir la [référence des détecteurs](../reference/detectors.md). ## Changer la forme des jetons `LabelCounterPlaceholderFactory`, la factory par défaut, produit `<>`{ .placeholder }. Si vous voulez une autre forme de jeton, passez au pipeline un `Anonymizer` construit sur une autre factory. Ici, `LabelHashPlaceholderFactory` remplace le numéro par une empreinte courte. ```python import asyncio from piighost.components.anonymizer import Anonymizer from piighost.components.detector import ExactMatchDetector from piighost.components.placeholder import LabelHashPlaceholderFactory from piighost.pipeline import AnonymizationPipeline detector = ExactMatchDetector({"Patrick": "PERSON", "Marie": "PERSON"}) anonymizer = Anonymizer(LabelHashPlaceholderFactory()) pipeline = AnonymizationPipeline(detector, anonymizer=anonymizer) async def main() -> None: result = await pipeline.anonymize("Patrick, Marie, Patrick.") print(result.text) asyncio.run(main()) ``` La sortie doit être : ```text <>, <>, <>. ``` L'empreinte est calculée à partir du label et du rang de l'entité, jamais à partir de la valeur. `Patrick`{ .pii } garde donc le même jeton à ses deux apparitions, et `Marie`{ .pii } en reçoit un autre. Pour restaurer les valeurs, la factory doit préserver l'identité, c'est-à-dire donner un jeton distinct à chaque valeur. `LabelCounterPlaceholderFactory` le fait. `LabelPlaceholderFactory` ne le fait pas, parce qu'elle donne le même `<>`{ .placeholder } à deux personnes distinctes. Voir la page [Fabriques de placeholders](../placeholder-factories.md). ## Voir aussi - [Détecteurs prêts à l'emploi](detectors.md) pour combiner groupes du catalogue et détecteurs. - [Référence du pipeline](../reference/pipeline.md) pour les étages optionnels. - [Étendre piighost](../extending.md) pour écrire vos propres composants.