diff --git a/anonymizer_core_refactored_onnx.py b/anonymizer_core_refactored_onnx.py index 2214dd4..54153c1 100644 --- a/anonymizer_core_refactored_onnx.py +++ b/anonymizer_core_refactored_onnx.py @@ -187,6 +187,47 @@ _INSEE_PRENOMS_SET: set = set() # uppercase sans accents _INSEE_COMMUNES: set = set() # uppercase _INSEE_NOMS_FAMILLE: set = set() # uppercase sans accents +# Gazetteer mondial paranames (Wikidata CC BY 4.0 — Sälevä & Lignos 2024) +# Fallback étendu après INSEE pour couvrir les noms étrangers présents en +# France (basques, maghrébins, asiatiques, africains, etc.) absents du +# gazetteer INSEE France. Chargé en lazy (au 1er besoin) pour ne pas +# pénaliser le splash de démarrage. +_PARANAMES_NOMS_SET: set = set() +_PARANAMES_LOADED: bool = False + + +def _load_paranames_noms() -> set: + """Charge le gazetteer paranames (Wikidata) en lazy. + + Fichier attendu : data/paranames/noms_famille_world.txt.gz + Si absent, retourne set vide (fallback transparent — comportement actuel). + + Cible : couvrir les noms étrangers présents en France absents d'INSEE + (basques, maghrébins, asiatiques, africains, etc.). + """ + global _PARANAMES_NOMS_SET, _PARANAMES_LOADED + if _PARANAMES_LOADED: + return _PARANAMES_NOMS_SET + _PARANAMES_LOADED = True + # Chercher le fichier relatif au module (compat dev + EXE PyInstaller) + try: + base = Path(__file__).parent + except NameError: + base = Path.cwd() + path = base / "data" / "paranames" / "noms_famille_world.txt.gz" + if not path.exists(): + log.info("paranames gazetteer absent (%s) — fallback INSEE seul", path) + return _PARANAMES_NOMS_SET + try: + import gzip + with gzip.open(path, "rt", encoding="utf-8") as f: + _PARANAMES_NOMS_SET = {line.strip() for line in f if line.strip()} + log.info("paranames loaded: %d noms (CC BY 4.0 — Sälevä & Lignos 2024)", + len(_PARANAMES_NOMS_SET)) + except Exception as e: + log.warning("paranames load failed: %s — fallback INSEE seul", e) + return _PARANAMES_NOMS_SET + def _normalize_nfkd_upper(s: str) -> str: """Supprime les accents et met en majuscules (pour matching INSEE).""" @@ -2355,7 +2396,12 @@ def _cross_validate_name_candidates( tok_lower = tok.lower() is_ner_confirmed = tok_upper in ner_confirmed_tokens - is_in_insee = tok_upper in insee_noms or tok_upper in insee_prenoms + # is_in_insee → étendu à paranames (gazetteer mondial Wikidata) en + # fallback : couvre les noms étrangers en France (basques, maghrébins, + # asiatiques, africains, etc.) absents du gazetteer INSEE France. + # paranames est chargé en lazy au 1er appel (cache global). + is_in_insee = (tok_upper in insee_noms or tok_upper in insee_prenoms + or tok_upper in _load_paranames_noms()) is_stopword = tok_lower in medical_stopwords strength = cand.context_strength