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

14 KiB

Rapport d'analyse — t2a_v2

Date : 2026-02-19 Codebase : /home/dom/ai/t2a_v2/ Branche : master (HEAD: 5c8c281)


1. Vue d'ensemble

Indicateur Valeur
Fichiers source (.py) 46
Lignes de code (src/) 12 596
Fichiers tests 24
Lignes de tests 7 095
Fonctions test 685
Ratio tests/code 0.56
Monolithes (>500L) 10 fichiers
Modules (sous-packages) 7

Comparaison t2a v1 -> v2

Aspect t2a (v1) t2a_v2 Delta
Lignes source 10 508 12 596 +2 088 (+20%)
Fichiers source 44 46 +2
Ratio tests/code 0.68 0.56 -0.12
Monolithe max 1 227L 1 352L +125L
Config YAML Aucun 6 fichiers +Flexibilite
Module quality/ - 1 226L NOUVEAU

2. Structure des modules

src/                               12 596L total
|
+-- config.py                       (746L) -- Config unifiee + modeles Pydantic + chargement YAML
+-- main.py                         (640L) -- Orchestrateur CLI principal
|
+-- anonymization/                  (904L) -- Anonymisation NER + regex
|   +-- anonymizer.py               (529L)
|   +-- entity_registry.py           (86L)
|   +-- ner_anonymizer.py            (95L)
|   +-- regex_patterns.py           (194L)
|
+-- control/                       (1161L) -- Controles CPAM
|   +-- cpam_parser.py              (115L) -- Parsing Excel CPAM
|   +-- cpam_response.py           (1046L) -- Contre-argumentation multi-pass
|
+-- export/                         (190L) -- Export RUM
|   +-- rum_export.py               (190L)
|
+-- extraction/                     (928L) -- Extraction documents PDF
|   +-- trackare_parser.py          (424L)
|   +-- crh_parser.py               (129L)
|   +-- document_splitter.py        (124L)
|   +-- document_classifier.py       (94L)
|   +-- page_tracker.py              (91L)
|   +-- pdf_extractor.py             (66L)
|
+-- medical/                       (5323L) -- Coeur metier CIM-10/CCAM/RAG
|   +-- cim10_extractor.py         (1352L) -- Extraction codes CIM-10 (MONOLITHE)
|   +-- rag_search.py               (849L) -- RAG FAISS + embedding + reranking
|   +-- rag_index.py                (803L) -- Index FAISS dual (ref + proc)
|   +-- clinical_context.py         (315L) -- Enrichissement contexte clinique
|   +-- fusion.py                   (294L) -- Merge multi-PDFs
|   +-- cim10_dict.py               (243L) -- Dictionnaire CIM-10
|   +-- severity.py                 (242L) -- Calcul severite + niveaux CMA
|   +-- ghm.py                      (231L) -- Estimation GHM
|   +-- ccam_dict.py                (191L) -- Dictionnaire CCAM
|   +-- exclusion_rules.py          (169L) -- Filtrage codes impossibles
|   +-- das_filter.py               (152L) -- 11 regles filtrage DAS bruit
|   +-- edsnlp_pipeline.py          (140L) -- Wrapper edsnlp (optionnel)
|   +-- ollama_client.py            (135L) -- Client Ollama + retry + JSON
|   +-- ccam_noncumul.py            (122L) -- Non-cumulativite CCAM
|   +-- ollama_cache.py              (85L) -- Cache JSON persistant
|
+-- quality/                       (1226L) -- NOUVEAU : qualite deterministe post-LLM
|   +-- decision_engine.py          (609L) -- Decisions KEEP/DOWNGRADE/REMOVE
|   +-- veto_engine.py              (411L) -- Vetos + contestabilite
|   +-- rules_router.py             (205L) -- Routage dynamique packs regles
|
+-- viewer/                        (1478L) -- Interface web Flask
    +-- app.py                      (872L) -- Routes + dashboard
    +-- validation.py               (272L) -- Validation manager (mode DIM)
    +-- referentiels.py             (160L) -- Upload/indexation referentiels
    +-- pdf_redactor.py             (154L) -- Redaction source PDF
    +-- __main__.py                  (20L)

3. Pipeline d'execution

3.1 CLI (python -m src.main)

