Deux corrections exploitant mieux les gazetteers FINESS/INSEE pour réduire la
dépendance au YAML force_mask_terms.
1. scripts/build_finess_gazetteers.py : ne lisait que col 1 (finess_et) du CSV.
Les col 2 (entjur, entité juridique) étaient ignorés. ~48k numéros
juridiques manqués, dont 640780417 (CHCB entjur) forcé en YAML à cause
de cette lacune. Fix : lecture col 1 + col 2 avec déduplication.
Régénération : 101 941 → 150 436 numéros (+48 495).
2. anonymizer_core_refactored_onnx.py :
- _FINESS_ETAB_NAMES (122k noms) chargé mais jamais consulté après le
refactoring NER-first (le matching passe par l'Aho-Corasick sur
etablissements_distinctifs.txt). Suppression → -122k entrées RAM.
- _INSEE_PRENOMS (lowercase) et _INSEE_PRENOMS_SET (uppercase sans accents)
lisaient deux fois le même fichier prenoms_france.txt. Fusion en une
seule passe disque, les deux formes dérivées en mémoire. -36k lectures.
Validation :
- 640780417 présent dans _FINESS_NUMBERS après rebuild
- 122 hits sur trackare-18007562 (non-régression)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Suite de l'externalisation des règles. Trois listes étaient codées en dur dans
anonymizer_core_refactored_onnx.py et impossibles à modifier par les
établissements sans recompiler :
- _NEVER_MASK_AS_NAME (12 entrées) — labels DPI structurels
- _DPI_LABELS_BLACKLIST (14 entrées, doublon partiel du précédent)
- _COMPANION_BLACKLIST (~75 entrées) — spécialités, labos pharma, mots ambigus
Les deux premières fusionnées dans data/dpi_labels_blacklist.txt (11 entrées
uniques, comparaison case-insensitive). La troisième dans
data/companion_blacklist.txt (75 entrées, comparaison uppercase).
Ajout de deux clés YAML pour enrichissement par établissement :
- additional_dpi_labels (ex: "Service", "Statut")
- additional_companion_blacklist (ex: spécialités locales)
Les 3 niveaux cumulatifs habituels s'appliquent : code (vide) → fichiers data/
→ YAML config. Chargement au démarrage avec log INFO du nombre d'entrées.
Test trackare-18007562-23054899 : 122 hits, 0 régression, 0 DPI label masqué
comme NOM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
La cross-validation NER (_cross_validate_name_candidates) gère désormais
les décisions contextuelles nom/terme-médical. Les stop-words purement
médicaux sont supprimés :
- data/stopwords_manuels.txt : 1307 → 233 entrées (uniquement les mots
ambigus qui sont aussi des noms/prénoms INSEE)
- _MEDICAL_STOP_WORDS_SET hardcodé : ~400 → 80 entrées essentielles
(mots courts, formes galéniques, titres hospitaliers)
- Les enrichissements BDPM (~7300), edsnlp (~2000) et fichier externe
sont conservés tels quels
Score qualité inchangé : 100/100 (A+), 0 fuite, 0 faux positif.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toutes les listes de règles sont maintenant modifiables sans toucher
au code Python :
Fichiers de données (data/) :
- stopwords_manuels.txt : 1307 termes médicaux/techniques
- villes_blacklist.txt : 117 communes à ne pas matcher
- medicaments_stopwords.txt : 7312 médicaments BDPM (existant)
- Chargés automatiquement au démarrage
Config YAML (dictionnaires.yml) :
- additional_stopwords : mots supplémentaires par établissement
- additional_villes_blacklist : villes supplémentaires
- whitelist_phrases : phrases à ne jamais anonymiser
- force_mask_terms : mots à toujours masquer
Chaîne de chargement : code dur → fichiers data/ → YAML config
Les 3 niveaux se cumulent (union).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nouveau script build_finess_gazetteers.py : extraction noms distinctifs, villes, numéros depuis CSV open data
- Automate Aho-Corasick (pyahocorasick) pour matching multi-pattern en ~1.7ms/page
- 108K patterns indexés (noms composés >= 8 chars, mots uniques >= 10 chars)
- Blacklist mots génériques (clinique, pharmacie, etc.) et stop words médicaux
- Normalisation position-preserving (sans accents, même longueur)
- Construction lazy de l'AC (après chargement des stop words)
- Intégration dans _mask_line_by_regex et selective_rescan
- Nouveau gazetteer villes_finess.txt (11,660 villes)
- Résultats : "Girandières" → masqué, "Côte Basque" → masqué, 0 FP sur termes médicaux courants
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Prénoms INSEE renforcent la confiance NER (prénom connu → ne pas filtrer)
- Communes INSEE disponibles pour distinction ville/nom de famille
- Export 29 fichiers silver annotations (252K tokens, 12.8K entités) pour fine-tuning
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>