--- icon: lucide/play --- # Premier pipeline Vous allez construire un pipeline composant par composant, puis le lancer sur une phrase. Vous partez d'un détecteur, ajoutez le linker et l'anonymiseur, puis assemblez le tout. Le détecteur dépend de ce que vous cherchez. Un modèle NER comme GLiNER2 détecte des noms et des lieux qu'il n'a jamais vus. Une regex ne reconnaît que des formats fixes, comme une adresse email. !!! note "Prérequis" `piighost` installé, voir [Installation](installation.md). Le chemin regex n'utilise que le socle, sans extra. Le chemin GLiNER2 demande l'extra `gliner2` et télécharge un modèle au premier chargement. ## 1. Choisir un détecteur Le détecteur lit le texte et renvoie des détections, une par valeur trouvée. Le reste du pipeline est identique quel que soit le détecteur, alors choisissez celui qui correspond à votre texte. === "Regex (catalogue)" Un `RegexDetector` reconnaît des motifs, c'est-à-dire des chaînes de caractères qui suivent une structure fixe. On lui passe un dictionnaire qui associe un label à un motif. Un prénom n'a pas de structure fixe, donc les deux motifs ci-dessous listent simplement les valeurs de la phrase d'exemple. Ils illustrent le fonctionnement du pipeline, ils ne détectent pas d'autres noms. ```python from piighost.components.detector import RegexDetector patterns = { "PERSON": r"\b(?:Patrick|Marie)\b", "LOCATION": r"\bParis\b", } detector = RegexDetector(patterns) ``` Pour les formats fixes qui ne dépendent pas d'une langue, comme l'email et l'URL, le [catalogue piighost](https://catalog.piighost.dev) publie des groupes tout faits. Le groupe `generic` ci-dessous ne contient aucun motif de nom ni de lieu. Il est récupéré depuis le catalogue à chaque construction du détecteur. ```python from piighost.components.detector import RegexDetector detector = RegexDetector.from_catalog("catalog:piighost/generic") ``` === "GLiNER2 (NER)" Un NER est un modèle d'IA qui classe les mots d'un texte dans des catégories décidées à l'avance (nom, prénom, lieu, organisation). Contrairement à la regex, il n'a pas besoin de connaître les valeurs à l'avance. Il détecte un prénom qu'il n'a jamais vu. ```python from piighost.components.detector.ner import Gliner2Detector detector = Gliner2Detector( model="fastino/gliner2-multi-v1", labels=["PERSON", "LOCATION"], threshold=0.5, ) ``` Le premier argument est un nom de modèle chargé par GLiNER2, ou une instance déjà chargée. `labels` fixe les catégories interrogées. `threshold` est la confiance minimale au-dessus de laquelle une détection est gardée. ## 2. Regrouper les détections en entités Un même prénom peut apparaître plusieurs fois. Le linker regroupe les détections d'une même valeur et d'un même label en une seule entité, pour que chaque occurrence reçoive plus tard le même jeton. ```python from piighost.components.linker import ExactEntityLinker linker = ExactEntityLinker() ``` ## 3. Assigner un jeton à chaque entité L'anonymiseur remplace chaque entité par un placeholder, c'est-à-dire le jeton qui prend sa place dans le texte. Le jeton dépend de la factory choisie. `LabelCounterPlaceholderFactory` numérote les jetons par label. Cela donne `<>`{ .placeholder }, `<>`{ .placeholder }, `<>`{ .placeholder }. ```python from piighost.components.anonymizer import Anonymizer from piighost.components.placeholder import LabelCounterPlaceholderFactory factory = LabelCounterPlaceholderFactory() anonymizer = Anonymizer(factory) ``` ## 4. Assembler et lancer `AnonymizationPipeline` enchaîne les trois composants dans l'ordre. Il détecte, regroupe, puis remplace. Sa méthode `anonymize` est asynchrone. Elle renvoie un résultat dont l'attribut `text` porte la phrase dé-identifiée. ```python import asyncio from piighost.pipeline import AnonymizationPipeline pipeline = AnonymizationPipeline(detector, linker, anonymizer) async def main() -> None: text = "Patrick habite à Paris. Patrick aime Paris. Marie aussi." result = await pipeline.anonymize(text) print(result.text) asyncio.run(main()) ``` La sortie doit être : ```text <> habite à <>. <> aime <>. <> aussi. ``` Chaque occurrence de `Patrick`{ .pii } reçoit le même `<>`{ .placeholder }. `Paris`{ .pii } garde `<>`{ .placeholder } à ses deux apparitions. `Marie`{ .pii } reçoit le numéro suivant, `<>`{ .placeholder }. C'est le linker de l'étape 2 qui rend cette cohérence possible. ## Comment ça marche `AnonymizationPipeline` exécute trois étapes obligatoires. Le détecteur trouve les données confidentielles. Le linker regroupe les occurrences d'une même valeur en une entité. L'anonymiseur remplace chaque entité par le jeton de sa factory. Des étapes optionnelles (expansion des occurrences manquées, fusion d'entités) existent, désactivées par défaut. La résolution de chevauchement, elle, s'exécute par défaut. Seul le détecteur est strictement requis pour construire le pipeline, et ce minimum suffit pour un premier pipeline. ## Voir aussi - Pour décrire ce pipeline dans un fichier plutôt qu'en Python, voir la [référence de configuration](../configuration/toml.md). Un détecteur regex y prend ses catalogues avec `catalogs = ["catalog:piighost/generic"]`. - Pour dé-identifier au fil d'une conversation avec des jetons stables entre les messages, voir le [Pipeline conversationnel](conversation.md).