Spaces:
Sleeping
Sleeping
| """Clarke data models — Pydantic v2 schemas for all system objects.""" | |
| from __future__ import annotations | |
| from datetime import datetime | |
| from enum import Enum | |
| from typing import Optional | |
| from pydantic import BaseModel, Field | |
| class ConsultationStatus(str, Enum): | |
| """Status lifecycle for a consultation session.""" | |
| IDLE = "idle" | |
| RECORDING = "recording" | |
| PAUSED = "paused" | |
| PROCESSING = "processing" | |
| REVIEW = "review" | |
| SIGNED_OFF = "signed_off" | |
| class PipelineStage(str, Enum): | |
| """Discrete execution stages for the consultation pipeline.""" | |
| TRANSCRIBING = "transcribing" | |
| RETRIEVING_CONTEXT = "retrieving_context" | |
| GENERATING_DOCUMENT = "generating_document" | |
| COMPLETE = "complete" | |
| FAILED = "failed" | |
| class Patient(BaseModel): | |
| """A patient in the clinic list.""" | |
| id: str = Field(description="FHIR Patient resource ID") | |
| nhs_number: str = Field(description="NHS number (format: XXX XXX XXXX)") | |
| name: str = Field(description="Full name (e.g., 'Mrs. Margaret Thompson')") | |
| date_of_birth: str = Field(description="DOB in DD/MM/YYYY format") | |
| age: int | |
| sex: str = Field(description="'Male' or 'Female'") | |
| appointment_time: str = Field(description="HH:MM format") | |
| summary: str = Field(description="One-line clinical summary for dashboard card") | |
| class LabResult(BaseModel): | |
| """A single laboratory result with trend.""" | |
| name: str = Field(description="e.g., 'HbA1c'") | |
| value: str = Field(description="e.g., '55'") | |
| unit: str = Field(description="e.g., 'mmol/mol'") | |
| reference_range: Optional[str] = Field(default=None, description="e.g., '20-42'") | |
| date: str = Field(description="ISO date of result") | |
| trend: Optional[str] = Field(default=None, description="'rising', 'falling', 'stable', or None") | |
| previous_value: Optional[str] = Field(default=None, description="Previous result value") | |
| previous_date: Optional[str] = Field(default=None) | |
| fhir_resource_id: Optional[str] = Field(default=None, description="Source FHIR Observation ID") | |
| class PatientContext(BaseModel): | |
| """Structured patient context synthesised by the EHR Agent from FHIR data.""" | |
| patient_id: str | |
| demographics: dict = Field(description="name, dob, nhs_number, age, sex, address") | |
| problem_list: list[str] = Field(description="Active diagnoses, e.g., ['Type 2 Diabetes Mellitus (2019)', ...]") | |
| medications: list[dict] = Field( | |
| description="[{'name': 'Metformin', 'dose': '1g', 'frequency': 'BD', 'fhir_id': '...'}]" | |
| ) | |
| allergies: list[dict] = Field( | |
| description="[{'substance': 'Penicillin', 'reaction': 'Anaphylaxis', 'severity': 'high'}]" | |
| ) | |
| recent_labs: list[LabResult] = Field(default_factory=list) | |
| recent_imaging: list[dict] = Field(default_factory=list, description="[{'type': 'CXR', 'date': '...', 'summary': '...'}]") | |
| clinical_flags: list[str] = Field(default_factory=list, description="['HbA1c rising trend over 6 months']") | |
| last_letter_excerpt: Optional[str] = Field(default=None, description="Key excerpt from most recent clinic letter") | |
| retrieval_warnings: list[str] = Field(default_factory=list, description="Warnings if some FHIR queries failed") | |
| retrieved_at: str = Field(description="ISO timestamp of retrieval") | |
| class Transcript(BaseModel): | |
| """Consultation transcript produced by MedASR.""" | |
| consultation_id: str | |
| text: str = Field(description="Full transcript text") | |
| duration_s: float = Field(description="Audio duration in seconds") | |
| word_count: int | |
| created_at: str | |
| class DocumentSection(BaseModel): | |
| """A single section of the generated clinical letter.""" | |
| heading: str = Field(description="e.g., 'History of presenting complaint'") | |
| content: str = Field(description="Section body text") | |
| editable: bool = Field(default=True) | |
| fhir_sources: list[str] = Field(default_factory=list, description="FHIR resource IDs cited in this section") | |
| class ClinicalDocument(BaseModel): | |
| """A generated NHS clinical letter.""" | |
| consultation_id: str | |
| letter_date: str | |
| patient_name: str | |
| patient_dob: str | |
| nhs_number: str | |
| addressee: str = Field(description="GP name and address") | |
| salutation: str = Field(description="e.g., 'Dear Dr. Patel,'") | |
| sections: list[DocumentSection] | |
| medications_list: list[str] = Field(description="Current medications (formatted)") | |
| sign_off: str = Field(description="e.g., 'Dr. S. Chen, Consultant Diabetologist'") | |
| status: ConsultationStatus = ConsultationStatus.REVIEW | |
| generated_at: str | |
| generation_time_s: float = Field(description="Time taken for MedGemma 27B inference") | |
| discrepancies: list[dict] = Field(default_factory=list, description="[{'type': 'allergy_mismatch', 'detail': '...'}]") | |
| class Consultation(BaseModel): | |
| """A complete consultation session — links patient, transcript, context, and document.""" | |
| id: str = Field(description="Unique consultation ID (UUID)") | |
| patient: Patient | |
| status: ConsultationStatus = ConsultationStatus.IDLE | |
| pipeline_stage: Optional[PipelineStage] = None | |
| context: Optional[PatientContext] = None | |
| transcript: Optional[Transcript] = None | |
| document: Optional[ClinicalDocument] = None | |
| started_at: Optional[str] = None | |
| ended_at: Optional[str] = None | |
| audio_file_path: Optional[str] = None | |
| doc_type: str = Field(default="Clinic Letter", description="Document type: 'Clinic Letter' or 'Ward Round Note'") | |
| letter_prefs: dict = Field(default_factory=dict, description="Letter preferences from frontend (clinician name, GP, etc.)") | |
| class PipelineProgress(BaseModel): | |
| """Real-time pipeline progress updates pushed to the UI.""" | |
| consultation_id: str | |
| stage: PipelineStage | |
| progress_pct: int = Field(ge=0, le=100) | |
| message: str = Field(description="Human-readable status, e.g., 'Finalising transcript...'") | |
| class ErrorResponse(BaseModel): | |
| """Standardised error response format.""" | |
| error: str = Field(description="Error category: 'model_error', 'fhir_error', 'audio_error', 'timeout'") | |
| message: str = Field(description="Human-readable error message for UI display") | |
| detail: Optional[str] = Field(default=None, description="Technical detail (logged, not shown to user)") | |
| consultation_id: Optional[str] = None | |
| timestamp: str | |