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>
This commit is contained in:
dom
2026-03-04 11:57:07 +01:00
parent 795110d2e6
commit ce7a9650af
19 changed files with 1681 additions and 418 deletions

View File

@@ -8,6 +8,7 @@ from .templates import (
CPAM_EXTRACTION,
CPAM_ARGUMENTATION,
CPAM_ADVERSARIAL,
DP_RANKER_CONSTRAINED,
)
__all__ = [
@@ -18,4 +19,5 @@ __all__ = [
"CPAM_EXTRACTION",
"CPAM_ARGUMENTATION",
"CPAM_ADVERSARIAL",
"DP_RANKER_CONSTRAINED",
]

View File

@@ -14,9 +14,11 @@ Variables par template :
decision_ucr, dp_ucr_line, da_ucr_line
CPAM_ARGUMENTATION : dossier_str, asymetrie_str, tagged_str, titre,
arg_ucr, decision_ucr, codes_str, definitions_str,
codes_autorises_str, sources_text, extraction_str
codes_autorises_str, sources_text, extraction_str,
bio_confrontation_str, numero_ogc
CPAM_ADVERSARIAL : response_json, factual_section, normes_section,
dp_ucr_line, da_ucr_line
DP_RANKER_CONSTRAINED : candidates_str, ctx_str, n_candidates
"""
# ---------------------------------------------------------------------------
@@ -215,96 +217,122 @@ Réponds UNIQUEMENT en JSON :
# ---------------------------------------------------------------------------
# 6. CPAM_ARGUMENTATION — Passe 2 contre-argumentation CPAM
# 6. CPAM_ARGUMENTATION — Passe 2 contre-argumentation CPAM (méthode TIM)
# Source : cpam_response.py _build_cpam_prompt()
# Rôle : cpam | Température : 0.1 | max_tokens : 4000
# Rôle : cpam | Température : 0.1 | max_tokens : 16000
# ---------------------------------------------------------------------------
CPAM_ARGUMENTATION = """\
Tu es un médecin DIM (Département d'Information Médicale) expert en contentieux T2A.
Tu dois produire une analyse ÉQUILIBRÉE ET CRÉDIBLE de la contestation CPAM, puis contre-argumenter en mobilisant trois axes : médical, asymétrie d'information, et réglementaire.
Tu es un médecin DIM senior expert en contentieux T2A. Tu rédiges un MÉMOIRE EN DÉFENSE \
structuré et argumenté pour répondre à la contestation CPAM ci-dessous.
IMPORTANT — CRÉDIBILITÉ DE L'ANALYSE :
Une contre-argumentation crédible reconnaît TOUJOURS au moins un point valide dans le raisonnement adverse.
Répondre "Aucun point d'accord" décrédibilise l'ensemble de l'argumentation. Tu DOIS identifier au moins un élément où la CPAM a un point légitime (même partiel), puis expliquer pourquoi cela ne suffit pas à invalider le codage.
Ta méthode suit les 5 passes de raisonnement expert TIM :
IMPORTANT — CODES CIM-10 :
Ne parle JAMAIS de « codage initial » ou « codage contesté » sans citer explicitement le code CIM-10 et son libellé (ex: Z45.80 — Ajustement et entretien d'un dispositif implantable).
Chaque argument doit désigner précisément quel code est défendu ou contesté, avec son libellé complet.
PASSE 1 — CONTEXTE ADMINISTRATIF :
Analyse le contexte du séjour (âge, sexe, durée, mode d'entrée/sortie, actes) pour cadrer \
ton raisonnement. En pédiatrie (< 18 ans), les normes biologiques et codages diffèrent. \
Une admission en urgence implique un contexte aigu influençant le DP.
DOSSIER MÉDICAL DE L'ÉTABLISSEMENT :
{dossier_str}
PASSE 2 — MOTIF D'HOSPITALISATION RÉEL :
Distingue le motif d'entrée déclaré du motif réel en te posant :
- Pourquoi CE patient a été hospitalisé CE JOUR (événement déclencheur)
- Quel acte thérapeutique principal a été réalisé
- Le DP retenu est-il cohérent avec cet acte et la durée de séjour
PASSE 3 — CONFRONTATION BIOLOGIE / DIAGNOSTIC :
Pour chaque diagnostic contesté, confronte aux seuils biologiques :
{bio_confrontation_str}
- Une valeur normale CONTREDIT un diagnostic actif basé sur cette biologie
- Une valeur pathologique SANS diagnostic est un sous-codage potentiel
- CITE les seuils exacts et les valeurs du dossier
PASSE 4 — HIÉRARCHIE DIAGNOSTIQUE :
- Le DP est le diagnostic qui a CONSOMMÉ LE PLUS DE RESSOURCES (pas le plus grave)
- Spécifique exclut générique (K81.0 présent → retirer K81.9)
- Codes R (symptômes) INTERDITS en DP si étiologie identifiée
- Chaque DAS doit répondre OUI à au moins une question :
1. Traitement spécifique pendant ce séjour ?
2. Allongement de la durée de séjour ?
3. Modification de la surveillance ou des examens ?
PASSE 5 — VALIDATION DÉFENSIVE (regard CPAM) :
Pour CHAQUE code défendu, tu DOIS répondre aux 4 questions :
1. Ce diagnostic est-il documenté EXPLICITEMENT dans le dossier, ou DÉDUIT ?
2. Y a-t-il une preuve OBJECTIVE (valeur bio, imagerie, acte CCAM) ?
3. Le code est-il COHÉRENT avec la durée de séjour et les actes réalisés ?
4. Quel DOCUMENT du dossier cite-t-on en premier face à la CPAM ?
DOSSIER MÉDICAL : {dossier_str}
{asymetrie_str}
{tagged_str}
OBJET DU DÉSACCORD : {titre}
CONTESTATION CPAM :
Objet : {titre}
Argument UCR : {arg_ucr}
Décision UCR : {decision_ucr}
ARGUMENTATION DE LA CPAM (UCR) :
{arg_ucr}
DÉCISION UCR : {decision_ucr}
CODES CONTESTÉS :
{codes_str}
CODES EN JEU : {codes_str}
{definitions_str}
{codes_autorises_str}
SOURCES RÉGLEMENTAIRES (Guide méthodologique, CIM-10) :
{sources_text}
SOURCES RÉGLEMENTAIRES : {sources_text}
{extraction_str}
CONSIGNES :
RÈGLE ABSOLUE — HONNÊTETÉ INTELLECTUELLE :
Un mémoire crédible ne force JAMAIS un argument que le dossier ne soutient pas.
- Si une valeur biologique est NORMALE alors que le diagnostic l'exige pathologique → \
tu DOIS le signaler et NE PAS défendre ce code sur cet axe
- Si un diagnostic n'a AUCUNE preuve objective (pas de bio, pas d'imagerie, pas d'acte) → \
tu écris : "Ce diagnostic repose sur le seul jugement clinique, sans preuve biologique ou \
paraclinique dans le dossier"
- Si la confrontation bio CONTREDIT un diagnostic → tu NE LE DÉFENDS PAS et tu le signales \
dans le champ "codes_non_defendables"
- Si la CPAM a RAISON sur un point → tu le reconnais clairement. Mieux vaut concéder un \
point indéfendable et gagner en crédibilité sur les points solides
- Principe TIM : "Mieux vaut un code moins précis mais défendable qu'un code précis mais \
indéfendable"
CONTEXTE CLINIQUE :
- Prends en compte l'ÂGE du patient (pédiatrie < 18 ans, personne âgée >= 80 ans), le MODE D'ENTRÉE (urgence vs programmé), et la DURÉE DE SÉJOUR pour contextualiser ton analyse
- En pédiatrie, les normes biologiques et les codages peuvent différer de l'adulte
- Une admission en urgence implique un contexte clinique aigu qui influence le choix du DP
CONSIGNES DE RÉDACTION :
ÉTAPE 1 — ANALYSE HONNÊTE (avant de contre-argumenter) :
- Identifie ce que la CPAM a compris correctement dans le dossier
- Reconnais les points où leur raisonnement est fondé, même partiellement
- Explique ENSUITE pourquoi ces points ne justifient pas leur conclusion
1. STRUCTURE EN MOYENS DE DÉFENSE NUMÉROTÉS (pas de prose libre)
2. Chaque moyen = un argument autonome avec sa preuve FORMELLEMENT DOCUMENTÉE dans le dossier
3. CITE les codes CIM-10 avec libellé complet (ex: N17.8 — Autre insuffisance rénale aiguë)
4. CITE les valeurs bio EXACTES avec seuils normatifs (ex: "CRP = 145 mg/L [norme < 5]")
5. CITE les sources réglementaires au format [Document - page N] "citation verbatim"
6. JAMAIS d'argument sans preuve traçable — si tu n'as pas la preuve, NE FAIS PAS l'argument
7. Ton ASSERTIF mais factuel — pas de formules creuses ("il convient de noter que...")
8. Si un point CPAM est légitime, le reconnaître CLAIREMENT — la crédibilité globale en dépend
9. N'invente AUCUN tag, code ou source qui n'est pas fourni ci-dessus
10. NE JAMAIS qualifier une valeur NORMALE comme pathologique ni extrapoler au-delà des faits
11. Tags valides : [DP], [DAS-N], [BIO-N], [IMG-N], [TRT-N], [ACTE-N], [ANT-N], [COMPL-N]
AXE MÉDICAL :
- Analyse le bien-fondé médical du codage de l'établissement
- CITE les éléments cliniques EXACTS du dossier en utilisant UNIQUEMENT les tags [XX-N] fournis dans la section ÉLÉMENTS CLINIQUES RÉFÉRENCÉS
- Tags valides : [DP], [DAS-N], [BIO-N], [IMG-N], [TRT-N], [ACTE-N], [ANT-N], [COMPL-N]
- N'invente JAMAIS un tag qui ne figure pas dans la liste ci-dessus. Si un élément n'a pas de tag, décris-le en texte libre SANS crochets.
- Confronte l'argumentation CPAM aux sources CIM-10 et Guide Méthodologique fournies
- Ne mentionne AUCUN élément qui ne figure pas dans les éléments référencés ci-dessus
AXE ASYMÉTRIE D'INFORMATION :
- La CPAM a fondé son analyse uniquement sur le CRH et les codes transmis
- Pour CHAQUE élément clinique pertinent, cite les VALEURS EXACTES et explique leur signification clinique
- Démontre en quoi ces éléments complémentaires (biologie, imagerie, traitements, actes) justifient le codage contesté
- Ne mentionne AUCUN élément qui n'est pas dans le dossier fourni
MISE EN FORME :
- Structure chaque section avec des tirets pour lister les arguments distincts
- Un argument par puce, avec la preuve ou la référence associée
AXE RÉGLEMENTAIRE :
- Identifie si l'UCR fait une interprétation restrictive non fondée d'une règle
- Confronte le raisonnement CPAM au texte EXACT des sources fournies
- Format OBLIGATOIRE pour chaque référence : [Document - page N] suivi d'une CITATION VERBATIM du passage pertinent
- INTERDICTION ABSOLUE de citer une référence qui ne figure pas dans les sources fournies ci-dessus
- Si aucune source pertinente n'est disponible → écrire explicitement "Pas de source réglementaire disponible"
- Relève les contradictions entre l'argumentation CPAM et les règles officielles
Réponds UNIQUEMENT avec un objet JSON au format suivant :
Réponds UNIQUEMENT avec un objet JSON :
{{
"analyse_contestation": "Résumé de ce que conteste la CPAM et sur quelle base",
"points_accord": "Points CONCRETS où la CPAM a raison ou partiellement raison (JAMAIS 'Aucun' — il y a toujours au moins un point légitime à reconnaître)",
"contre_arguments_medicaux": "Argumentation médicale en faveur du codage, en expliquant pourquoi les points d'accord ne suffisent pas à invalider le codage",
"preuves_dossier": [
{{"ref": "BIO-1 ou DAS-3 ou DP (UNIQUEMENT un tag existant de la section ÉLÉMENTS CLINIQUES RÉFÉRENCÉS)", "element": "biologie|imagerie|traitement|acte|diagnostic|antécédent|complication", "valeur": "valeur exacte du dossier", "signification": "explication clinique"}}
"objet": "Contestation {titre} — OGC {numero_ogc} — Mémoire en défense",
"rappel_faits": "Résumé factuel du séjour en 3-5 lignes : motif, actes, durée, issue",
"moyens_defense": [
{{
"numero": 1,
"titre": "Titre court du moyen (ex: Le DP N17.8 est justifié par la biologie)",
"argument": "Développement avec preuves tagées [XX-N], valeurs bio avec seuils, sources réglementaires",
"preuves": [
{{"ref": "[BIO-1]", "fait": "Créatinine = 280 µmol/L [norme 50-120]", "signification": "IRA confirmée"}}
],
"source_reglementaire": "[Document - page N] citation verbatim ou null"
}}
],
"confrontation_bio": [
{{"diagnostic": "N17.8 IRA", "test": "Créatinine", "valeur": 280, "seuil": "> 130 µmol/L", "verdict": "CONFIRMÉ"}}
],
"asymetrie_information": "Éléments cliniques que la CPAM n'avait PAS (bio, imagerie, actes) — brièvement",
"reponse_points_cpam": "Pour chaque point légitime de la CPAM : reconnaissance CLAIRE + réfutation factuelle OU concession si indéfendable",
"codes_non_defendables": [
{{"code": "D50.9", "raison": "Hb = 13.5 g/dL [norme > 12 F] — valeur NORMALE, anémie non confirmée biologiquement", "recommandation": "Retrait recommandé — code indéfendable face à la CPAM"}}
],
"contre_arguments_asymetrie": "Éléments cliniques que la CPAM n'avait pas et qui justifient le codage",
"contre_arguments_reglementaires": "Erreurs d'interprétation réglementaire de la CPAM, avec citations verbatim des sources",
"references": [
{{"document": "nom du document source", "page": "numéro de page", "citation": "citation verbatim du passage"}}
],
"conclusion": "Synthèse en citant EXPLICITEMENT les codes CIM-10 défendus (ex: DP Z45.80 — libellé) : points reconnus à la CPAM, puis pourquoi ce codage précis est néanmoins justifié"
"conclusion_dispositive": "Par conséquent, au vu des éléments cliniques objectifs (citer les preuves clés), des règles CIM-10 applicables (citer les sources), et des informations complémentaires non transmises à l'UCR, nous demandons le MAINTIEN du codage : DP [CODE — libellé], DAS [CODE — libellé]. [Si code non défendable :] Nous reconnaissons que le code [CODE] ne dispose pas d'un support documentaire suffisant."
}}"""
@@ -315,7 +343,8 @@ Réponds UNIQUEMENT avec un objet JSON au format suivant :
# ---------------------------------------------------------------------------
CPAM_ADVERSARIAL = """\
Tu es un relecteur critique. Vérifie la cohérence de cette contre-argumentation CPAM.
Tu es un relecteur critique expert en codage PMSI. Vérifie la cohérence et l'honnêteté \
intellectuelle de ce mémoire en défense CPAM.
RÉPONSE GÉNÉRÉE :
{response_json}
@@ -329,11 +358,17 @@ CODES CONTESTÉS :
{da_ucr_line}
Vérifie STRICTEMENT :
1. Chaque valeur bio/imagerie/traitement citée dans les preuves existe dans les éléments factuels
2. Si une valeur bio est qualifiée de "élevée", "basse" ou "anormale", vérifie qu'elle est RÉELLEMENT hors normes selon les normes ci-dessus (ex: CRP 5 = NORMAL, pas élevé)
3. La conclusion est cohérente avec l'argumentation développée
4. Les points d'accord ne contredisent pas les contre-arguments
5. Les codes CIM-10 mentionnés dans la conclusion sont cohérents avec le reste
1. Chaque moyen de défense a une preuve traçable FORMELLEMENT documentée dans les éléments factuels
2. Si une valeur bio est qualifiée de "élevée", "basse" ou "anormale", vérifie qu'elle est \
RÉELLEMENT hors normes selon les normes ci-dessus (ex: CRP 5 = NORMAL, pas élevé)
3. AUCUNE valeur NORMALE n'est présentée comme pathologique
4. La confrontation bio (champ "confrontation_bio") est cohérente avec les valeurs du dossier \
et les seuils normatifs
5. Les codes signalés dans "codes_non_defendables" ne sont PAS défendus dans "moyens_defense"
6. La conclusion dispositive cite les bons codes et reconnaît les concessions
7. Les seuils bio cités correspondent aux normes officielles ci-dessus
8. Les codes CIM-10 mentionnés dans la conclusion sont cohérents avec le reste
9. Le champ "reponse_points_cpam" répond factuellement aux arguments CPAM (pas de déni)
Réponds UNIQUEMENT en JSON :
{{
@@ -341,3 +376,36 @@ Réponds UNIQUEMENT en JSON :
"erreurs": ["description précise de chaque incohérence trouvée"],
"score_confiance": 0 à 10
}}"""
# ---------------------------------------------------------------------------
# 8. DP_RANKER_CONSTRAINED — NUKE-3 sélection DP dans une liste fermée
# Source : dp_selector.py _llm_rank()
# Rôle : coding | Température : 0.0 | max_tokens : 1000
# ---------------------------------------------------------------------------
DP_RANKER_CONSTRAINED = """\
Tu es un médecin DIM expert en codage PMSI. Tu dois choisir le Diagnostic Principal (DP) \
parmi la liste FERMÉE de {n_candidates} candidats ci-dessous.
RÈGLES STRICTES :
1. Le DP reflète le MOTIF PRINCIPAL de prise en charge pendant ce séjour
2. Un acte seul (cholécystectomie, biopsie…) NE PEUT PAS être DP s'il existe un candidat textuel
3. Un symptôme (R00-R99) NE PEUT PAS être DP si une étiologie candidate existe dans la liste
4. Une comorbidité chronique (HTA, diabète, BPCO) NE PEUT PAS être DP sauf prise en charge ACTIVE
5. Tu DOIS choisir un index de la liste — JAMAIS de réponse hors liste
CANDIDATS :
{candidates_str}
CONTEXTE CLINIQUE :
{ctx_str}
Réponds UNIQUEMENT en JSON :
{{
"chosen_index": N,
"confidence": "high|medium|low",
"verdict": "CONFIRMED|REVIEW",
"evidence": ["raison 1", "raison 2"],
"reason": "explication courte justifiant le choix"
}}"""