fix(core): charger gazetteer médicaments edsnlp depuis data/ (torch-free) + log si absent

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 09:36:08 +02:00
parent b196d00813
commit 6a992d87de
6 changed files with 4597 additions and 14 deletions

View File

@@ -256,24 +256,62 @@ except ImportError:
APP_VERSION = "0.11.0-mvp" # incrémenter avant rebuild release
# Gazetteer médicaments extrait de edsnlp/resources/drugs.json et versionné dans
# le dépôt (data/edsnlp/drugs.json). Lu EN PREMIER au runtime pour rester complet
# dans le build Windows torch-free (Plan 3), où edsnlp — qui importe torch en dur —
# n'est pas disponible. En mode frozen, __file__ pointe vers _MEIPASS, donc ce
# chemin résout le fichier embarqué (cf _load_bdpm_medication_names).
_EDSNLP_DRUGS_DATA_PATH = Path(__file__).parent / "data" / "edsnlp" / "drugs.json"
def _parse_edsnlp_drugs_json(path: Path) -> set:
"""Parse un drugs.json edsnlp (code ATC → liste de noms).
Retourne le set des noms mono-mot de longueur >= 4, en minuscules.
Parsing IDENTIQUE à l'historique (garantie de non-régression du gazetteer)."""
import json as _json
data = _json.loads(path.read_text(encoding="utf-8"))
result = set()
for _code, names in data.items():
for name in names:
if " " not in name and len(name) >= 4:
result.add(name.lower())
return result
def _load_edsnlp_drug_names() -> set:
"""Charge les noms de médicaments mono-mot depuis edsnlp/resources/drugs.json.
Retourne un set lowercase. Fallback silencieux si edsnlp absent."""
"""Charge les noms de médicaments mono-mot pour la whitelist anti-faux-positif.
Ordre de résolution (torch-free) :
1. data/edsnlp/drugs.json (fichier versionné, 0 dépendance edsnlp/torch) ;
2. fallback : package edsnlp (BASE_DIR/resources/drugs.json), comportement
historique en mode dev ;
3. échec total → log.warning explicite + set() (dégradation rendue visible).
Retourne un set lowercase."""
# 1. Fichier data versionné (disponible aussi en frozen torch-free).
try:
if _EDSNLP_DRUGS_DATA_PATH.exists():
return _parse_edsnlp_drugs_json(_EDSNLP_DRUGS_DATA_PATH)
except Exception as exc: # fichier corrompu → on tente le fallback
log.debug("Lecture %s échouée : %s", _EDSNLP_DRUGS_DATA_PATH, exc)
# 2. Fallback package edsnlp (dev).
try:
import edsnlp as _edsnlp
drugs_path = _edsnlp.BASE_DIR / "resources" / "drugs.json"
if not drugs_path.exists():
return set()
import json as _json
data = _json.loads(drugs_path.read_text(encoding="utf-8"))
result = set()
for _code, names in data.items():
for name in names:
if " " not in name and len(name) >= 4:
result.add(name.lower())
return result
except Exception:
return set()
if drugs_path.exists():
return _parse_edsnlp_drugs_json(drugs_path)
except Exception as exc:
log.debug("Fallback package edsnlp indisponible : %s", exc)
# 3. Échec total : rendre la dégradation visible (risque de sur-masquage).
log.warning(
"Gazetteer médicaments edsnlp indisponible (ni data/edsnlp/drugs.json "
"ni package edsnlp) — whitelist médicaments réduite, risque de sur-masquage"
)
return set()
def _load_bdpm_medication_names() -> set: