Génération de comptes rendus d'hospitalisation (CRH) synthétiques à partir de statistiques PMSI nationales et de modèles de langage (LLM).
Stream unifie plusieurs méthodes de génération au sein d'une architecture commune, chacune étant implémentée sous forme de pipeline :
| Pipeline | Source de données | Méthode | Statut |
|---|---|---|---|
| Brest | ATIH (Base nationale) | Tirage pondéré DP/CCAM/DAS/DMS + LLM | Implémenté |
| AP-HP | ATIH (Base nationale) | Tirage pondéré PMSI + LLM | Implémenté |
Projets de référence : Doppelgänger (CHU Brest) et Recode-Scenario (AP-HP).
Stream/
├── cli.py # Point d'entrée CLI
├── runner.py # Orchestration du pipeline
├── core/
│ ├── config.py # Chargement YAML
│ ├── logger.py # Logger console
│ └── clients.py # Definition des clients de connexion (Ollama, Mistral, Antropic)
├── pipelines/
│ ├── __init__.py # Expose les pipelines et modules communs
│ ├── pipeline.py # Classes de base et clients LLM
│ ├── fictive.py # Génération de séjours fictifs (Brest/AP-HP)
│ ├── scenario.py # Transformation en scénarios textuels
│ ├── report.py # Génération de rapports CRH via LLM
│ ├── brest/
│ │ ├── __init__.py # Expose BrestPipeline, constants, sampler
│ │ ├── pipeline.py # Pipeline Brest spécifique
│ │ ├── constants.py # Constantes et sources de données
│ │ ├── fictive.py # Création de CR fictif
│ │ ├── report.py # Création de rapport
│ │ └── sampler.py # Échantillonnage et génération aléatoire
│ └── aphp/
│ ├── __init__.py # Expose les modules AP-HP et APHPPipeline
│ ├── pipeline.py # Pipeline AP-HP spécifique
│ ├── loader.py # Chargement des référentiels et données PMSI
│ ├── scenario.py # Construction des scénarios cliniques
│ ├── managment.py # Classification des types de prise en charge
│ ├── prompt.py # Génération des prompts utilisateur et système
│ ├── sampler.py # Échantillonnage et génération aléatoire
│ ├── constants.py # Constantes et listes de codes
│ ├── fictive.py # Création de CR fictif
│ ├── report.py # Création de rapport
│ ├── referentials/ # Référentiels AP-HP (ICD-10, CCAM, GHM, etc.)
│ └── templates/ # Modèles de prompts système
└── config/
├── prompts.yaml # System prompts LLM
└── servers.example.yaml # Template config (copier vers servers.yaml)
Avec pip :
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtAvec uv:
uv venv
source .venv/bin/activate
uv syncCopier le template et renseigner vos clés API :
cp config/servers.example.yaml config/servers.yamlÉditer config/servers.yaml :
pipelines:
brest:
data:
input: "data/brest/" # CSV PMSI extraits via SAS
output: "reports/brest/" # CRH générés
aphp:
data:
input: "data/aphp/" # Fichiers PMSI AP-HP
output: "reports/aphp/" # CRH générés
referentials: "data/aphp/referentials" # Référentiels AP-HP
generation:
mode: "direct" # direct ou mistral_batch
max_tokens: 4096 # Nombre maximum de tokens par requête
poll_interval_seconds: 1 # Intervalle de polling en secondes
servers:
ollama:
host: "http://localhost:11434"
model: "mistral"
claude:
api_key: "sk-..."
model: "claude-sonnet-4-6"
mistral:
api_key: "..."
model: "mistral-large-latest"Pour reproduire la méthode historique AP-HP avec Mistral, le pipeline AP-HP peut être lancé en mode batch Mistral :
pipelines:
aphp:
generation:
mode: "mistral_batch"
max_tokens: 128000
poll_interval_seconds: 1Ce mode est spécifique au client mistral. Le mode direct reste le mode par défaut et fonctionne avec Ollama, Claude et Mistral.
Déposer les CSV suivants dans le répertoire data.input configuré :
| Fichier | Contenu |
|---|---|
PMSI_DP.csv |
Probabilités P(DP | GHM5) |
PMSI_DAS.csv |
Probabilités P(DAS | GHM5, AGE, SEXE, DP) |
PMSI_CCAM_DP.csv |
Probabilités P(CCAM | GHM5, DP) |
PMSI_DMS.csv |
Durées de séjour (P25, P50, P75) |
ALL_CIM10.csv |
Référentiel diagnostics CIM-10 |
ALL_CCAM.csv |
Référentiel actes CCAM |
ALL_CLASSIF_PMSI.csv |
Référentiel GHM |
Ces fichiers sont produits par les scripts d'extraction ATIH spécifiques au CHU Brest.
Déposer les fichiers suivants dans le répertoire data.input configuré :
| Fichier | Contenu |
|---|---|
scenarios_*.parquet |
Profils PMSI avec diagnostics principaux et associés |
bn_pmsi_related_diag_*.csv |
Diagnostics associés par GHM |
bn_pmsi_procedures_*.csv |
Actes CCAM par GHM |
Ces fichiers sont produits par les scripts d'extraction ATIH spécifiques à l'AP-HP. Les référentiels AP-HP doivent être placés dans data.referentials.
# Générer 500 CRH avec Ollama (local)
python cli.py brest --n-sejours 500
# Générer avec Claude, filtré sur les GHM chirurgicaux "06C"
python cli.py brest --client claude --n-sejours 1000 --ghm5 06C
# Générer avec Mistral, 3 actes CCAM max, 4 DAS max
python cli.py brest --client mistral --n-ccam 3 --n-das 4# Générer 2 CRH AP-HP avec le mode direct par défaut
python cli.py aphp --n-sejours 2
# Générer des CRH AP-HP avec Claude
python cli.py aphp --client claude --n-sejours 10
# Générer des CRH AP-HP avec Mistral en mode direct
python cli.py aphp --client mistral --n-sejours 10| Option | Défaut | Description |
|---|---|---|
pipeline |
— | brest ou aphp |
--client |
ollama |
ollama, claude ou mistral |
--n-sejours |
1000 | Nombre de séjours fictifs |
--n-ccam |
1 | Nombre max d'actes CCAM par séjour (Brest uniquement) |
--n-das |
5 | Nombre max de diagnostics associés (Brest uniquement) |
--ghm5 |
— | Filtre sur les codes GHM5 (ex. 06C) |
--batch-size |
1000 | Lignes par fichier Parquet de sortie |
Les sorties sont écrites en fichiers Parquet horodatés dans le répertoire data.output.
Pour les générations classiques :
reports/brest/medical_reports_1000_20260405_143022.parquet
reports/aphp/medical_reports_10_20260512_113644.parquet
Pour le pipeline AP-HP, les scénarios complets sont également sauvegardés avant l’appel au LLM :
reports/aphp/generated_scenarios_10_20260512_113402.parquet
Ces fichiers contiennent notamment les diagnostics, DAS, actes, règle de codage, template, scenario, user_prompt, system_prompt, prefix et prefix_len.
En mode Mistral batch AP-HP, les sorties sont sauvegardées séparément :
reports/aphp/aphp_mistral_batch_reports_10_20260512_115347.parquet
Schéma minimal des sorties CRH : generation_id, scenario, report, model, timestamp.
Les sorties AP-HP peuvent contenir des colonnes supplémentaires utiles au debug et à la comparaison avec la méthode historique AP-HP.
Pour exécuter les tests unitaires, utilisez la commande suivante :
python -m tests/ -vou plus simplement à l'aide du Makefile
make testLes tests couvrent :
- L'initialisation des pipelines Brest et AP-HP
- La vérification des données d'entrée
- L'intégration des pipelines avec le runner
Les pipelines suivent une architecture modulaire avec trois étapes principales :
get_fictive() → get_scenario() → get_report()
- get_fictive() : Génère des séjours fictifs à partir des données chargées.
- get_scenario() : Transforme les séjours fictifs en scénarios textuels pour le LLM.
- get_report() : Génère les comptes rendus d'hospitalisation (CRH) à partir des scénarios.
Trois nouveaux modules ont été ajoutés pour centraliser la logique commune entre les pipelines :
Module responsable de la génération de séjours fictifs à partir des données PMSI.
Fonction principale :
generate_fictive_stays(data, n_sejours, generate_fn, **kwargs)
Responsabilités :
- Génération de séjours fictifs pour les pipelines Brest et AP-HP
- Logique d'échantillonnage spécifique à chaque pipeline
- Réduction de la duplication de code
Module responsable de la transformation des séjours fictifs en scénarios textuels pour les LLM.
Fonction principale :
format_scenarios(df, scenario_fn, **kwargs)
Responsabilités :
- Transformation des séjours en prompts textuels
- Formatage spécifique Brest (simple) et AP-HP (riche)
- Gestion des templates et règles ATIH
Module responsable de la génération de rapports CRH via appels LLM.
Fonction principale :
generate_reports(df, client, model, batch_size, output_dir, generate_fn)
Responsabilités :
- Interaction avec les clients LLM (Anthropic, Mistral, Ollama)
- Gestion des batches et persistance des résultats
- Formatage des réponses LLM
flowchart TD
subgraph Source["Source de données (ATIH)"]
A["Base nationale ATIH"]
end
subgraph Brest["Pipeline Brest"]
B1["Extraction CHU Brest"] --> B2["CSV: DP/DAS/DMS/CCAM"]
B2 --> B3["Tirage pondéré simple"]
B3 --> B4["Scénarios génériques"]
B4 --> B5["Templates LLM basiques"]
end
subgraph APHP["Pipeline AP-HP"]
A2["Extraction AP-HP"] --> A3["Parquet: Scénarios PMSI"]
A3 --> A4["Tirage + règles ATIH"]
A4 --> A5["Scénarios enrichis"]
A5 --> A6["Templates LLM spécifiques"]
A6 --> A7["Validation ATIH"]
end
A --> B1
A --> A2
style Source fill:#f9f,stroke:#333
style Brest fill:#bbf,stroke:#333
style APHP fill:#bfb,stroke:#333
| Aspect | Pipeline Brest (CHU Brest) | Pipeline AP-HP (Paris) |
|---|---|---|
| Extraction | Scripts CHU Brest | Scripts AP-HP spécifiques |
| Format | CSV (DP/DAS/DMS/CCAM) | Parquet (scénarios PMSI) |
| Tirage | Pondéré simple | Pondéré + règles ATIH |
| Modules | fictive.py, scenario.py | + report.py personnalisé |
| Classification | Basique | MCO/SSR/HAD (managment.py) |
| Validation | Standard | Règles ATIH spécifiques |
| Templates | Génériques | Spécifiques AP-HP |
| Complexité | Simple | Sur-couche métier |
Les pipelines Brest et AP-HP ont été mis à jour pour utiliser ces modules communs :
class BrestPipeline(BasePipeline):
@override
def get_fictive(self, data, **kwargs):
return generate_fictive_stays(data, generate_fn=generate_brest_fictive, **kwargs)
@override
def get_scenario(self, df):
return format_scenarios(df, scenario_fn=format_brest_scenario)
@override
def get_report(
self,
df: pl.DataFrame,
client: AnthropicClient | MistralClient | OllamaClient,
model: str,
batch_size: int = 1000,
) -> pl.DataFrame:
output_dir = Path(self.config["data"]["output"])
system_prompt = self.prompt["generate"]["system_prompt"]
return generate_reports(
df=df,
client=client,
model=model,
generate_fn=generate_brest_report,
batch_size=batch_size,
output_dir=output_dir,
system_prompt=system_prompt,
)Le pipeline AP-HP utilise les modules communs avec une sur-couche spécifique pour la génération de rapports. Cette sur-couche implémente la logique métier AP-HP pour :
- Gestion des référentiels ATIH : Chargement et validation des codes ICD-10, CCAM et GHM spécifiques à l'AP-HP
- Classification des prises en charge : Application des règles de managment (MCO, SSR, HAD) selon les référentiels ATIH
- Génération de prompts enrichis : Intégration des templates système spécifiques AP-HP avec règles de formatage ATIH
- Validation des scénarios : Vérification de la cohérence clinique selon les règles métiers AP-HP
class APHPPipeline(BasePipeline):
@override
def get_fictive(self, data, **kwargs):
return generate_fictive_stays(data, generate_fn=generate_aphp_ficitive, **kwargs)
@override
def get_scenario(self, df):
return format_scenarios(df, scenario_fn=format_aphp_scenario, **kwargs)
@override
def get_report(
self,
df: pl.DataFrame,
client: Any,
model: str,
batch_size: int = 1000,
) -> pl.DataFrame:
"""Generate one CRH per scenario using the row's own system prompt.
Overrides :meth:`~pipelines.pipeline.BasePipeline.get_report` to read
``df_row["system_prompt"]`` instead of a single global system prompt.
"""
output_dir = Path(self.config["data"]["output"])
return generate_reports(
df,
client,
model,
batch_size=batch_size,
output_dir=output_dir,
generate_fn=generate_aphp_report,
system_prompt="", # just for signature since system from is in the df in the function generate_aphp_report
)Créer une classe héritant de BasePipeline et implémenter les 4 méthodes :
from pipelines.pipeline import BasePipeline
class MonPipeline(BasePipeline):
name = "mon_pipeline"
def check_data(self) -> None:
"""Verify that source data is present and prepare it if needed."""
# Ajoutez des messages de log pour faciliter le débogage
self.logger.info("Vérification des données d'entrée pour le pipeline %s.", self.name)
# Votre logique de vérification des données ici
self.logger.info("Données vérifiées avec succès.")
def load_data(self) -> dict[str, pl.LazyFrame]:
"""Load prepared data as LazyFrames."""
# Ajoutez des messages de log pour suivre le chargement des données
self.logger.info("Chargement des données pour le pipeline %s.", self.name)
# Votre logique de chargement des données ici
self.logger.info("Données chargées avec succès.")
return {}
def get_fictive(self, data, **kwargs) -> pl.DataFrame:
"""Generate fictitious hospital stays from loaded data."""
# Ajoutez des messages de log pour suivre la génération des séjours fictifs
self.logger.info("Génération de %d séjours fictifs.", kwargs.get("n_sejours", 1000))
# Votre logique de génération des séjours fictifs ici
self.logger.info("Génération des séjours fictifs terminée avec succès.")
return pl.DataFrame()
def get_scenario(self, df) -> pl.DataFrame:
"""Transform fictitious stays into text scenarios for the LLM."""
# Ajoutez des messages de log pour suivre le formatage des scénarios
self.logger.info("Formatage des scénarios pour %d séjours.", len(df))
# Votre logique de formatage des scénarios ici
self.logger.info("Formatage des scénarios terminé avec succès.")
return dfPuis l'enregistrer dans runner.py (PIPELINES) et cli.py (choices).
gantt
title Roadmap de fusion des pipelines
dateFormat YYYY-MM
section Étapes techniques
Unification interfaces :a1, 2024-05, 2024-06
Refactoring ciblé :a2, 2024-06, 2024-07
Validation complète :a3, 2024-07, 2024-08
section Décisions architecturales
Référentiels :crit1, 2024-05, 2024-05
Règles métiers :crit2, 2024-05, 2024-06
Validation données :crit3, 2024-06, 2024-06
Templates LLM :crit4, 2024-06, 2024-07
section Livraison
Intégration continue :2024-07, 2024-08
Documentation finale :2024-08, 2024-08
1. Unification des interfaces (Mai-Juin 2024)
- Aligner
get_report()entre pipelines - Standardiser les structures de données
- Créer des adaptateurs pour les spécificités
2. Refactoring ciblé (Juin-Juillet 2024)
- Extraire la logique métier AP-HP
- Documenter les divergences nécessaires
- Optimiser les performances
3. Validation complète (Juillet-Août 2024)
- Tests d'intégration croisés Brest/AP-HP
- Benchmarking comparatif
- Validation des données et cohérence
mindmap
root((Décisions architecturales))
Référentiels
Séparés (Brest/AP-HP)
Unifiés avec mappings
Système de plugins
Règles métiers
Modules spécifiques
Configurable (YAML)
Moteur générique
Validation
Stricte (échec rapide)
Progressive (warnings)
Scoring qualité
Templates LLM
Séparés par établissement
Unifié conditionnel
Composition modulaire
-
Ateliers collaboratifs (Mai 2024)
- Alignement Brest/AP-HP sur les besoins
- Priorisation des décisions
-
Prototypage (Juin 2024)
- Preuves de concept pour options critiques
- Évaluation technique
-
Benchmarking (Juillet 2024)
- Mesures de performance
- Évaluation maintenabilité
-
Documentation (Août 2024)
- ADR (Architecture Decision Records)
- Mise à jour diagrammes
Ce projet est sous licence Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.
Vous êtes libre de :
- Partager — copier et redistribuer le projet
- Adapter — remixer et transformer le projet Sous les conditions suivantes :
- Attribution — Vous devez citer le projet original
- Non Commercial — Usage commercial interdit sans accord explicite
- Partage dans les mêmes conditions — Toute modification doit être publiée sous la même licence