feat: ajout RAG CIM-10 avec FAISS + Ollama

Implémente un système RAG (Retrieval Augmented Generation) qui indexe
les documents de référence ATIH (CIM-10 FR 2026, Guide Métho MCO,
CCAM PMSI) et utilise Ollama (mistral-small3.2:24b) pour justifier
et valider le codage CIM-10 des diagnostics.

- Nouveaux modèles Pydantic : RAGSource, Diagnostic étendu (confidence,
  justification, sources_rag) — rétrocompatible
- Module rag_index.py : chunking des 3 PDFs, embedding sentence-camembert-large,
  index FAISS IndexFlatIP (3630 vecteurs)
- Module rag_search.py : recherche FAISS + appel Ollama avec fallback double
- Flag CLI --no-rag pour désactiver l'enrichissement RAG
- 18 nouveaux tests (88/88 passent)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dom
2026-02-10 17:47:08 +01:00
parent 4a12cd2676
commit 4d6fbef2b9
8 changed files with 885 additions and 4 deletions

View File

@@ -22,8 +22,9 @@ logging.basicConfig(
)
logger = logging.getLogger(__name__)
# Flag global pour désactiver edsnlp
# Flags globaux
_use_edsnlp = True
_use_rag = True
def process_pdf(pdf_path: Path) -> tuple[str, DossierMedical, AnonymizationReport]:
@@ -63,7 +64,7 @@ def process_pdf(pdf_path: Path) -> tuple[str, DossierMedical, AnonymizationRepor
edsnlp_result = _run_edsnlp(anonymized_text)
# 6. Extraction médicale CIM-10
dossier = extract_medical_info(parsed, anonymized_text, edsnlp_result)
dossier = extract_medical_info(parsed, anonymized_text, edsnlp_result, use_rag=_use_rag)
dossier.source_file = pdf_path.name
dossier.document_type = doc_type
logger.info(" DP : %s", dossier.diagnostic_principal)
@@ -123,7 +124,7 @@ def write_outputs(
def main(input_path: str | None = None) -> None:
"""Point d'entrée principal."""
global _use_edsnlp
global _use_edsnlp, _use_rag
parser = argparse.ArgumentParser(
description="Anonymisation de documents médicaux PDF et extraction CIM-10",
@@ -144,6 +145,11 @@ def main(input_path: str | None = None) -> None:
action="store_true",
help="Désactiver l'analyse edsnlp (mode regex seul)",
)
parser.add_argument(
"--no-rag",
action="store_true",
help="Désactiver l'enrichissement RAG (FAISS + Ollama)",
)
args = parser.parse_args()
if args.no_ner:
@@ -154,6 +160,9 @@ def main(input_path: str | None = None) -> None:
if args.no_edsnlp:
_use_edsnlp = False
if args.no_rag:
_use_rag = False
input_p = Path(args.input)
if input_p.is_file():
pdfs = [input_p]