Aller au contenu

Détecteurs prêts à l'emploi

piighost tire du catalogue piighost des groupes de motifs regex prêts à l'emploi pour les PII à structure fixe (email, IP, IBAN, téléphone). Ce guide montre comment les charger, les fusionner et combiner plusieurs détecteurs, avec le seul cœur de piighost.

Quatre groupes du catalogue couvrent les formats courants. Chacun est un ensemble d'entrées label vers pattern.

  • catalog:piighost/generic, email, URL, IPv4, carte bancaire, indépendants du pays
  • catalog:piighost/us, téléphone, ZIP, ITIN, SSN, préfixés US_
  • catalog:piighost/eu, IBAN ISO 13616 pan-européen
  • catalog:piighost/fr, téléphone, IBAN, NIR, SIRET, SIREN, préfixés FR_

Une référence sans suffixe suit la dernière version du groupe, récupérée à chaque construction d'un détecteur. Pour figer une version, ajoutez son commit après un deux-points, comme catalog:piighost/generic:fab51b33. Le groupe est alors récupéré une seule fois, puis relu depuis le cache sur disque, hors ligne compris. Les secrets comme les clés d'API sont dans les groupes du catalogue piighost/secrets et piighost/secrets-extended. Ces groupes se tirent de la même façon, par exemple avec catalogs = ["catalog:piighost/secrets"] dans une config.

Pour le détail des labels, voir la référence des détecteurs.

Utiliser un seul groupe

Construisez un RegexDetector à partir du groupe avec from_catalog, puis montez le pipeline.

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("Email alice@example.com, server 192.168.1.42.")
    print(result.text)


asyncio.run(main())

La sortie doit être :

Email <<EMAIL:1>>, server <<IPV4:1>>.

Fusionner générique et régional

Si vous voulez couvrir à la fois les PII génériques et celles d'une région, tirez chaque groupe avec pull et fusionnez les dictionnaires obtenus. pull renvoie un dictionnaire label vers pattern. Quand deux dictionnaires ont un label en commun, l'entrée du dictionnaire de droite l'emporte.

from piighost.catalog import pull

patterns = {**pull("catalog:piighost/generic"), **pull("catalog:piighost/fr")}
detector = RegexDetector(patterns)
pipeline = AnonymizationPipeline(detector)


async def main() -> None:
    result = await pipeline.anonymize(
        "IBAN FR7630006000011234567890189, email marie@exemple.fr, tel 06 12 34 56 78."
    )
    print(result.text)


asyncio.run(main())

La sortie doit être :

IBAN <<FR_IBAN:1>>, email <<EMAIL:1>>, tel <<FR_PHONE:1>>.

Pour ne garder que certains labels, construisez un dictionnaire à la carte.

generic = pull("catalog:piighost/generic")
french = pull("catalog:piighost/fr")
patterns = {
    "EMAIL": generic["EMAIL"],
    "FR_IBAN": french["FR_IBAN"],
}
detector = RegexDetector(patterns)

Combiner plusieurs détecteurs

CompositeDetector exécute plusieurs détecteurs sur le même texte et concatène leurs détections. Les chevauchements sont arbitrés par l'étage de résolution du pipeline. C'est ainsi qu'on couple un détecteur regex à un détecteur qui reconnaît des noms.

from piighost.components.detector import (
    CompositeDetector,
    ExactMatchDetector,
    RegexDetector,
)

exact_detector = ExactMatchDetector({"Patrick": "PERSON"})
regex_detector = RegexDetector.from_catalog("catalog:piighost/generic")
detector = CompositeDetector([exact_detector, regex_detector])
pipeline = AnonymizationPipeline(detector)


async def main() -> None:
    result = await pipeline.anonymize("Patrick emailed alice@example.com.")
    print(result.text)


asyncio.run(main())

La sortie doit être :

<<PERSON:1>> emailed <<EMAIL:1>>.

En production, remplacez ExactMatchDetector par un détecteur NER ou LLM, voir la référence des détecteurs. ExactMatchDetector sert ici à garder l'exemple reproductible sans modèle.

Traiter un texte long

Un détecteur NER a une fenêtre de contexte bornée, et un long document peut la dépasser. ChunkedDetector enveloppe n'importe quel détecteur, découpe le texte en fragments qui se chevauchent, détecte sur chacun et reprojette les positions sur le texte d'origine.

from piighost.components.detector import ChunkedDetector, RegexDetector
from piighost.text import RecursiveCharacterTextSplitter

regex_detector = RegexDetector.from_catalog("catalog:piighost/generic")
splitter = RecursiveCharacterTextSplitter(chunk_size=40, chunk_overlap=10)
detector = ChunkedDetector(regex_detector, splitter=splitter)
pipeline = AnonymizationPipeline(detector)


async def main() -> None:
    text = (
        "Filler text here. Reach alice@example.com now. "
        "More filler padding words. Then bob@example.org later."
    )
    result = await pipeline.anonymize(text)
    print(result.text)


asyncio.run(main())

La sortie doit être :

Filler text here. Reach <<EMAIL:1>> now. More filler padding words. Then <<EMAIL:2>> later.

Laissez splitter=None pour un RecursiveCharacterTextSplitter par défaut, réglé pour de vrais documents. Le chunk_size réduit ci-dessus ne sert qu'à forcer plusieurs fragments dans un court exemple.

Charger les groupes depuis un fichier de config

Si vous pilotez le pipeline par un fichier de configuration plutôt que par du code, un détecteur regex accepte une clé catalogs.

[detector]
type = "regex"
catalogs = ["catalog:piighost/generic", "catalog:piighost/fr"]

Le détecteur fusionne d'abord les groupes, puis les patterns en ligne. Pour un même label, un motif en ligne l'emporte donc sur celui d'un groupe. Voir la configuration TOML.

Voir aussi