Commit Graph

64 Commits

Author SHA1 Message Date
dom
2701efb1d2 feat: CRH diag sections + DP scoring bonus + evidence by code
- crh_parser: 3 nouvelles sections (diag_sortie, diag_principal, synthese)
  avec garde-fou début de ligne pour éviter faux positifs mid-sentence
- dp_selector: NUKE-3 sélecteur DP déterministe (548 lignes)
  - build_candidates/score_candidates/select_dp
  - bonus +4 pour mention dans diag_sortie/diag_principal
  - bonus +2 pour mention dans synthese
  - hardening DIM : A1 evidence, A2 mono-fragile, A3 confidence cap
  - _collect_evidence match par terme OU code CIM-10
  - LLM tiebreaker optionnel (DP_RANKER_CONSTRAINED)
- fusion: propagation dp_selection depuis le dossier source du DP retenu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:28:31 +01:00
dom
1e79b7cc52 feat: viewer — affichage qualité CPAM, traçabilité décisions DP/DAS, VetoReport et bio
- CPAM : badge quality_tier (A/B/C), bandeau requires_review, warnings catégorisés, force probante dossier
- DP/DAS : code suggestion barré → code final si modifié, ligne grisée si ruled_out, badges décision + règles
- DAS : badge needs_info avec détails, raison ruled_out sous la ligne
- VetoReport : section contestabilité avec verdict, barre score/100, tableau issues HARD/MEDIUM/LOW
- Biologie : badge Suspect avec tooltip, valeurs écartées en details pliable
- Nouveau filtre Jinja2 decision_badge, import _assess_dossier_strength (pas de duplication)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:56:15 +01:00
dom
cc642c1143 fix: max_tokens extraction CPAM et validation adversariale 1500→3000
Les deux appels tronquaient systématiquement (done_reason=length),
causant des JSON invalides et des faux positifs adversariaux.
num_predict n'a aucun impact sur VRAM ni sur les réponses courtes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:12:26 +01:00
dom
d192af74ec feat: évaluation force probante dossier + seuils qualité relaxés pour dossiers faibles
Score 0-10 basé sur les preuves objectives (bio/img/trt/actes).
Dossier faible (score < 3) : prompt LLM adapté + seuil adversarial
abaissé (score 2-3 → Tier B au lieu de C). Les éléments contextuels
(âge, IMC, urgence) restent dans le prompt mais hors du scoring car
ils ne constituent pas des preuves opposables à un contrôleur CPAM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:19:43 +01:00
dom
1844d1be7e feat: sanitisation déterministe des codes CIM-10 hors périmètre CPAM
Le LLM (deepseek) propose systématiquement des codes alternatifs (D62,
T81.0, T80, R39.2) malgré l'interdiction dans le prompt. Ces codes
déclenchaient des warnings CRITIQUE → Tier C automatique.

Solution conforme au principe "LLM propose, moteur de règles dispose" :
- _sanitize_unauthorized_codes() supprime les codes hors whitelist du
  texte de la réponse AVANT toute validation
- Nettoyage propre : "D62 — libellé" → "libellé", "(D62)" → ""
- _build_whitelist_prefixes() factorisé en helper partagé
- Sanitisation appliquée après génération ET après correction
- 9 tests unitaires couvrant tous les cas (parenthèses, tirets, multiple)

Résultat live : 0 warning CRITIQUE "code hors périmètre" sur 3 dossiers
(vs 6 warnings CRITIQUE avant). Le seul CRITIQUE restant est le score
adversarial bas, qui reflète des limites de raisonnement du modèle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:18:42 +01:00
dom
8e0ed1220d fix: max_tokens CPAM 6000→16000 + diagnostic troncature Ollama
- Argumentation + correction : max_tokens porté à 16000 (num_predict)
- ollama_client : log done_reason=length pour détecter les troncatures serveur
- Résultat live : 1/3 Tier B (dossier 132 passé de C à B, score 5/10)
- Les 2 Tier C restants sont bloqués par hallucination de codes et
  absence de données bio, pas par max_tokens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:00:08 +01:00
dom
4d49d4e114 feat: grounding CPAM — tags DP/DAS/ANT/COMPL + fuzzy matching CIM-10 + prompt renforcé
Cause racine du Tier C : le LLM inventait des tags ([C83.3], [Antécédents])
car _build_tagged_context() ne taguait que bio/img/trt/actes. Le DP, les DAS,
antécédents et complications n'avaient aucun tag citable.