main()
  +-- Pour chaque PDF :
  |   +-- extract_text_with_pages()          [extraction/pdf_extractor.py]
  |   +-- classify()                          [extraction/document_classifier.py]
  |   +-- split_documents()                   [extraction/document_splitter.py]
  |   +-- parse_trackare() ou parse_crh()     [extraction/]
  |   +-- Anonymizer.anonymize()              [anonymization/anonymizer.py]
  |   +-- _run_edsnlp()                       [medical/edsnlp_pipeline.py]  (optionnel)
  |   +-- extract_medical_info()              [medical/cim10_extractor.py]  << MONOLITHE
  |   |   +-- RAG FAISS + Ollama (si --rag)
  |   |   +-- Validation CIM-10 dict + supplements
  |   |   +-- Extraction actes CCAM
  |   |   +-- Scoring confiance biologie
  |   +-- build_rules_runtime_context()       [quality/rules_router.py]
  |   +-- apply_vetos()                       [quality/veto_engine.py]
  |   +-- apply_decisions()                   [quality/decision_engine.py]
  |   +-- _compute_metrics()                  [main.py]
  |   +-- estimate_ghm()                      [medical/ghm.py]
  |   +-- write_outputs()                     [main.py]
  |
  +-- FUSION (si multi-PDFs meme groupe)
  |   +-- merge_dossiers()                    [medical/fusion.py]
  |   +-- Re-application vetos/decisions
  |   +-- Re-estimation GHM
  |
  +-- CONTROLE CPAM (si Excel detecte)
      +-- match_dossier_ogc()                 [control/cpam_parser.py]
      +-- generate_cpam_response()            [control/cpam_response.py]  << MONOLITHE
          +-- Passe 1 : extraction structuree
          +-- 5 requetes RAG ciblees
          +-- Passe 2 : argumentation 3 axes
          +-- Passe 3 : validation adversariale

3.2 Viewer (python -m src.viewer --debug)

  • Dashboard : / -- liste dossiers + stats
  • Detail : /dossier/<nom> -- codes CIM-10, DAS, CPAM, GHM
  • Admin : /admin/models -- gestion modeles Ollama
  • Referentiels : /referentiels -- upload/indexation PDFs
  • Validation : mode DIM pour valider/corriger les codes

3.3 Flags CLI

--no-ner          # Desactiver anonymisation NER
--no-edsnlp       # Desactiver pipeline edsnlp
--no-rag          # Desactiver RAG (LLM seul)
--build-dict      # Reconstruire dictionnaire CIM-10
--build-ccam-dict # Reconstruire dictionnaire CCAM
--rebuild-index   # Reconstruire index FAISS
--export-rum      # Export RUM V016
--control-cpam    # Excel CPAM pour contre-argumentation

4. Nouveau module : quality/

Le module src/quality/ est l'ajout architectural majeur de la v2. Il implementa la couche de validation deterministe post-LLM.

decision_engine.py (609L)

Post-traitement des codes proposes par le LLM. Chaque code recoit une decision :

  • KEEP : code valide, maintenu
  • DOWNGRADE : confiance reduite (ex: symptome R00-R99 avec diagnostic precis)
  • REMOVE : code rejete (invalide, redondant, non pertinent)

veto_engine.py (411L)

Detection de vetos deterministes :

  • Negation dans le texte source
  • Conditionnel (diagnostics non confirmes)
  • Antecedents non pertinents pour le sejour
  • Conflits entre codes

rules_router.py (205L)

Routage dynamique des packs de regles selon les signaux du dossier :

  • Pack biologie active si valeurs bio presentes
  • Pack CPAM active si controle CPAM detecte
  • Configuration via config/rules/router.yaml

Configuration YAML associee

config/
+-- reference_ranges.yaml     -- Valeurs normales biologiques (adulte/enfant)
+-- bio_rules.yaml            -- Regles hyponatremie, hyperkaliemie, etc.
+-- lab_value_sanity.yaml     -- Garde-fous OCR (K, Na, Plaquettes, Hb, etc.)
+-- rules/
    +-- base.yaml             -- Catalogue complet des regles
    +-- enabled.yaml          -- Overlay d'activation
    +-- router.yaml           -- Routage packs par signaux

5. Croissance par module (v1 -> v2)

Module t2a (v1) t2a_v2 Delta %
anonymization 904 904 0 0%
control 1 062 1 161 +99 +9%
extraction 928 928 0 0%
medical 4 912 5 323 +411 +8%
viewer 1 486 1 478 -8 -0.5%
quality 0 1 226 +1 226 NOUVEAU
root (config+main) 669 1 386 +717 +107%
TOTAL 10 508 12 596 +2 088 +20%

La croissance vient principalement de :

  1. quality/ (+1 226L) : nouveau module deterministe
  2. config.py (+484L) : chargement YAML, rules context, modeles Pydantic supplementaires
  3. main.py (+233L) : fusion multi-PDFs, vetos/decisions, metriques

6. Monolithes identifies (>500L)

# Fichier Lignes Responsabilites
1 cim10_extractor.py 1 352 Extraction LLM + validation + filtering + RAG
2 cpam_response.py 1 046 RAG CPAM multi-requete + prompt engineering
3 app.py 872 Routes Flask + dashboard + admin
4 rag_search.py 849 Embedding + reranker + FAISS + generation
5 rag_index.py 803 Dual indexing + chunking CIM-10
6 config.py 746 Config + Pydantic + chargement YAML
7 main.py 640 Orchestration pipeline complet
8 decision_engine.py 609 Decisions KEEP/DOWNGRADE/REMOVE
9 anonymizer.py 529 3 phases anonymisation
10 veto_engine.py 411 Vetos + contestabilite

7. Tests

