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

@@ -2,10 +2,13 @@
from __future__ import annotations
import logging
import re
from datetime import datetime
from typing import Optional
logger = logging.getLogger(__name__)
from ..config import (
ActeCCAM,
BiologieCle,
@@ -91,6 +94,7 @@ def extract_medical_info(
parsed_data: dict,
anonymized_text: str,
edsnlp_result: Optional[EdsnlpResult] = None,
use_rag: bool = False,
) -> DossierMedical:
"""Extrait les informations médicales structurées depuis les données parsées et le texte."""
dossier = DossierMedical()
@@ -105,9 +109,23 @@ def extract_medical_info(
_extract_imagerie(anonymized_text, dossier)
_extract_complications(anonymized_text, dossier, edsnlp_result)
if use_rag:
_enrich_with_rag(dossier)
return dossier
def _enrich_with_rag(dossier: DossierMedical) -> None:
"""Enrichit les diagnostics via le RAG (FAISS + Ollama)."""
try:
from .rag_search import enrich_dossier
enrich_dossier(dossier)
except ImportError:
logger.warning("Module RAG non disponible (faiss-cpu ou sentence-transformers manquant)")
except Exception:
logger.warning("Erreur lors de l'enrichissement RAG", exc_info=True)
def _extract_sejour(parsed: dict, dossier: DossierMedical) -> None:
"""Extrait les informations de séjour."""
patient = parsed.get("patient", {})