From 7b09b06065313c59899261177a4a3232e4af0092 Mon Sep 17 00:00:00 2001 From: Domi31tls Date: Tue, 2 Jun 2026 14:35:33 +0200 Subject: [PATCH] =?UTF-8?q?feat(detect):=20F3=20capture=20du=20nom=20apr?= =?UTF-8?q?=C3=A8s=20label=20"Nom=20usuel=20:"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le pipeline ne reconnaissait pas le label "Nom usuel :" — utilisé dans certains comptes-rendus type BACTERIO. Ajout d'une regex dédiée RE_EXTRACT_NOM_USUEL qui : 1. Trouve "Nom usuel :" en début de ligne 2. Skippe les lignes qui ne commencent pas par une lettre majuscule (date au format DD/MM/YYYY, placeholders entre crochets, lignes vides) 3. Capture le premier token en MAJUSCULES ≥4 chars Cas couvert : BACTERIO 23232115 contient SIMONET Marie lise Nom usuel : 14/03/1985 OYARCABAL OYARCABAL est ainsi extrait avec contexte "high" (champ DPI structuré quasi-certain) et masqué. Test unitaire rapide validé sur l'exemple ci-dessus. Reste à faire : F2 (SIMONET — pattern NAME+PRENOM+PRENOM sans label) — non trivial sans label, à implémenter avec heuristique contextuelle (top du doc, etc.). Reporté. Co-Authored-By: Claude Opus 4.7 (1M context) --- anonymizer_core_refactored_onnx.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/anonymizer_core_refactored_onnx.py b/anonymizer_core_refactored_onnx.py index d42d359..f1e5804 100644 --- a/anonymizer_core_refactored_onnx.py +++ b/anonymizer_core_refactored_onnx.py @@ -572,6 +572,17 @@ RE_EXTRACT_NOM_UTILISE = re.compile( r"([A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑ][A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑa-zéèàùâêîôûäëïöüçñ\-\' ]+?)(?:\s*$)", re.MULTILINE, ) +# F3 — capture du nom après "Nom usuel :" : le label peut être suivi de la +# date de naissance ou autres champs avant le nom. On skippe les lignes ne +# commençant pas par une majuscule (date au format DD/MM/YYYY, placeholders, +# champs vides) puis on capture le premier token en MAJUSCULES (≥4 chars). +# Cas typique BACTERIO : "Nom usuel :\n14/03/1985\nOYARCABAL". +RE_EXTRACT_NOM_USUEL = re.compile( + r"Nom\s+usuel\s*:\s*\n" + r"(?:[^A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑ\n][^\n]*\n)*" + r"([A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑ][A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑ\-\']{3,})", + re.MULTILINE, +) RE_EXTRACT_PRENOM = re.compile( r"Pr[ée]nom\s+(?:de\s+naissance|utilis[ée])\s*:\s*" r"([A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑ][A-ZÉÈÀÙÂÊÎÔÛÄËÏÖÜÇÑa-zéèàùâêîôûäëïöüçñ\-\' ]+?)(?:\s*$)", @@ -2140,6 +2151,9 @@ def _extract_document_names(full_text: str, cfg: Dict[str, Any]) -> Tuple[set, s _add_tokens_force_all(m.group(1), "RE_EXTRACT_NOM_NAISSANCE", "high") for m in RE_EXTRACT_NOM_UTILISE.finditer(full_text): _add_tokens_force_all(m.group(1), "RE_EXTRACT_NOM_UTILISE", "high") + # F3 — "Nom usuel :" + ligne suivante (skip date intermédiaire) + for m in RE_EXTRACT_NOM_USUEL.finditer(full_text): + _add_tokens_force_all(m.group(1), "RE_EXTRACT_NOM_USUEL", "high") for m in RE_EXTRACT_NOM_PRENOM.finditer(full_text): _add_tokens_force_all(m.group(1), "RE_EXTRACT_NOM_PRENOM", "high") for m in RE_EXTRACT_PRENOM.finditer(full_text):