Commit Graph

90 Commits

Author SHA1 Message Date
dom
828356eff1 fix: corriger le chemin gunicorn dans t2a-viewer.service
Le chemin ExecStart pointait vers /home/dom/ai/t2a/.venv/ (ancien projet)
au lieu de /home/dom/ai/t2a_v2/.venv/ (projet actuel).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:38:37 +01:00
dom
8f43759ba4 chore: compléter .gitignore et dé-tracker output/ (1603 fichiers)
Ajouts au .gitignore :
- output/ : données patient anonymisées et résultats pipeline (ne doivent pas être versionnées)
- unsloth_compiled_cache/ : cache de compilation Unsloth
- *.rttm : fichiers de diarisation audio
- /benchmark_*.py, /bench_pipeline.py : scripts de benchmark ponctuels (racine)
- training/ : artefacts d'entraînement

Suppression du tracking de output/ via git rm --cached (1603 fichiers, ~1.2M lignes).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:38:23 +01:00
dom
ae02c81572 chore: suppression fichiers parasites non liés au projet
- unsloth_compiled_cache/ : cache de compilation Unsloth (fine-tuning LLM, non lié)
- sans titre_diarization.rttm : fichier RTTM vide (transcription audio)
- sans titre_diarized.txt : transcription audio 241 Ko (medical_ai_scribe)
- sans titre_summary_v2.md : résumé audio 11 Ko (medical_ai_scribe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:37:50 +01:00
dom
214a5d1914 fix: qualité codage — anti-hallucination LLM + négation regex + veto calibration
- Prompt DAS_EXTRACTION : ajout consignes anti-hallucination (zero invention,
  pas d'inférence de comorbidités, exiger citation exacte du texte)
- Prompt CODING_CIM10 : ajout consignes conditionnel et négation
- diagnostic_extraction.py : détection de négation avant les patterns regex DAS
  (bloque "pas d'embolie", "absence de sepsis", "sans signe d'IRC", etc.)
- veto_engine.py : VETO-03 conditionnel cherche maintenant PRÈS du concept
  (40 chars), "si" isolé ne déclenche plus de faux positif, ajout cues
  (possible, risque de, aspect de, à confirmer, à rechercher)
- veto_engine.py : négation enrichie (ne retrouve pas, sans signe/argument,
  écarté, infirmé, pas mis en évidence)

Batch analysis: VETO-02 63% from LLM hallucinations, VETO-03 63% false positives

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:59:02 +01:00
dom
a371626f40 feat: dictionnaire de codage + détection anomalies statistiques
- Script build_coding_dict.py génère le dictionnaire depuis le batch (240 dossiers)
- coding_dictionary.json : co-occurrences DP→DAS, fréquences, associations bio
- anomaly_stats.py : 8 checks (DP/DAS rare, DAS manquant, bio-DAS, âge atypique)
- Intégré dans le pipeline cim10_extractor post-DIM-senior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:48:36 +01:00
dom
13fe9fa666 chore: mise à jour output pipeline (anonymized + structured)
Résultats de re-traitement pipeline v2 sur 261 dossiers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:14:42 +01:00
dom
c73515ac89 chore: mise à jour index FAISS (+15 référentiels ATIH) et cache ollama
- Index FAISS ref/proc enrichis avec 15 nouveaux documents ATIH/DGOS
- Métadonnées FAISS refactorisées (metadata_ref, metadata_proc séparés)
- Référentiels utilisateur ajoutés (5 docs)
- Nettoyage cache ollama (suppression backup gemma3)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:14:32 +01:00
dom
4b6e3cf6d5 feat: optimisations pipeline médical (bio_normals, GHM, DP selector, CIM-10)
- bio_normals: table de normes biologiques étendue (+200 analytes)
- bio_extraction: amélioration parsing valeurs biologiques
- cim10_extractor: règles supplémentaires extraction codes
- dp_selector: affinement sélection diagnostic principal
- ghm: estimation sévérité GHM enrichie
- validation_pipeline: correctifs mineurs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:14:13 +01:00
dom
63f61f196b feat: 8 optimisations vitesse + qualité pipeline CIM-10
1. Parallélisation intra-dossier (RAG + DP selector en parallèle)
2. Cache embeddings FAISS (_embed_cached avec LRU)
3. Lazy loading edsnlp (déjà singleton, vérifié)
4. Prompt DP amélioré avec règles PMSI/ATIH
5. Validation croisée Bio↔DAS (cohérence biologie/diagnostics)
6. Resélection DP après vetos/exclusions (reselect_dp_after_vetos)
7. Pré-filtrage R-codes (déjà implémenté dans exclusion_rules)
8. Cache embeddings texte (intégré dans rag_search)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 22:18:07 +01:00
dom
e6bd7406a4 chore: nettoyage YAML base.yaml + corrections templates viewer
- base.yaml: suppression commentaires verbose, normalisation quotes YAML
- Templates: corrections mineures cpam.html, detail.html, dim.html, index.html
- admin_rules.html: ajustements interface admin règles
- test_referentiels.py: mise à jour imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 22:07:00 +01:00
dom
79c447688c fix: ajouter liens navigation vers interface admin regles
- Lien sidebar base.html : "Regles metier" sous "Referentiels"
- Lien croise admin_referentiels.html → regles
- Boutons dashboard : "Gerer les referentiels" + "Regles metier"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:42:42 +01:00
dom
1e837c2758 feat: interface admin regles, refactoring viewer, README, pyproject.toml
- Nouveau module rules_manager.py : CRUD YAML pour les regles metier
- Nouveau blueprint bp_rules.py + template admin_rules.html :
  interface web pour activer/desactiver/ajouter/supprimer des regles
- Extraction helpers.py depuis app.py (filtres Jinja2, statistiques,
  scan dossiers, status systeme) — app.py passe de 1585 a 482 lignes
- Suppression backward-compat re-exports dans cim10_extractor et
  cpam_response (imports corriges dans les tests)
- README.md : architecture, modules, installation, utilisation
- pyproject.toml : dependencies completes, config ruff, pytest, coverage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:11:27 +01:00
dom
2478928798 chore: suppression scripts obsolètes, anciens benchmarks et fichiers de dev
- Suppression scripts racine : analyze_pdfs.py, rebuild_index.py,
  compare_cpam_models.py, test_cpam_quality.py, test_quality_tier_live.py
- Suppression docs obsolètes : rapport_analyse_pdfs.md,
  ANALYSE_COHERENCE_ET_AMELIORATIONS.md, patch_0+1.md
- Suppression outils CPAM legacy : extract_t2a_llm.py, parse_decision_ucr.py
- Suppression backups CPAM : *.xlsx_old
- Suppression hors-git : 19 archives .zip, cache gemma3.bak

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 16:49:26 +01:00
dom
4e2b4bd946 refactor: réorganisation référentiels, nouveaux modules extraction, nettoyage code obsolète
- Réorganisation data/referentiels/ : pdfs/, dicts/, user/ (structure unifiée)
- Fix badges "Source absente" sur page admin référentiels
- Ré-indexation COCOA 2025 (555 → 1451 chunks, couverture 94%)
- Fix VRAM OOM : embeddings forcés CPU via T2A_EMBED_CPU
- Nouveaux modules : document_router, docx_extractor, image_extractor, ocr_engine
- Module complétude (quality/completude.py + config YAML)
- Template DIM (synthèse dimensionnelle)
- Gunicorn config + systemd service t2a-viewer
- Suppression t2a_install_rag_cleanup/ (copie obsolète)
- Suppression scripts/ et scripts_t2a_v2/ (anciens benchmarks)
- Suppression 81 fichiers _doc.txt de test
- Cache Ollama : TTL configurable, corrections loader YAML
- Dashboard : améliorations templates (base, index, detail, cpam, validation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 16:48:10 +01:00
dom
2578afb6ff chore: add .gitignore 2026-03-05 00:37:41 +01:00
dom
542797a124 fix: injecter les tags réels du dossier dans le prompt CPAM pour éliminer les tags génériques [TYPE-N]
Le LLM générait des tags génériques [BIO-N], [TRT-N] au lieu des vrais tags du dossier,
causant des warnings "preuve non traçable". Corrigé en 3 points :
- cpam_context: liste exhaustive des tags disponibles injectée dans le prompt
- templates: remplacement des patterns génériques par {tags_disponibles_str}
- cpam_validation: guardian step 4b résout les tags génériques résiduels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:14:40 +01:00
dom
798cee463f feat: guardian déterministe + config modèles locaux + prompt TIM R1-R6
Guardian déterministe post-LLM (0 appel modèle, <1ms) :
- Corrige les valeurs bio hallucinées via confrontation dossier
- Step 1b : vérifie l'association test↔diagnostic via _BIO_THRESHOLDS
- Chemin bidirectionnel : CONFIRMÉ↔NON CONFIRMÉ selon bio réelle
- Force R3 : codes bio-infirmés → codes_non_defendables
- Step 2b : retire les codes bio-confirmés de codes_non_defendables
- Retire les moyens défendant des codes bio-contredits
- _safe_bio_replace() : regex protégeant les normes [X-Y]
- Nettoyage texte libre (conclusion, rappel, codes_nd, raisonnement)
- Score factuel déterministe avec pénalités

Config modèles pour déploiement local (DGX Spark) :
- CPAM : mistral-small3.2:24b (TIM complet, bonne précision bio)
- Validation : qwen3:32b (rapide, LOGIC-3 actif)
- Timeout : 120s → 600s pour modèles locaux

Ollama : migration /api/generate → /api/chat (messages format)

Prompt CPAM_ARGUMENTATION restructuré :
- R1-R6 non-négociables en tête (avant données)
- Champ raisonnement_interne (chain-of-thought structuré)
- 5 passes TIM avec références explicites aux règles

Test cpam_quality : métriques guardian dans le résumé

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:00:40 +01:00
dom
ce7a9650af feat: méthode TIM experte CPAM + moteur de règles étendu
CPAM — Méthode TIM (mémoire en défense) :
- Réécriture CPAM_ARGUMENTATION avec raisonnement 5 passes TIM
  (contexte admin → motif réel → confrontation bio → hiérarchie → validation défensive)
- _BIO_THRESHOLDS (19 entrées) + _build_bio_confrontation() pour
  confrontation biologie/diagnostic avec seuils chiffrés et verdicts
- _format_response() dual format : nouveau TIM (moyens numérotés, tableau
  bio, codes non défendables, conclusion dispositive) + rétrocompat legacy
- CPAM_ADVERSARIAL mis à jour pour vérifier honnêteté intellectuelle
- Tests adaptés + 12 nouveaux tests (bio confrontation, format TIM)

Moteur de règles :
- Nouvelles règles YAML : demographic, diagnostic_conflicts,
  procedure_diagnosis, temporal, parcours
- Bio extraction FAISS (synonymes vectoriels)
- Veto engine enrichi (citations, Trackare skip, règles démographiques)
- Decision engine : _apply_bio_rules_gen() + matchers analytiques

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:57:07 +01:00
dom
795110d2e6 fix: anonymisation — sur-anonymisation + fuites PHI + patterns sécurisés
- DR_NAME_PATTERN limité à 2 mots (évite capture "CHARLANNE Traitements")
- CIVILITE_NAME_PATTERN et DESTINATAIRE_PATTERN : chaque mot doit commencer
  par majuscule (évite capture de phrases entières comme noms)
- DATE_NAISSANCE_PATTERN : colon optionnel après "le" ("Né(e) le : DD/MM/YYYY")
- N_CSULT_PATTERN ajouté pour numéros de consultation anesthésie
- CONTACT_RELATION_PATTERN : +15 relations familiales (Neveu, Nièce, Oncle...)
- MEDICAL_TERMS_WHITELIST : +30 termes hospitaliers (scanner, traitement,
  viscerale, radiologie, consultation, etc.)
- FRENCH_STOP_WORDS : +20 mots courts (fort, aide, suite, avant, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 12:38:13 +01:00
dom
99069f150a feat: anonymisation qualité++ — 15 patterns, subparts tirets, fix entity registry
Bloc A: fix sous-parties dans _mappings, filtre NER anti-tag,
intégration patterns manquants (DESTINATAIRE, PRESCRIPTION_AUTHOR),
whitelist médicaments élargie (+60), villes retirées de whitelist.

Bloc B: CRH dedup chars 200-1000, CP_VILLE vrais codes postaux FR,
DR_NAME capital par mot, BACTERIO header tolère ligne vide.

Bloc C: DR_NAME negative lookahead multi-docteurs même ligne,
entity_registry split tirets (RITZ-QUILLACQ), fix early return
subparts dans _find_matching_entity, PRESCRIPTION_AUTHOR élargi
(Révisé/Traité, variable.), NOTE_AUTHOR élargi (Diététicienne,
Kiné, Ergo), + 8 nouveaux patterns (CONTACT_RELATION, MOD_PAR,
AIDE_NAME, SIGNATURE_LINE, VALIDE_PAR, INTERNE_SIGNATURE,
FOIS_NAME, MALADIE_NAME), adresses inline +ALLEE/IMP,
text_cleaner préserve abréviations médicales.

Validé sur 6 cas (21, 11, 104, 160, 50, 200). 70 tests OK.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 11:11:47 +01:00
dom
f4a23a5f43 feat: qualité anonymisation — sur-anonymisation, fuites PHI, nettoyage bruit
P0-A: stop words français + seuil subparts 5 chars + sweep conditionnel
P0-B: 6 nouveaux patterns PHI (DDN, Par, N Ipp, Adresse, DEMANDE, venue)
P2-C: cohérence pseudonymes (_find_matching_entity) + fix crochets
P1-B: text_cleaner.py — sidebar OCR, footers, dédup vitales, collapse blanks
P1-A: dédup CRH par SequenceMatcher (seuil 85%)
Tests: 34 nouveaux tests (996 pass, 0 fail)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:00:07 +01:00
dom
63354e75bc tests: dp_finalizer — 20 tests R1-R5 + pass-through + quality_flags + sérialisation
- TestR1CrhConfirmedOverridesTrackare (2 tests : override + cohérent)
- TestR2TrackareCorroborated (2 tests : exact + family3)
- TestR3TrackareSymptom (3 tests : override, review prudent, evidence faible)
- TestR4Ambiguous (1 test)
- TestR5Interdictions (4 tests : Z-code, Z-whitelist, R-code, allow_symptom)
- TestPassThrough (3 tests : CRH-only, Trackare-only, aucun DP)
- TestFinalizeDp (5 tests : flags merge, alertes append, sources set, sérialisation)

1063 tests passent, 0 régression.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:50:32 +01:00
dom
c7317af447 feat: dp_finalizer — arbitrage Trackare vs CRH-only avec traçabilité audit
Nouveau module src/medical/dp_finalizer.py :
- 5 règles d'arbitrage (R1-R5) : CRH CONFIRMED override, Trackare corroboré,
  symptôme R* override/review, ambigu REVIEW, Z-code/R-code interdits auto-confirm
- Traçabilité : dp_trackare, dp_crh_only, dp_final sur DossierMedical
- quality_flags dict (merge sans écraser) + alertes_codage (append)

Modèles config.py :
- DPCandidate, DPSelection (NUKE-3)
- get_dp_ranker_llm_enabled(), check_adversarial_model_config()
- Champs DossierMedical : dp_trackare, dp_crh_only, dp_final, quality_flags

Intégration :
- main.py : appel finalize_dp() après vetos/GHM (individuel + fusionné)
- benchmark : finalizer dans _rebuild_and_select(), dp_final dans output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:50:07 +01:00
dom
cad0dd22b1 tests: alias DLBCL + garde-fou Trackare + e2e PDFs réels + gold CRH + benchmark enrichi
- 11 tests unitaires : TestAliasAndConclusionBonus (7) + TestTrackareSymptomGuard (4)
- Tests e2e sur PDFs réels (skip si absent) : méningite A87.0 + DLBCL C83.3 top1
- Gold CRH enrichi : 5 cas (2 réels ajoutés : 115_23066188, 132_23080179)
- Benchmark synthese : récupération conclusion depuis source_excerpt des DAS/traitements
- .gitignore : protection anti-PHI (real_crh_pdfs/, data/crh_samples/*.pdf)
- docs/PHI_POLICY.md : 7 règles de sécurité PHI
- Rapports debug : case 132 REVIEW (garde-fou actif), top errors, DIM pack

1043 tests passent, 0 régression.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:35:57 +01:00
dom
06a1be5425 feat: alias diagnostiques CIM-10 + scoring conclusion + garde-fou Trackare R-code
- DIAGNOSIS_ALIASES : mapping acronymes cliniques → CIM-10 (DLBCL→C83.3, SCA→I25.1, EP→I26.9, IDM→I21.9, etc.)
- Scoring 4b étendu : conclusion (+2) ajouté aux sections diagnostiques, matching par alias en plus du terme/code
- _collect_evidence : détection alias dans les sections pour preuves plus complètes
- Garde-fou Trackare : si DP est un R-code (symptôme) et que les sections CRH mentionnent un diagnostic étiologique via alias → verdict REVIEW au lieu de CONFIRMED, alerte DIM
- Case 74 : verdict attendu REVIEW (conclusion mentionne les 2 diagnostics, delta insuffisant)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:35:15 +01:00
dom
07c267539c tests: CRH sections + DP diag bonus + case 74 regression + fusion propagation
- test_extraction: +21 tests (sections diag_sortie/diag_principal/synthese,
  variantes titres, terminaisons, faux positifs mid-sentence, biosynthèse)
- test_dp_selector: +55 tests (flags, candidates, scoring, hardening DIM,
  bonus +4/+2, evidence excerpt, cas 74 D50→I25.1 corrigé)
- test_fusion: +39 tests (propagation dp_selection evidence/reason/verdict,
  source 2e dossier, pas de crash si aucun DP)
- fixtures: case_74_min.json + 3 fixtures DP existantes

Aucun mock utilisé — données synthétiques uniquement.
Le test cas 74 passe : I25.1 gagne sur D50 grâce au bonus diag_sortie +4.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:28:54 +01:00
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