File size: 8,150 Bytes
5aec14b aa6bf8a 5aec14b aaf8cf2 c37ed45 aa6bf8a c37ed45 aa6bf8a aaf8cf2 5aec14b c37ed45 5aec14b aa6bf8a 5aec14b aa6bf8a 5aec14b aaf8cf2 5aec14b c37ed45 aa6bf8a 5aec14b c37ed45 5aec14b aa6bf8a c37ed45 aa6bf8a c37ed45 5aec14b c37ed45 aa6bf8a c37ed45 5aec14b c37ed45 5aec14b c37ed45 5aec14b c37ed45 5aec14b aa6bf8a c37ed45 5aec14b aa6bf8a 5aec14b aa6bf8a 5aec14b aaf8cf2 aa6bf8a aaf8cf2 aa6bf8a 5aec14b aa6bf8a 5aec14b aa6bf8a 5aec14b aa6bf8a 5aec14b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# utils/oneclick.py
from typing import Tuple, Optional, Dict
from .meldrx import MeldRxAPI
from .responseparser import PatientDataExtractor
from .pdfutils import PDFGenerator
import logging
logger = logging.getLogger(__name__)
def generate_ai_discharge_summary(patient_dict: Dict[str, str], client) -> Optional[str]:
"""Generate a discharge summary using AI based on extracted patient data."""
try:
formatted_summary = format_discharge_summary(patient_dict)
logger.info("Generating AI discharge summary with patient info: %s", formatted_summary)
messages = [
{
"role": "assistant",
"content": (
"You are a senior medical practitioner tasked with creating discharge summaries. "
"Generate a complete discharge summary based on the provided patient information."
)
},
{"role": "user", "content": formatted_summary}
]
stream = client.chat.completions.create(
model="grok-3",
messages=messages,
temperature=0.4,
max_tokens=3584,
top_p=0.7,
stream=True
)
discharge_summary = ""
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
discharge_summary += content
logger.info("AI discharge summary generated successfully")
return discharge_summary.strip()
except Exception as e:
logger.error(f"Error generating AI discharge summary: {str(e)}", exc_info=True)
return None
def generate_discharge_paper_one_click(
api: MeldRxAPI,
client,
patient_id: str = "",
first_name: str = "",
last_name: str = ""
) -> Tuple[Optional[str], str, Optional[str], Optional[str]]:
"""
Generate a discharge summary PDF with one click using MeldRx API data.
Returns:
Tuple of (pdf_path, status_message, basic_summary, ai_summary)
"""
try:
patients_data = api.get_patients()
if not patients_data or "entry" not in patients_data:
logger.error("No patient data received from MeldRx API")
return None, "Failed to fetch patient data from MeldRx API", None, None
logger.debug(f"Raw patient data from API: {patients_data}")
extractor = PatientDataExtractor(patients_data, "json")
if not extractor.patients:
logger.error("No patients found in the parsed data")
return None, "No patients found in the data", None, None
logger.info(f"Found {len(extractor.patients)} patients in the data")
matching_patients = []
for i in range(len(extractor.patients)):
extractor.set_patient_by_index(i)
patient_data = extractor.get_patient_dict()
patient_id_from_data = patient_data.get('id', '').strip().lower()
first_name_from_data = patient_data.get('first_name', '').strip().lower()
last_name_from_data = patient_data.get('last_name', '').strip().lower()
patient_id_input = patient_id.strip().lower()
first_name_input = first_name.strip().lower()
last_name_input = last_name.strip().lower()
logger.debug(f"Comparing - ID: {patient_id_input} vs {patient_id_from_data}, "
f"First: {first_name_input} vs {first_name_from_data}, "
f"Last: {last_name_input} vs {last_name_from_data}")
matches = True
if patient_id_input and patient_id_from_data != patient_id_input:
matches = False
if first_name_input and first_name_from_data != first_name_input:
matches = False
if last_name_input and last_name_from_data != last_name_input:
matches = False
if matches:
matching_patients.append(patient_data)
logger.info(f"Found matching patient: {patient_data.get('id', 'unknown')}")
if not matching_patients:
search_criteria = f"ID: {patient_id or 'N/A'}, First: {first_name or 'N/A'}, Last: {last_name or 'N/A'}"
logger.warning(f"No patients matched criteria: {search_criteria}")
return None, f"No patients found matching criteria: {search_criteria}", None, None
patient_data = matching_patients[0]
logger.info(f"Selected patient data: {patient_data}")
basic_summary = format_discharge_summary(patient_data)
ai_summary = generate_ai_discharge_summary(patient_data, client)
if not ai_summary:
return None, "Failed to generate AI summary", basic_summary, None
pdf_gen = PDFGenerator()
filename = f"discharge_{patient_data.get('id', 'unknown')}_{patient_data.get('last_name', 'patient')}.pdf"
pdf_path = pdf_gen.generate_pdf_from_text(ai_summary, filename)
if pdf_path:
return pdf_path, "Discharge summary generated successfully", basic_summary, ai_summary
return None, "Failed to generate PDF file", basic_summary, ai_summary
except Exception as e:
logger.error(f"Error in one-click discharge generation: {str(e)}", exc_info=True)
return None, f"Error generating discharge summary: {str(e)}", None, None
def format_discharge_summary(patient_data: dict) -> str:
"""Format patient data into a discharge summary text."""
patient_data.setdefault('name_prefix', '')
patient_data.setdefault('first_name', '')
patient_data.setdefault('last_name', '')
patient_data.setdefault('dob', 'Unknown')
patient_data.setdefault('age', 'Unknown')
patient_data.setdefault('sex', 'Unknown')
patient_data.setdefault('id', 'Unknown')
patient_data.setdefault('address', 'Unknown')
patient_data.setdefault('city', 'Unknown')
patient_data.setdefault('state', 'Unknown')
patient_data.setdefault('zip_code', 'Unknown')
patient_data.setdefault('phone', 'Unknown')
patient_data.setdefault('admission_date', 'Unknown')
patient_data.setdefault('discharge_date', 'Unknown')
patient_data.setdefault('diagnosis', 'Unknown')
patient_data.setdefault('medications', 'None specified')
patient_data.setdefault('doctor_first_name', 'Unknown')
patient_data.setdefault('doctor_last_name', 'Unknown')
patient_data.setdefault('hospital_name', 'Unknown')
patient_data.setdefault('doctor_address', 'Unknown')
patient_data.setdefault('doctor_city', 'Unknown')
patient_data.setdefault('doctor_state', 'Unknown')
patient_data.setdefault('doctor_zip', 'Unknown')
summary = [
"DISCHARGE SUMMARY",
"",
"PATIENT INFORMATION",
f"Name: {patient_data['name_prefix']} {patient_data['first_name']} {patient_data['last_name']}".strip(),
f"Date of Birth: {patient_data['dob']}",
f"Age: {patient_data['age']}",
f"Gender: {patient_data['sex']}",
f"Patient ID: {patient_data['id']}",
"",
"CONTACT INFORMATION",
f"Address: {patient_data['address']}",
f"City: {patient_data['city']}, {patient_data['state']} {patient_data['zip_code']}",
f"Phone: {patient_data['phone']}",
"",
"ADMISSION INFORMATION",
f"Admission Date: {patient_data['admission_date']}",
f"Discharge Date: {patient_data['discharge_date']}",
f"Diagnosis: {patient_data['diagnosis']}",
"",
"MEDICATIONS",
f"{patient_data['medications']}",
"",
"PHYSICIAN INFORMATION",
f"Physician: Dr. {patient_data['doctor_first_name']} {patient_data['doctor_last_name']}".strip(),
f"Hospital: {patient_data['hospital_name']}",
f"Address: {patient_data['doctor_address']}",
f"City: {patient_data['doctor_city']}, {patient_data['doctor_state']} {patient_data['doctor_zip']}",
]
return "\n".join(line for line in summary if line.strip() or line == "") |