fix(detect): RPPS avec qualificateur (RPPS prescripteur :, RPPS de garde :…) (#1)

Étend `RE_RPPS` pour tolérer 0 à 3 mots qualificateurs entre `RPPS`
et le séparateur `:` ou `-`. Couvre les variantes observées :
- RPPS prescripteur :
- RPPS du médecin signataire :
- RPPS de garde -
- N° RPPS :

Si un qualificateur est présent, le séparateur (`:` ou `-`) devient
obligatoire pour éviter d'aspirer du narratif (faux positif type
"Le RPPS est consulté pour vérifier 12345678901 dans la base").

La lambda `_repl_rpps` reconstruit `RPPS : [RPPS]` en sortie : le
qualificateur est consommé mais perdu (pas de fuite, choix cosmétique).

Cas 005_bacterio_complete passe désormais (retiré de KNOWN_FAILURES).
La fuite `10101010101` derrière `RPPS prescripteur :` est masquée.

Cohérent avec le cadrage section 10.1 (règle cœur générique
applicable à tout établissement de santé français — pas de
spécificité locale).

Tests : 72 passed, 1 xfailed (avant : 71 passed, 2 xfailed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-27 22:33:01 +02:00
parent 7242b5350e
commit c7e71072e7
4 changed files with 22 additions and 11 deletions

View File

@@ -391,7 +391,19 @@ RE_IPP = re.compile(r"\b(?:I\.?P\.?P\.?|IPP|N°\s*Ipp)\s*[:\-]?\s*([A-Za-z0-9]{6
RE_CSULT = re.compile(r"\b(?:N°\s*Csult|N°\s*Interv)\s*[:\-]?\s*(\d{6,})\b", re.IGNORECASE)
RE_FINESS = re.compile(r"\b(?:N°\s*)?FINESS?\s*[:\-]?\s*(\d{9})\b", re.IGNORECASE)
RE_OGC = re.compile(r"\b(?:N°\s*)?OGC\s*[:\-]?\s*([A-Za-z0-9\-]{1,})\b", re.IGNORECASE)
RE_RPPS = re.compile(r"\b(?:N°\s*)?RPPS\s*[:\-]?\s*(\d{8,11})\b", re.IGNORECASE)
RE_RPPS = re.compile(
r"\b(?:N°\s*)?RPPS"
# 0 à 3 mots qualificateurs entre RPPS et la valeur :
# "RPPS prescripteur :", "RPPS du médecin signataire :",
# "RPPS de garde :", etc. Si qualificateur présent, le séparateur
# est obligatoire pour éviter d'aspirer du narratif.
r"(?:"
r"(?:\s+[A-Za-zéèàùÉÈÀÙ'-]+){1,3}\s*[:\-]\s*"
r"|\s*[:\-]?\s*"
r")"
r"(\d{8,11})\b",
re.IGNORECASE,
)
RE_NUM_ADHERENT = re.compile(
r"\b(?:n[°o]?\s*|num[ée]ro\s+(?:d[']\s*)?)adh[ée]rent[e]?\s*[:\-]?\s*([A-Z0-9]{6,15})\b",
re.IGNORECASE,

View File

@@ -9,7 +9,7 @@ N° venue
[NOM] [NOM]
[NDA]
IPP : [IPP]
RPPS prescripteur : [RPPS]
RPPS : [RPPS]
Prélèvement : ECBU
Date de prélèvement : 02/04/2024 à 08h30

View File

@@ -20,11 +20,14 @@ Points critiques :
- le nom composé `MARIE-PIERRE` doit être traité en bloc ;
- le biologiste signataire (`Dr DUHALDE Anne`) doit être masqué.
Écarts détectés au runner (à corriger) :
- **fuite RPPS critique** : `RPPS prescripteur : 10101010101` n'est pas masqué.
La règle RPPS courante attend `RPPS\s*:\s*\d{11}` et ne tolère pas un
qualificateur (`prescripteur`, `signataire`, `prescripteur du jour`, …)
entre `RPPS` et `:`. Mêmes layouts probables pour FINESS, IPP, NDA.
Écart résolu dans la session 2026-04-27 :
- **fuite RPPS** : pattern `RE_RPPS` étendu pour tolérer 0 à 3 mots
qualificateurs (`prescripteur`, `signataire`, `du médecin`, `de garde`)
entre `RPPS` et `:`. Le qualificateur est consommé par le matcher et
la sortie reconstruit `RPPS : [RPPS]` (perte cosmétique du qualificateur,
pas de fuite).
Écart résiduel cosmétique :
- bloc `Dr DUHALDE Anne` masqué comme un seul `[NOM]` plutôt que
`Dr [NOM] [NOM]` — accepté tant qu'aucun token de nom ne fuit ; à
retraiter si l'usage demande la conservation du préfixe `Dr`.

View File

@@ -30,10 +30,6 @@ from tools.run_synthetic_review_corpus import ( # noqa: E402
KNOWN_FAILURES: dict[str, str] = {
"005_bacterio_complete": (
"RPPS avec qualificateur (`RPPS prescripteur :`) non détecté — "
"fuite identifiant médecin."
),
"009_multi_etablissements": (
"Fuites résiduelles : suffixe `de Bordeaux` après "
"[ETABLISSEMENT], CHCB en fin de phrase. À traiter via "