- cpam_context: 4 nouveaux types de tags [DP], [DAS-N], [ANT-N], [COMPL-N]
- cpam_validation: fuzzy matching — résout les refs CIM-10 nues vers le tag contenant ce code
- templates: liste explicite des tags valides, interdiction d'inventer des tags
- tests: 18 nouveaux tests (tags, fuzzy match, grounding DAS/DP)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:56:07 +01:00
dom
e77c10da7d fix: réparation JSON tronqué + retry 429 + whitelist codes CPAM anti-hallucination
- parse_json_response : réparation JSON tronqué par max_tokens (fermeture
  auto des structures ouvertes), meilleur stripping des blocs fencés avec
  texte superflu après la fermeture ```
- call_ollama : retry avec backoff exponentiel (1s/2s/4s) pour les erreurs
  429 rate limit, 3 tentatives au lieu de 2
- Validation adversariale : max_tokens 800 → 1500
- Prompt CPAM : whitelist PÉRIMÈTRE DE CODES AUTORISÉS (dossier DP+DAS +
  UCR) avec interdiction explicite des codes hors périmètre
- Tests : 19 tests parse_json/_repair_truncated_json, 6 tests whitelist

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:33:39 +01:00
dom
5d5f119057 feat: quality_tier CPAM (A/B/C) + requires_review + warnings catégorisés
- ControleCPAM enrichi : quality_tier, requires_review, quality_warnings
- _assess_quality_tier() : classification basée sur score adversarial + warnings
  - Tier C (requires_review) : score <4, code hors périmètre, >2 preuves non traçables
  - Tier B : score 4-6, warnings mineurs
  - Tier A : score >=7, 0 critique
- _format_response() : bandeau "REVUE MANUELLE REQUISE" pour tier C,
  sections CRITIQUES/MINEURS séparées
- Badge qualité dans le viewer CPAM (vert A / orange B / rouge C)
- 17 tests : tier A/B/C, bandeau, séparation warnings, backward compat

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:01:21 +01:00
dom
77ffbc56d4 feat: CODE_CORRECTIONS 12 règles déterministes + sentinel REJECT
- CODE_CORRECTIONS passe de 1 à 12 règles (corrections + rejets)
- REJECT_SENTINEL pour codes trop vagues (R69, R69.8, Z53.9, D71.9) ou inexistants
- Corrections : J96.0→J96.00, I50.9→I50.1 (IC gauche), N17.9→N17.0 (NTA),
  E11.9→E11.65 (DT2 insuline), K92.2→K92.0 (hématémèse), G40.9→G40.3 (épilepsie)
- _apply_code_corrections() gère REJECT : DP→None, DAS→supprimé + alerte
- 21 tests paramétrés (corrections, rejets, non-corrections)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:01:06 +01:00
dom
1a3c523987 feat: BIO_NORMALS 33 analytes + interprétations cliniques + cohérence DAS/bio étendue
- BIO_NORMALS passe de 13 à 33 tests (cardio, infectio, métabo, thyroïde, hémato, hépatique)
- _BIO_INTERPRETATION synchronisé (33 entrées, 3 clés high/low/normal chacune)
- _DAS_BIO_CHECKS étendu de 13 à 38 patterns (sepsis, infarctus, EP, diabète, thyroïde, etc.)
- lab_value_sanity.yaml étendu avec 20 garde-fous plausibilité nouveaux tests
- tests/test_bio_normals.py : 32 tests (complétude, concordance, _is_abnormal)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:00:53 +01:00
dom
3c070f3c1d refactor: split cpam_response → cpam_rag, cpam_context, cpam_validation
Découpe le monolithe cpam_response.py (1207L) en 3 modules spécialisés :
- cpam_rag.py : recherche RAG ciblée (5 requêtes, dédup)
- cpam_context.py : construction prompt, définitions CIM-10, bio summary
- cpam_validation.py : grounding, références, codes fermée, adversariale

Le cpam_response.py reste orchestrateur (~230L) avec re-exports
backward-compat. Mocks des tests mis à jour pour cibler les bons modules.
Ajout RULE-CPAM-CORRECTION-LOOP dans base.yaml. 748 tests passent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:06:26 +01:00
dom
e760b12961 refactor: split cim10_extractor → bio_normals, bio_extraction, diagnostic_extraction, validation_pipeline
Découpe le monolithe cim10_extractor.py (1356L) en 4 modules spécialisés :
- bio_normals.py : constante BIO_NORMALS + _is_abnormal() (feuille)
- bio_extraction.py : extraction biologie structurée
- diagnostic_extraction.py : extraction DP/DAS/actes CCAM
- validation_pipeline.py : validation CIM-10/CCAM + règles métier

Le cim10_extractor.py reste orchestrateur (~450L) avec re-exports
backward-compat. Imports mis à jour dans clinical_context, rag_search,
fusion. 748 tests passent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:06:18 +01:00
dom
5823eb6b53 feat: infrastructure — pyproject.toml, requirements-dev, conftest, pytest-cov
Ajoute pyproject.toml (pytest strict markers, coverage fail_under=55),
requirements-dev.txt (pytest-cov, pytest-xdist), et tests/conftest.py
avec fixtures partagées (dossier_minimal, dossier_complet, controle_cpam).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:06:11 +01:00
dom
1b680e9592 feat: qualité DP Phase 2 — filtre OCR étendu, abréviations médicales, promotion DAS→DP
- Filtre OCR : regex étendu (opérateurs +-*/), artefacts temporels (années),
  seuil digits abaissé 0.50→0.48
- Dictionnaire 41 abréviations médicales françaises (BMR, BPCO, SDRA, OAP,
  IDM, SCA, AVC, ACFA, SIDA, TDAH, etc.) avec expand_medical_abbreviations()
  appelé sur diagnostics Trackare et DAS LLM
- Promotion DAS→DP : si aucun DP extrait, le meilleur DAS (scoring
  pertinence/confiance/spécificité) est promu avec traçabilité RULE-DAS-TO-DP
- 95 nouveaux tests (OCR, abréviations, promotion, scoring, non-régression)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 08:37:10 +01:00
dom
6c036ed7f1 fix: garde-fous qualité Phase 1 — codes invalides et raisonnements vides
- Ajout R33, R33.0, R33.8, R33.9, F17.1, F17.2 au dictionnaire supplémentaire
- Rejet des codes CIM-10 avec raisonnement ET justification vides (corrélation hallucinations)
- Validation du code contre le dictionnaire CIM-10 avant copie suggestion → final

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 07:53:43 +01:00
dom
5cf7d74fa3 feat: parallélisation pipeline --workers N (ThreadPoolExecutor)
- Fix thread-safety FAISS index (Lock + double-check sur _loaded)
- Fix thread-safety reranker (Lock + double-check sur _reranker_model)
- main.py : flag --workers, extraction _process_group(), ThreadPoolExecutor
- benchmark_quality.py : flag --workers, subprocess en parallèle
- Validé sur 10 dossiers gold standard --workers 3 : 0 crash, codes identiques

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:30:51 +01:00
dom
0b94299975 feat: fix extraction DP Trackare + 5 règles ATIH (veto engine)
- Fix DP : les diagnostics Trackare marqués "principal" ne sont plus
  filtrés par is_valid_diagnostic_text() (3 dossiers récupérés)
- VETO-20 : Z code interdit en DP (sauf whitelist Z09/Z51/Z54/Z75...)
- VETO-21 : Code R (symptôme) en DP → alerte CMD 23
- VETO-22 : Même catégorie 3 chars en DP+DAS (redondance)
- VETO-23 : Exclusions mutuelles (E10↔E11, I10↔I11-I13)
- VETO-24 : Lésion traumatique (S/T) sans cause externe (V/W/X/Y)
- 24 tests unitaires, 699 tests passent sans régression

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:39:07 +01:00
dom
909e051cc9 feat: architecture multi-modèles LLM + quality engine + benchmark
- Multi-modèles : 4 rôles LLM (coding=gemma3:27b-cloud, cpam=gemma3:27b-cloud,
  validation=deepseek-v3.2:cloud, qc=gemma3:12b) avec get_model(role)
- Prompts externalisés : 7 templates dans src/prompts/templates.py
- Cache Ollama : modèle stocké par entrée (migration auto ancien format)
- call_ollama() : paramètre role= (priorité: model > role > global)
- Quality engine : veto_engine + decision_engine + rules_router (YAML)
- Benchmark qualité : scripts/benchmark_quality.py (A/B, métriques CIM-10)
- Fix biologie : valeurs qualitatives (troponine négative) non filtrées
- Fix CPAM : gemma3:27b-cloud au lieu de deepseek (JSON tronqué par thinking)
- CPAM max_tokens 4000→6000, viewer admin multi-modèles
- Benchmark 10 dossiers : 100% DAS valides, 10/10 CPAM, 243s/dossier

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:21:09 +01:00
dom
5c8c2817ec fix: modal source viewer — data-attributes + nettoyage ellipses
- Remplace onclick inline par data-excerpt/data-page + event delegation
  (élimine les problèmes d'échappement JS dans attributs HTML)
- Nettoie les "..." préfixe/suffixe des extraits avant recherche
- Fallback morceau central si l'extrait complet ne matche pas

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:40:20 +01:00
dom
40934fdc39 feat: traçabilité source systématique + viewer interactif
Ajoute source_page/source_excerpt à tous les types (biologie, imagerie,
traitements, actes CCAM, antécédents, complications). Convertit antecedents
et complications en types structurés (Antecedent/Complication) avec
validators backward-compat pour les vieux JSON. Étend _apply_source_tracking
à tous les éléments du dossier. Ajoute un endpoint /api/source-text/ et un
modal interactif dans le viewer avec surlignage du texte source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 20:59:50 +01:00
dom
fe22c0f0f5 fix: filtre bruit Trackare — antécédents parasites + répétitions DAS
- das_filter: regex anti-répétition gère les espaces entre mots concaténés
  ("VentilationVentilation Ventilation..." désormais rejeté)
- cim10_extractor: regex antécédents s'arrête à "Signes Vitaux" (ne capture
  plus le tableau de surveillance)
- Nouveau _is_valid_antecedent() filtre noms de service, mots de surveillance
  isolés, infos admin (RPPS), répétitions, Mode de vie
- 28 nouveaux tests (TestIsValidAntecedent + das_filter repetition)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:20:50 +01:00
dom
f7d87f2602 feat: pipeline CPAM multi-pass + garde-fous qualité (solutions 1+2+3+6)
- Solution 1 : injection déterministe des définitions CIM-10 dans le prompt
- Solution 2 : grounding tagué [BIO-N], [IMG-N], [TRT-N], [ACTE-N] avec validation
- Solution 3 : pipeline 2 passes (extraction structurée → argumentation)
- Solution 6 : validation adversariale LLM post-génération
- Normes bio injectées dans les tags (NORMAL/ÉLEVÉ/BAS avec norme de référence)
- Cross-check DAS/biologie détecte les incohérences (leucocytose vs leucocytes bas)
- Contexte patient : flags pédiatrie, patient âgé, admission urgence
- Dossiers pauvres : avertissement explicite au lieu de spéculation
- Validation adversariale enrichie avec normes bio de référence
- 75 tests CPAM (612 total), 0 régression

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:16:34 +01:00
dom
09a251185e feat: modèle par défaut gemma3:27b-cloud pour meilleure qualité
Le 27b-cloud via Ollama Cloud est plus rapide (2m25 vs 4m) et
produit des résultats nettement supérieurs au 12b local :
- CPAM : plus de confusion Z45.80/Z43.6, preuves non hallucinées
- Contre-argumentation : 5334 chars vs 4394, citations du dossier
- Fallback local possible via OLLAMA_MODEL=gemma3:12b

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:37:17 +01:00
dom
e74064a2e1 fix: thread-safety embedding singleton + QC alertes string
- Ajout threading.Lock sur _get_embed_model() pour empêcher les
  chargements concurrents depuis ThreadPool(2) — élimine les erreurs
  "meta tensor" et les doubles CUDA OOM
- Sentinelle _embed_failed évite les retries infinis après échec
- NotImplementedError ajouté aux exceptions capturées (meta tensor)
- Fallback CPU protégé par try/except avec _embed_failed
- QC: alertes_globales string wrappée en liste (évite itération par
  caractère quand le LLM retourne une string au lieu d'une liste)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:42:14 +01:00
dom
44118f69aa fix: SentenceTransformer meta tensor avec accelerate + torch 2.10
low_cpu_mem_usage=False évite les meta tensors lors du chargement
de l'embedding (sentence-transformers 5.x + accelerate 1.12).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:16:01 +01:00
dom
8c1b5a243e fix: prompt CPAM exige codes CIM-10 explicites, RAG résilient aux erreurs embedding
- Prompt : consigne de toujours citer les codes CIM-10 avec libellé (jamais
  "codage initial" sans préciser le code), appliquée dans conclusion et partout
- RAG résilient : _search_rag_for_control attrape toute exception (meta tensor,
  CUDA OOM, index absent) et génère la contre-argumentation sans sources plutôt
  que de perdre silencieusement tout le contrôle CPAM
- Embedding fallback : condition élargie pour couvrir "meta tensor" en plus de
  "memory" dans le message d'erreur RuntimeError

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 23:38:46 +01:00
dom
bc0ccbef7c feat: enrichissement contre-argumentation CPAM — libellés CIM-10, RAG ciblé, reprocess complet
- Résolution des libellés CIM-10 pour les codes contestés (dp_ucr, da_ucr, dr_ucr)
- Fallback DP depuis dp_ucr quand le pipeline n'extrait pas de diagnostic principal
- Troncature arg_ucr augmentée de 200 à 500 chars pour conserver les citations de règles
- Requête RAG 4 : définitions CIM-10 (inclusion/exclusion) des codes contestés
- Requête RAG 5 : extraction et recherche des règles nommées (RègleT7, Annexe, etc.)
- Cap résultats RAG de 10 à 12 pour absorber les nouvelles requêtes
- Reprocess viewer : pipeline complet (fusion + GHM + CPAM) pour dossiers multi-PDF
- Affichage structuré response_data dans le viewer (analyse, preuves, références)
- 7 nouveaux tests CPAM, 6 nouveaux tests viewer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 23:24:10 +01:00
dom
94fa4e5f3b feat: résumé clinique enrichi + preuves cliniques + validation QC batch
Améliore la qualité du codage CIM-10 sur 3 axes :
- Contexte clinique enrichi (interprétations bio, traitements indicatifs, marqueurs sévérité)
- Preuves cliniques structurées par diagnostic (evidence linking dans le prompt LLM)
- Validation batch post-codage (1 appel LLM/dossier, ajustement confiance, alertes QC)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:47:27 +01:00
dom
dbc5bdbaf4 feat: mode Validation DIM dans le viewer Flask
Permet aux médecins DIM de valider/corriger les codes CIM-10 extraits
par le pipeline pour construire un gold standard (50 dossiers).

- ValidationManager : gestion annotations JSON dans data/gold_standard/
- Script sélection 50 dossiers (25 CPAM + 25 stratifiés CMD/confiance)
- Routes /validation, /api/cim10/search, /api/validation/save, /validation/metrics
- Formulaire avec autocomplete CIM-10, boutons Correct/Modifier/Supprimer
- Dashboard métriques : precision, recall, F1, hallucination par confiance/source

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:43:02 +01:00
dom
aad925ebea fix: suppression mode hybride 27b, prompt CPAM nuancé pour gemma3:12b
Benchmark 4 modèles (gemma3:12b/27b, qwen3:14b, mistral-small3.2:24b)
sur 3 dossiers CPAM : le 12b domine en vitesse (30s vs 231s) et densité
argumentaire. Seul avantage du 27b : nuance (points d'accord 3/3 vs 1/3).

Solution : prompt nuancé qui force l'analyse équilibrée (étape 1 honnête,
points d'accord obligatoires, conclusion reconnaissant les points CPAM).
Résultat 12b-v2 : 3/3 points d'accord, 26s, refs verbatim +17%.

Supprime OLLAMA_MODEL_CPAM et OLLAMA_TIMEOUT_CPAM (gemma3:12b pour tout).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:45:53 +01:00
dom
01d47f3c4b feat: mode hybride Ollama — gemma3:27b pour CPAM, 12b pour codage
Le pipeline utilise désormais gemma3:12b (rapide) pour le codage CIM-10
et gemma3:27b (meilleur raisonnement) pour la contre-argumentation CPAM.
Configurable via OLLAMA_MODEL_CPAM et OLLAMA_TIMEOUT_CPAM.

Inclut aussi : traçabilité source/page DAS, niveaux CMA ATIH, sévérité,
page tracker PDF, améliorations fusion et filtres DAS.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:53:53 +01:00
dom
4ef42dd3d3 fix: filtre DAS décimaux, dédup parents CIM-10, tiebreak enrichissement
- Rule 3 das_filter étendue pour rejeter "K 3.6", "B 12,5" (valeurs labo)
- Suppression codes parents dans la fusion (K85 retiré si K85.9 présent)
- Préférence du diagnostic enrichi RAG à confiance égale lors de la dédup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 15:05:26 +01:00
dom
4c6c0d25bd feat: fallback Anthropic Haiku quand Ollama est indisponible
Quand Ollama refuse la connexion ou timeout, call_ollama() bascule
automatiquement sur l'API Anthropic (Haiku par défaut). Configurable
via ANTHROPIC_API_KEY et ANTHROPIC_FALLBACK_MODEL dans .env.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 09:42:32 +01:00
dom
4333b45cda fix: estimation GHM sur dossiers fusionnés multi-PDF
estimate_ghm() n'était appelée que dans process_pdf() pour chaque
document individuel, jamais après merge_dossiers(). Les 179/250
dossiers fusionnés n'avaient donc pas d'estimation GHM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 09:09:25 +01:00
dom
8c75941e40 feat: 3 quick wins — source DAS, fallback code parent, filtre anatomique
1. Champ source sur Diagnostic : trackare/edsnlp/regex/llm_das
   - Renseigné dans les 8 constructeurs de cim10_extractor.py
   - Permet l'audit de provenance des DAS dans le JSON de sortie

2. Fallback code parent pour les codes LLM halluccinés :
   - fallback_parent_code() dans cim10_dict.py (D71.9→D71, R69.8→R69)
   - Intégré dans _apply_llm_result_diagnostic() de rag_search.py
   - Récupère les codes rejetés dont le parent 3-char est valide

3. Règle 12 filtre DAS : en-têtes anatomiques + catégories vagues
   - Rejette "Musculaire", "Digestif", "Hépatique" (mots isolés)
   - Rejette "Musculaire - masse musculaire" (catégorie + description)
   - 13 nouveaux tests unitaires au total

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 11:34:32 +01:00
dom
59365e3af9 feat: re-ranking cross-encoder CPU pour la recherche RAG CPAM
- Nouveau singleton _get_reranker() : CrossEncoder ms-marco-MiniLM-L-6-v2
  forcé sur CPU pour ne pas interférer avec Ollama sur GPU
- Fonction _rerank() : re-classe les résultats FAISS via cross-encoder,
  conserve le score FAISS original dans score_faiss
- Intégré dans search_similar_cpam() après déduplication, avant priorisation
- Config RERANKER_MODEL externalisée via T2A_RERANKER_MODEL (.env)
- Fix fallback CUDA OOM : rattrapage de torch.AcceleratorError en plus
  de torch.OutOfMemoryError

Latence : ~7-12s (incluant chargement one-time du modèle ~80Mo).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 11:16:58 +01:00
dom
50a77c9f61 feat: RAG CPAM dédié avec requêtes multi-ciblées + prompt 3 axes
- Nouvelle search_similar_cpam() : priorité Guide Méthodo, seuil 0.40,
  déduplication par code CIM-10, fetch élargi top_k*3
- _search_rag_for_control() refactoré : 2-3 requêtes ciblées (codes
  contestés, argument CPAM, contexte clinique) au lieu d'1 fourre-tout
- Fusion dédupliquée par (document, code, page), top 10 résultats
- Prompt CPAM enrichi : 3 axes (médical, asymétrie, réglementaire),
  section asymétrie d'information, format réponse structuré
- 9 nouveaux tests unitaires pour la logique RAG multi-requêtes

Élimine les sources CIM-10 hors-sujet (F45, F98.1, F50.5 sur pancréatite)
au profit de résultats Guide Méthodo et référentiels pertinents.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 11:08:15 +01:00
dom
aa397d5360 feat: configuration externalisée via .env + audit requirements
- Externalise 13 variables de config via python-dotenv (chemins PDF,
  modèles Ollama/embedding/NER, FINESS, seuils) avec défauts identiques
- Centralise EMBEDDING_MODEL dans config.py (était hardcodé en 3 endroits)
- Ajoute .env.example documenté et .env au .gitignore
- Ajoute openpyxl et pandas manquants au requirements.txt
- Ajoute data/referentiels au mkdir de run.sh

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:46:33 +01:00
dom
c838d75174 feat: affichage des référentiels intégrés dans la page admin RAG
Ajout d'une section listant les 6 sources built-in (CIM-10, CCAM, Guide Métho,
dictionnaires) avec compteurs de chunks et statut. Séparation claire entre
référentiels intégrés et référentiels utilisateur uploadés.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:00:44 +01:00
dom
ee661dae1d feat: dashboard métriques + vue CPAM agrégée dans le viewer
Ajout d'un dashboard global (distribution confiance DP, top 15 codes CIM-10,
types GHM, sévérité) et d'une page listant tous les contrôles CPAM agrégés.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:11:21 +01:00
dom
906a2797e5 feat: champ de recherche dossiers dans la sidebar du viewer
Filtrage côté client en temps réel par nom de dossier ou document.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:39:56 +01:00
dom
837bdaca76 fix: filtre DAS=DP + correction D55.9→D64.9 + enrichissement supplements CIM-10
- Filtre DAS identique au DP (violation règle PMSI) dans extracteur et fusion
- Correction automatique D55.9 → D64.9 pour "Anémie" non qualifiée (70 cas)
- 17 codes ajoutés aux supplements (K59.0, Z93.1, H92.0, A87.0, D64.9, etc.)
- 436 tests OK (+14 nouveaux)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 14:03:10 +01:00
dom
0d3cb83f12 fix: fallback CPU embedding + protection CPAM contre crash OOM
- SentenceTransformer : fallback CPU si CUDA OOM (Ollama peut occuper la VRAM)
- Bloc CPAM dans main.py : try/except pour éviter crash fatal du pipeline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 06:11:38 +01:00
dom
e90450903e feat: enrichissement CIM-10 sous-codes + normes biologiques dans prompt DAS
Piste 1 : ajout de cim10_supplements.json (40 sous-codes E10/E11/E13/F10)
fusionné au chargement par load_dict() — E11.9 et autres ne sont plus rejetés.

Piste 2 : export BIO_NORMALS depuis cim10_extractor, inclusion des plages
de référence [N: min-max] dans le contexte LLM et règle explicite dans le
prompt DAS pour éviter les hallucinations sur valeurs biologiques normales.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 23:46:42 +01:00
dom
f44216b95b feat: pass LLM hybride pour DAS + interface admin référentiels RAG
Chantier 1 — Extraction DAS par LLM :
- Nouveau prompt expert DIM dans rag_search.py (extract_das_llm)
- Phase 4 dans cim10_extractor.py : détection DAS supplémentaires avant enrichissement RAG
- Cache persistant (clé hash du texte), validation CIM-10, déduplication
- Activé uniquement avec use_rag=True (--no-rag le désactive)

Chantier 2 — Admin référentiels :
- Config : REFERENTIELS_DIR, UPLOAD_MAX_SIZE_MB, ALLOWED_EXTENSIONS
- Chunking générique (PDF/CSV/Excel/TXT) + ajout incrémental FAISS dans rag_index.py
- ReferentielManager CRUD dans viewer/referentiels.py
- 5 routes Flask (listing, upload, indexation, suppression, rebuild)
- Template admin avec tableau interactif + lien sidebar

Fix : if cache → if cache is not None (OllamaCache vide évaluait à False)

410 tests passent (27 nouveaux, 0 régression).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 23:12:39 +01:00
dom
bf92a0ce3e feat: auto-détection du fichier Excel CPAM dans input/Control_cpam/
Plus besoin du flag --control-cpam : si un .xlsx est présent dans
input/Control_cpam/, il est chargé automatiquement. Le flag reste
disponible comme override.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 14:48:08 +01:00
dom
0ea49e675f fix: .gitignore — exclure PDFs, XLS, .claude/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 13:46:17 +01:00
dom
a58398f5d4 feat: cache Ollama + parallélisation ThreadPool + filtrage DAS renforcé + modules GHM/CPAM/export RUM
- Cache persistant JSON thread-safe pour les résultats Ollama (invalidation par modèle)
- Parallélisation des appels Ollama (ThreadPoolExecutor, 2 workers)
- 6 nouvelles règles de filtrage DAS parasites (doublons, ponctuation, OCR, labo, fragments)
- Client Ollama centralisé (mode JSON natif + retry)
- Module GHM (estimation CMD/sévérité)
- Module contrôle CPAM (parser + contre-argumentation RAG)
- Export RUM (format RSS)
- Viewer enrichi (détail dossier)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 13:44:34 +01:00
dom
a00e5f1147 feat: découpage PDFs multi-dossiers (Trackare multi-épisodes, CRH concaténés)
Ajoute une étape de splitting entre extraction texte et parsing. Chaque chunk
est traité indépendamment par le pipeline existant, avec suffixe _partN en sortie.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 09:08:37 +01:00