Couverture par fichier (top 10)

Fichier test Lignes Fonctions
test_cpam_response.py 1 289 75
test_rag.py 1 089 72
test_medical.py 686 94
test_fusion.py 493 33
test_viewer.py 299 31
test_das_llm.py 272 13
test_clinical_context.py 264 36
test_das_filter.py 260 67
test_justification.py 245 13
test_rum_export.py 212 29

Zones sous-testees

  • quality/ : nouveau module, pas de fichier test dedie visible
  • rag_index.py : 803L sans test specifique (teste via test_rag.py)
  • Ratio global : 0.56 (en baisse vs 0.68 en v1) -- le code a grandi plus vite que les tests

8. Dependencies externes

Package Role Criticite
pdfplumber Extraction PDF Haute
PyMuPDF PDF alternatif + redaction Haute
torch + transformers Modeles HF Haute
sentence-transformers Embeddings RAG Haute
faiss-cpu Index semantique Haute
edsnlp NLP medical francais Moyenne (optionnel)
flask Viewer web Moyenne
pydantic Validation donnees Haute
requests Client HTTP (Ollama) Haute
openpyxl + pandas Parsing Excel CPAM Moyenne
PyYAML Configuration YAML Haute (v2)

9. Variables globales et thread-safety

Thread-safe

Module Variable Technique
config.py _RULES_RUNTIME_CTX contextvars.ContextVar
rag_search.py _embed_model Lock + double-check + sentinel
rag_search.py _reranker_model Lazy singleton
cim10_dict.py _dict_cache @lru_cache(maxsize=1)
ccam_dict.py _dict_cache @lru_cache(maxsize=1)
ollama_cache.py JSON File-based lock (fcntl)

Non thread-safe (risque)

Module Variable Risque
main.py:139 _use_edsnlp Race condition en batch multi-thread
main.py:141 _use_rag Race condition en batch multi-thread

10. Dettes techniques

Haute priorite

# Description Fichier Impact
T1 Flags _use_edsnlp, _use_rag non thread-safe main.py Comportement imprevisible en batch
T2 cim10_extractor.py (1352L) melange 4+ responsabilites medical/ Testabilite, maintenance
T3 cpam_response.py (1046L) -- prompts en dur, pas de templates control/ Versioning, A/B testing
T4 Docstrings manquantes sur extract_medical_info() cim10_extractor.py Documentation API
T5 except Exception: sans re-raise dans main.py main.py Bugs silencieux

Moyenne priorite

# Description Fichier Impact
T6 Prompts LLM en dur (~50 lignes) cim10_extractor.py Versioning
T7 Pas de pytest-cov -> couverture inconnue tests/ Risque regressions
T8 Cache Ollama sans TTL, grandit indefiniment ollama_cache.py Disque
T9 GHM estime sur 28% des dossiers seulement ghm.py Reporting incomplet
T10 quality/ sans tests dedies tests/ Couverture insuffisante

Basse priorite

# Description Fichier Impact
T11 Pagination viewer (500+ dossiers) viewer/app.py UX
T12 Extraction CCAM eparses (~1/dossier) cim10_extractor.py Completude
T13 Vetos/decisions appliques 2x (PDF + fusion) -- code duplique main.py Maintenance

11. Points forts architecturaux

  1. Couche quality/ deterministe : le LLM propose, le moteur de regles dispose -- conforme au principe de l'IA medicale
  2. Pipeline CPAM multi-pass : extraction -> argumentation -> validation adversariale avec modeles potentiellement differents
  3. Configuration YAML editable : regles, seuils bio, routage dynamique sans toucher au code
  4. Fallbacks gracieux : CUDA->CPU (embedding), Ollama->Anthropic (LLM), edsnlp optionnel
  5. RAG dual-index : separation referentiels / procedures pour meilleure precision
  6. Fusion multi-PDFs : gestion native des dossiers en plusieurs parties
  7. Tracabilite : tags [BIO-1], [IMG-2] etc. dans les arguments CPAM

12. Recommandations

Court terme (stabilite)

  1. Remplacer _use_edsnlp / _use_rag par contextvars (thread-safety)
  2. Ajouter docstrings sur les fonctions principales des monolithes
  3. Remplacer except Exception: par logging exc_info=True + re-raise fatales
  4. Ajouter tests dedies pour quality/ (decision_engine, veto_engine, rules_router)

Moyen terme (maintenance)

  1. Externaliser les prompts LLM dans src/prompts/ (templates versionnables)
  2. Refactorer cim10_extractor.py : separer extraction LLM / validation / enrichissement RAG
  3. Ajouter pytest-cov et viser 70%+ de couverture
  4. Extraire la logique vetos+decisions dupliquee dans un helper _apply_quality_checks()

Long terme (architecture pro)

  1. Architecture en couches : Domain / Use Cases / Adapters
  2. Event bus pour vetos/decisions (permet A/B testing regles sans code)
  3. Architecture multi-modeles LLM (role-based dispatch : coding, cpam, validation, qc)