"""Templates LLM externalisés pour le pipeline T2A. Chaque template utilise str.format() avec des variables nommées. Les accolades JSON sont doublées ({{ }}) pour échapper le format(). Les fragments conditionnels (ex: DP UCR) sont résolus AVANT l'appel à template.format() dans les fonctions appelantes. Variables par template : CODING_CIM10 : texte, type_diag, ctx_str, sources_text CODING_CCAM : texte, ctx_str, sources_text DAS_EXTRACTION : dp_texte, existing_str, ctx_str, text_medical QC_VALIDATION : ctx_str, codes_section CPAM_EXTRACTION : dp_str, das_str, tagged_text, titre, arg_ucr, 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, sources_text, extraction_str CPAM_ADVERSARIAL : response_json, factual_section, normes_section, dp_ucr_line, da_ucr_line """ # --------------------------------------------------------------------------- # 1. CODING_CIM10 — Codage CIM-10 (DP ou DAS) via RAG # Source : rag_search.py _build_prompt() # Rôle : coding | Température : 0.1 | max_tokens : 2500 # --------------------------------------------------------------------------- CODING_CIM10 = """\ Tu es un médecin DIM (Département d'Information Médicale) expert en codage PMSI. Tu dois coder le diagnostic suivant en respectant STRICTEMENT les règles de l'ATIH. RÈGLES IMPÉRATIVES : - Le code doit provenir UNIQUEMENT des sources CIM-10 fournies - Distingue la DESCRIPTION CLINIQUE (ce que le médecin écrit) de la LOGIQUE DE CODAGE (ce que l'ATIH impose) - Privilégie le code le plus SPÉCIFIQUE disponible (4e ou 5e caractère) - Vérifie les notes d'inclusion/exclusion de chaque code candidat - Si le diagnostic est un DP, il doit refléter le motif principal de prise en charge du séjour - Si c'est un DAS, il doit avoir mobilisé des ressources supplémentaires pendant le séjour - EXCLUSION SYMPTÔME : Si le diagnostic est un symptôme (R00-R99) et qu'un diagnostic précis (Chapitres I-XIV, A00-N99) expliquant ce symptôme est présent, le symptôme ne doit PAS être codé comme DAS DIAGNOSTIC À CODER : "{texte}" TYPE : {type_diag} CONTEXTE CLINIQUE : {ctx_str} SOURCES DE RÉFÉRENCE : {sources_text} Réponds UNIQUEMENT avec un objet JSON au format suivant, sans aucun texte avant ou après : {{ "analyse_clinique": "que signifie ce diagnostic sur le plan médical", "codes_candidats": "quels codes CIM-10 des sources sont compatibles", "discrimination": "pourquoi choisir ce code plutôt qu'un autre (inclusions/exclusions, spécificité)", "regle_pmsi": "conformité aux règles PMSI pour un {type_diag} (guide méthodologique)", "code": "X99.9", "confidence": "high ou medium ou low", "justification": "explication courte en français", "preuves_cliniques": [ {{"type": "biologie|imagerie|traitement|acte|clinique", "element": "élément concret du dossier", "interpretation": "signification clinique justifiant le code"}} ] }}""" # --------------------------------------------------------------------------- # 2. CODING_CCAM — Codage CCAM via RAG # Source : rag_search.py _build_prompt_ccam() # Rôle : coding | Température : 0.1 | max_tokens : 2500 # --------------------------------------------------------------------------- CODING_CCAM = """\ Tu es un médecin DIM (Département d'Information Médicale) expert en codage CCAM PMSI. Tu dois coder l'acte chirurgical/médical suivant en respectant STRICTEMENT la nomenclature CCAM. RÈGLES IMPÉRATIVES : - Le code doit provenir UNIQUEMENT des sources CCAM fournies - Un code CCAM est composé de 4 lettres + 3 chiffres (ex: HMFC004) - Vérifie l'activité (1=acte technique, 4=anesthésie) et le regroupement - Tiens compte du tarif secteur 1 pour valider la cohérence - Si plusieurs codes sont possibles, choisis le plus spécifique à l'acte décrit - En cas de doute, indique confidence "low" plutôt que de proposer un code inadapté ACTE À CODER : "{texte}" CONTEXTE CLINIQUE : {ctx_str} SOURCES CCAM : {sources_text} Réponds UNIQUEMENT avec un objet JSON au format suivant, sans aucun texte avant ou après : {{ "analyse_acte": "que décrit cet acte sur le plan technique/chirurgical", "codes_candidats": "quels codes CCAM des sources sont compatibles", "discrimination": "pourquoi choisir ce code plutôt qu'un autre (activité, regroupement, tarif)", "code": "ABCD123", "confidence": "high ou medium ou low", "justification": "explication courte en français" }}""" # --------------------------------------------------------------------------- # 3. DAS_EXTRACTION — Extraction DAS supplémentaires via LLM # Source : rag_search.py _build_prompt_das_extraction() # Rôle : coding | Température : 0.1 | max_tokens : 2000 # --------------------------------------------------------------------------- DAS_EXTRACTION = """\ Tu es un médecin DIM (Département d'Information Médicale) expert en codage PMSI. Analyse le texte médical suivant et identifie les diagnostics associés significatifs (DAS) qui n'ont PAS encore été codés. RÈGLES IMPÉRATIVES : - Un DAS doit avoir mobilisé des ressources supplémentaires pendant le séjour - Ne PAS proposer de doublons avec les DAS déjà codés ci-dessous - Ne PAS proposer le diagnostic principal comme DAS - Ne PAS coder les symptômes (R00-R99) si un diagnostic précis les explique - Ne PAS coder les antécédents non pertinents pour le séjour - Privilégie les codes CIM-10 les plus SPÉCIFIQUES (4e ou 5e caractère) - Ne propose que des diagnostics CLAIREMENT mentionnés dans le texte - ATTENTION aux valeurs biologiques : ne code PAS un diagnostic si les valeurs sont dans les normes indiquées entre crochets [N: min-max]. Exemple : Créatinine 76 [N: 50-120] = NORMAL, pas d'insuffisance rénale. DIAGNOSTIC PRINCIPAL : {dp_texte} DAS DÉJÀ CODÉS : {existing_str} CONTEXTE CLINIQUE : {ctx_str} TEXTE MÉDICAL : {text_medical} Réponds UNIQUEMENT avec un objet JSON au format suivant, sans aucun texte avant ou après : {{ "diagnostics_supplementaires": [ {{ "texte": "description du diagnostic", "code_cim10": "X99.9", "justification": "pourquoi ce DAS est pertinent pour le séjour" }} ] }} Si aucun DAS supplémentaire n'est pertinent, retourne : {{"diagnostics_supplementaires": []}}""" # --------------------------------------------------------------------------- # 4. QC_VALIDATION — Validation croisée batch des justifications # Source : cim10_extractor.py _validate_justifications() # Rôle : qc | Température : 0.1 | max_tokens : 2500 # --------------------------------------------------------------------------- QC_VALIDATION = """\ Tu es un médecin DIM contrôleur qualité PMSI. Vérifie la cohérence et la justification de ce codage complet. DOSSIER CLINIQUE : {ctx_str} CODAGE À VALIDER : {codes_section} Pour CHAQUE code, vérifie : 1. Existe-t-il une preuve clinique concrète dans le dossier ? 2. Le code est-il le plus spécifique possible ? 3. Y a-t-il des conflits ou redondances avec d'autres codes ? Réponds avec un JSON : {{ "validations": [ {{ "numero": 1, "code": "X99.9", "verdict": "maintenir|reclasser|supprimer", "confidence_recommandee": "high|medium|low", "commentaire": "explication courte" }} ], "alertes_globales": ["..."] }}""" # --------------------------------------------------------------------------- # 5. CPAM_EXTRACTION — Passe 1 extraction structurée CPAM # Source : cpam_response.py _extraction_pass() # Rôle : cpam | Température : 0.0 | max_tokens : 1500 # --------------------------------------------------------------------------- CPAM_EXTRACTION = """\ Tu es un médecin DIM expert. Analyse cette contestation CPAM sans argumenter. DOSSIER : - DP : {dp_str} - DAS : {das_str} {tagged_text} CONTESTATION CPAM : Titre : {titre} Argument : {arg_ucr} Décision : {decision_ucr} {dp_ucr_line} {da_ucr_line} Réponds UNIQUEMENT en JSON : {{ "comprehension_contestation": "Résumé factuel : que conteste la CPAM et pourquoi", "elements_cliniques_pertinents": [ {{"tag": "BIO-1 ou texte libre", "pertinence": "en quoi cet élément est pertinent pour le codage contesté"}} ], "points_accord_potentiels": ["points où la CPAM a partiellement raison"], "codes_en_jeu": {{ "dp_etablissement": "code + libellé", "dp_ucr": "code + libellé si proposé", "difference_cle": "explication de la différence entre les deux codages" }} }}""" # --------------------------------------------------------------------------- # 6. CPAM_ARGUMENTATION — Passe 2 contre-argumentation CPAM # Source : cpam_response.py _build_cpam_prompt() # Rôle : cpam | Température : 0.1 | max_tokens : 4000 # --------------------------------------------------------------------------- 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. 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. 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. DOSSIER MÉDICAL DE L'ÉTABLISSEMENT : {dossier_str} {asymetrie_str} {tagged_str} OBJET DU DÉSACCORD : {titre} ARGUMENTATION DE LA CPAM (UCR) : {arg_ucr} DÉCISION UCR : {decision_ucr} CODES CONTESTÉS : {codes_str} {definitions_str} SOURCES RÉGLEMENTAIRES (Guide méthodologique, CIM-10) : {sources_text} {extraction_str} CONSIGNES : 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 É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 AXE MÉDICAL : - Analyse le bien-fondé médical du codage de l'établissement - CITE les éléments cliniques EXACTS du dossier en utilisant les tags [XX-N] fournis (ex: [BIO-1] CRP 180 mg/L) - 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 : {{ "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", "element": "biologie|imagerie|traitement|acte|clinique", "valeur": "valeur exacte du dossier", "signification": "explication clinique"}} ], "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é" }}""" # --------------------------------------------------------------------------- # 7. CPAM_ADVERSARIAL — Validation adversariale de la contre-argumentation # Source : cpam_response.py _validate_adversarial() # Rôle : validation | Température : 0.0 | max_tokens : 800 # --------------------------------------------------------------------------- CPAM_ADVERSARIAL = """\ Tu es un relecteur critique. Vérifie la cohérence de cette contre-argumentation CPAM. RÉPONSE GÉNÉRÉE : {response_json} {factual_section} {normes_section} CODES CONTESTÉS : {dp_ucr_line} {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 Réponds UNIQUEMENT en JSON : {{ "coherent": true ou false, "erreurs": ["description précise de chaque incohérence trouvée"], "score_confiance": 0 à 10 }}"""