File size: 9,296 Bytes
5aec14b aa6bf8a 5aec14b 8acfcaf aaf8cf2 4bb7d6f e82969b 15ec37f aaf8cf2 e82969b 8acfcaf e82969b 15ec37f aa6bf8a e82969b aa6bf8a 15ec37f aa6bf8a 15ec37f aa6bf8a 15ec37f aa6bf8a aaf8cf2 5aec14b c37ed45 5aec14b 15ec37f aaf8cf2 5aec14b c37ed45 15ec37f 5aec14b c37ed45 5aec14b aa6bf8a c37ed45 15ec37f aa6bf8a c37ed45 df4a994 5aec14b 83a7a3b be39fa4 aa6bf8a 8acfcaf df4a994 5aec14b df4a994 c37ed45 df4a994 c37ed45 be39fa4 15ec37f df4a994 8acfcaf df4a994 5aec14b 15ec37f aa6bf8a 5aec14b df4a994 aa6bf8a 5aec14b aaf8cf2 15ec37f aaf8cf2 aa6bf8a 15ec37f 788ec9b 5aec14b 788ec9b aa6bf8a 788ec9b aa6bf8a 5aec14b 788ec9b 5aec14b 788ec9b 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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# utils/oneclick.py
from typing import Tuple, Optional, Dict
from .meldrx import MeldRxAPI
from .responseparser import PatientDataExtractor
from .pdfutils import PDFGenerator
from .verifier import DischargeVerifier
import logging
import json
from huggingface_hub import InferenceClient
import os
logger = logging.getLogger(__name__)
HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
raise ValueError("HF_TOKEN environment variable not set.")
client = InferenceClient(api_key=HF_TOKEN)
MODEL_NAME = "meta-llama/Llama-3.3-70B-Instruct"
verifier = DischargeVerifier()
def generate_ai_discharge_summary(patient_dict: Dict[str, str], client) -> Tuple[Optional[str], Optional[str]]:
"""Generate a discharge summary using AI and verify it for hallucinations."""
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=MODEL_NAME,
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
discharge_summary = discharge_summary.strip()
logger.info("AI discharge summary generated successfully")
question = "Provide a complete discharge summary based on the patient information."
verified_summary = verifier.verify_discharge_summary(
context=formatted_summary,
question=question,
answer=discharge_summary
)
return discharge_summary, verified_summary
except Exception as e:
logger.error(f"Error generating AI discharge summary: {str(e)}", exc_info=True)
return None, 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], Optional[str]]:
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, 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, None
logger.info(f"Found {len(extractor.patients)} patients in the data")
matching_patient = None
patient_id_input = str(patient_id).strip().lower()
first_name_input = str(first_name).strip().lower()
last_name_input = str(last_name).strip().lower()
for i in range(len(extractor.patients)):
extractor.set_patient_by_index(i)
patient_data = extractor.get_patient_dict()
logger.debug(f"Processing patient {i}: {patient_data}") # Add debug log
patient_id_from_data = str(patient_data.get('id', '')).strip().lower()
if patient_id_input and patient_id_from_data == patient_id_input:
matching_patient = patient_data
logger.info(f"Exact match found for patient ID: {patient_id_from_data}")
break
if not matching_patient and (first_name_input or last_name_input):
for i in range(len(extractor.patients)):
extractor.set_patient_by_index(i)
patient_data = extractor.get_patient_dict()
first_name_from_data = str(patient_data.get('first_name', '')).strip().lower()
last_name_from_data = str(patient_data.get('last_name', '')).strip().lower()
if (first_name_input == first_name_from_data and
last_name_input == last_name_from_data):
matching_patient = patient_data
logger.info(f"Match found by name: {first_name_from_data} {last_name_from_data}")
break
if not matching_patient:
search_criteria = f"ID: {patient_id or 'N/A'}, First: {first_name or 'N/A'}, Last: {last_name or 'N/A'}"
all_patient_ids = [str(p.get('id', '')) for p in extractor.get_all_patients()]
all_patient_names = [f"{p.get('first_name', '')} {p.get('last_name', '')}".strip()
for p in extractor.get_all_patients()]
logger.warning(f"No patients matched criteria: {search_criteria}")
return None, (f"No patients found matching criteria: {search_criteria}\n"
f"Available IDs: {', '.join(all_patient_ids)}\n"
f"Available Names: {', '.join(all_patient_names)}"), None, None, None
logger.info(f"Selected patient data: {matching_patient}")
basic_summary = format_discharge_summary(matching_patient)
ai_summary, verified_summary = generate_ai_discharge_summary(matching_patient, client)
if not ai_summary or not verified_summary:
return None, "Failed to generate or verify AI summary", basic_summary, None, None
pdf_gen = PDFGenerator()
filename = f"discharge_{matching_patient.get('id', 'unknown')}_{matching_patient.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 and verified successfully", basic_summary, ai_summary, verified_summary
return None, "Failed to generate PDF file", basic_summary, ai_summary, verified_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, 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 == "") |