feat: traçabilité source systématique + viewer interactif
Ajoute source_page/source_excerpt à tous les types (biologie, imagerie, traitements, actes CCAM, antécédents, complications). Convertit antecedents et complications en types structurés (Antecedent/Complication) avec validators backward-compat pour les vieux JSON. Étend _apply_source_tracking à tous les éléments du dossier. Ajoute un endpoint /api/source-text/ et un modal interactif dans le viewer avec surlignage du texte source. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -125,24 +125,44 @@ class ActeCCAM(BaseModel):
|
||||
date: Optional[str] = None
|
||||
validite: Optional[str] = None # "valide" | "obsolete" | "non_verifie"
|
||||
alertes: list[str] = Field(default_factory=list)
|
||||
source_page: Optional[int] = None
|
||||
source_excerpt: Optional[str] = None
|
||||
|
||||
|
||||
class Traitement(BaseModel):
|
||||
medicament: str
|
||||
posologie: Optional[str] = None
|
||||
code_atc: Optional[str] = None
|
||||
source_page: Optional[int] = None
|
||||
source_excerpt: Optional[str] = None
|
||||
|
||||
|
||||
class BiologieCle(BaseModel):
|
||||
test: str
|
||||
valeur: Optional[str] = None
|
||||
anomalie: Optional[bool] = None
|
||||
source_page: Optional[int] = None
|
||||
source_excerpt: Optional[str] = None
|
||||
|
||||
|
||||
class Imagerie(BaseModel):
|
||||
type: str
|
||||
conclusion: Optional[str] = None
|
||||
score: Optional[str] = None
|
||||
source_page: Optional[int] = None
|
||||
source_excerpt: Optional[str] = None
|
||||
|
||||
|
||||
class Antecedent(BaseModel):
|
||||
texte: str
|
||||
source_page: Optional[int] = None
|
||||
source_excerpt: Optional[str] = None
|
||||
|
||||
|
||||
class Complication(BaseModel):
|
||||
texte: str
|
||||
source_page: Optional[int] = None
|
||||
source_excerpt: Optional[str] = None
|
||||
|
||||
|
||||
class DossierMedical(BaseModel):
|
||||
@@ -152,17 +172,45 @@ class DossierMedical(BaseModel):
|
||||
diagnostic_principal: Optional[Diagnostic] = None
|
||||
diagnostics_associes: list[Diagnostic] = Field(default_factory=list)
|
||||
actes_ccam: list[ActeCCAM] = Field(default_factory=list)
|
||||
antecedents: list[str] = Field(default_factory=list)
|
||||
antecedents: list[Antecedent] = Field(default_factory=list)
|
||||
traitements_sortie: list[Traitement] = Field(default_factory=list)
|
||||
biologie_cle: list[BiologieCle] = Field(default_factory=list)
|
||||
imagerie: list[Imagerie] = Field(default_factory=list)
|
||||
complications: list[str] = Field(default_factory=list)
|
||||
complications: list[Complication] = Field(default_factory=list)
|
||||
alertes_codage: list[str] = Field(default_factory=list)
|
||||
source_files: list[str] = Field(default_factory=list)
|
||||
ghm_estimation: Optional[GHMEstimation] = None
|
||||
controles_cpam: list[ControleCPAM] = Field(default_factory=list)
|
||||
processing_time_s: float | None = None
|
||||
|
||||
@field_validator("antecedents", mode="before")
|
||||
@classmethod
|
||||
def _coerce_antecedents(cls, v):
|
||||
"""Backward compat : convertit les anciennes list[str] en list[Antecedent]."""
|
||||
if not isinstance(v, list):
|
||||
return v
|
||||
result = []
|
||||
for item in v:
|
||||
if isinstance(item, str):
|
||||
result.append({"texte": item})
|
||||
else:
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
@field_validator("complications", mode="before")
|
||||
@classmethod
|
||||
def _coerce_complications(cls, v):
|
||||
"""Backward compat : convertit les anciennes list[str] en list[Complication]."""
|
||||
if not isinstance(v, list):
|
||||
return v
|
||||
result = []
|
||||
for item in v:
|
||||
if isinstance(item, str):
|
||||
result.append({"texte": item})
|
||||
else:
|
||||
result.append(item)
|
||||
return result
|
||||
|
||||
|
||||
# --- Rapport d'anonymisation ---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user