Files
t2a_v2/docs/NUKE3_NEXT_STEPS.md
2026-03-05 00:37:41 +01:00

172 lines
6.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NUKE-3 — Plan de sprint court
## 3 Objectifs
1. **Réduire le taux REVIEW sur les dossiers sans DP** : 43/43 → cible < 50% REVIEW
2. **Améliorer la qualité du pool** : éliminer le bruit OCR et fusionner les doublons
3. **Activer le signal synthèse** : rendre motif_align opérant même sur les dossiers trackare
## 5 Patchs proposés (ordre d'impact)
### Patch 1 — Dedup par code dans `build_candidates()` ⭐⭐⭐
**Symptôme** : Même code CIM-10 apparaît 2× (edsnlp + regex) → le candidat se bat contre lui-même, delta artificiellement réduit.
**Patch minimal** : `src/medical/dp_selector.py`, fonction `build_candidates()`
```python
# Après la boucle de construction des candidats :
# Dedup par code : garder le meilleur section_strength, ajouter bonus multi-source
seen: dict[str, DPCandidate] = {}
for c in candidates:
if not c.code:
continue
if c.code in seen:
existing = seen[c.code]
existing.num_occurrences += 1
if c.section_strength > existing.section_strength:
existing.section_strength = c.section_strength
existing.source = c.source
else:
seen[c.code] = c
candidates = list(seen.values())
# Réindexer
for i, c in enumerate(candidates):
c.index = i
```
**Pourquoi ça aide** : Les 4 dossiers avec doublons (I26.9, K81.0, D69.6, J18.9) gagnent un candidat fusionné plus fort. Le bonus `occurrences` existant (+1 ou +2) s'active déjà sur `num_occurrences`.
**Test** : `test_dedup_same_code_merged()` — 2 candidats avec même code, sources différentes → 1 seul candidat avec meilleur section_strength.
**Effort** : 1h
---
### Patch 2 — Filtre bruit OCR dans `build_candidates()` ⭐⭐⭐
**Symptôme** : Candidats avec texte OCR corrompu ("C : 9.4", "C omprend décollement de la (d") polluent le pool et consomment des places dans top_k=7.
**Patch minimal** : `src/medical/dp_selector.py`, dans `build_candidates()`
```python
MIN_TERM_WORDS = 2
def _is_ocr_noise(text: str) -> bool:
"""Rejette les candidats dont le texte est du bruit OCR."""
clean = text.strip()
if len(clean) < 4:
return True
words = clean.split()
if len(words) < MIN_TERM_WORDS:
return True
# Ratio de caractères non-alpha suspect
alpha = sum(1 for ch in clean if ch.isalpha())
if alpha / max(len(clean), 1) < 0.5:
return True
return False
```
**Pourquoi ça aide** : Réduit le pool de 7 à ~4-5 candidats pertinents, améliore le delta.
**Test** : `test_ocr_noise_excluded()` — candidat "C : 9.4" exclu du pool.
**Effort** : 1h
---
### Patch 3 — Synthèse depuis top-level JSON + sections trackare ⭐⭐
**Symptôme** : 100% des REVIEW ont synthèse vide → `motif_align` ne fonctionne jamais. Le JSON a `sejour.motif` mais `build_synthese()` ne lit que `sections.motif_hospitalisation`.
**Patch minimal** : `src/medical/dp_selector.py`, fonction `build_synthese()`
```python
def build_synthese(dossier, parsed_data):
sections = parsed_data.get("sections", {})
motif = sections.get("motif_hospitalisation", "")
conclusion = sections.get("conclusion", "")
# Fallback : motif depuis le séjour (trackare)
if not motif and dossier.sejour.motif:
motif = dossier.sejour.motif
return {"motif": motif, "conclusion": conclusion, ...}
```
**Pourquoi ça aide** : Active le bonus `motif_align` (+2) sur les trackare qui stockent le motif dans `sejour.motif`, discriminant les candidats.
**Test** : `test_synthese_fallback_sejour_motif()` — synthèse avec motif depuis séjour.
**Effort** : 30min
---
### Patch 4 — Abaisser DELTA_CONFIRMED de 3.0 à 2.0 ⭐⭐
**Symptôme** : 13/43 REVIEW ont delta 2.0-2.9 — cas où le pré-ranker a une préférence nette mais pas assez pour le seuil actuel. Exemple : T83.5 (4.0) vs R50.9 (2.0) = delta 2.0 → REVIEW, alors que le symptôme (R50.9) est clairement un mauvais DP.
**Patch minimal** : `src/medical/dp_selector.py`
```python
DELTA_CONFIRMED = 2.0 # Était 3.0
```
**Pourquoi ça aide** : +13 CONFIRMED (30% des REVIEW), mais uniquement si les gardes A1/A2/A3 valident. Le hardening empêche les faux positifs.
**Test** : Adapter les fixtures existantes (dp_acute_vs_comorbidity.json utilise un delta attendu).
**Effort** : 30min (+ vérification non-régression)
---
### Patch 5 — DAS order bonus (premier listé = plus saillant) ⭐
**Symptôme** : En cas d'ex-aequo total (15 cas), il n'y a aucun signal pour départager. Or l'ordre des DAS dans le document médical n'est pas aléatoire — les premiers listés sont souvent les plus pertinents.
**Patch minimal** : `src/medical/dp_selector.py`, dans `score_candidates()`
```python
# 9. Bonus d'ordre (premier DAS listé = +1)
if c.index == 0:
score += 1
details["first_listed"] = 1
elif c.index == 1:
score += 0.5
details["second_listed"] = 0.5
```
**Pourquoi ça aide** : Brise les ex-aequo dans 15 cas (36% des REVIEW) avec un signal faible mais non-arbitraire. Le premier DAS listé reflète l'ordre du document source.
**Test** : `test_first_listed_bonus()` — 2 candidats identiques, le premier listé gagne.
**Effort** : 30min
---
## Ordre d'exécution
| # | Patch | Effort | Impact estimé | Pré-requis |
|---|-------|--------|---------------|------------|
| 1 | Dedup par code | 1h | 4 dossiers améliorés | Aucun |
| 2 | Filtre bruit OCR | 1h | ~5 dossiers pool nettoyé | Aucun |
| 3 | Synthèse fallback | 30min | Jusqu'à 43 dossiers (si motif trackare dispo) | Vérifier séjour.motif |
| 4 | DELTA 3.0 → 2.0 | 30min | +13 CONFIRMED | Patches 1+2 (pool propre) |
| 5 | DAS order bonus | 30min | Brise 15 ex-aequo | Après patch 4 |
**Total estimé** : 3h30
## Critères d'acceptation (KPI)
| KPI | Avant | Cible |
|-----|-------|-------|
| REVIEW rate (sans-DP) | 100% (43/43) | < 50% |
| CONFIRMED + evidence | 100% | 100% (maintenu) |
| DP symptôme R* (CONFIRMED) | 0% | < 5% |
| DP comorbidité (CONFIRMED) | 0% | < 3% |
| Candidats bruit OCR dans pool | ~5% | 0% |
| Ex-aequo (delta=0) | 36% (15/43) | < 15% |
## Prochaines étapes hors sprint
- **Gold standard CRH** : sélectionner 20 CRH avec DP expert pour mesurer `confirmed_accuracy`
- **Benchmark LLM ON** : relancer le pipeline avec `T2A_DP_RANKER_LLM=1` sur les 43 REVIEW
- **Extraction synthèse trackare** : parser le motif d'hospitalisation depuis les PDF trackare
---
*Plan rédigé le 2026-02-24 — benchmark offline sur 249 dossiers*