Update callbackmanager.py
Browse files- callbackmanager.py +178 -61
callbackmanager.py
CHANGED
@@ -26,26 +26,20 @@ from PIL import Image # For image handling
|
|
26 |
|
27 |
system_instructions = """
|
28 |
**Discharge Guard - Medical Data Analysis Assistant**
|
29 |
-
|
30 |
**Core Role:** I am Discharge Guard, an advanced AI designed for deep medical data analysis and informational insights. My outputs are based on thorough analysis of medical data but are **not medical advice.**
|
31 |
-
|
32 |
**Important Guidelines:**
|
33 |
-
|
34 |
1. **Deep Analysis & Search:** Perform "Deep Thought and Deep Search" when analyzing medical data. This includes:
|
35 |
* Comprehensive data ingestion from various formats (HL7, FHIR, CCDA, DICOM, PDF, CSV, text).
|
36 |
* Multi-layered analysis: surface extraction, deep pattern identification, and inferential reasoning.
|
37 |
* Contextual understanding of medical data.
|
38 |
* Evidence-based approach, simulating cross-referencing with medical knowledge.
|
39 |
* Structured output with clear explanations.
|
40 |
-
|
41 |
2. **Focus on Informational Insights, Not Medical Advice:** Emphasize that my insights are for informational purposes only and not a substitute for professional medical judgment. **Never provide diagnoses or specific treatment recommendations.**
|
42 |
-
|
43 |
3. **Key Functionalities (Focus Areas):**
|
44 |
* **Clinical Data Analysis:** Interpret lab results, analyze EHR data (FHIR, HL7), recognize symptom patterns, analyze medications, support medical image analysis (DICOM).
|
45 |
* **Predictive Analytics:** Provide conceptual risk stratification and treatment outcome modeling based on data patterns.
|
46 |
* **Medical Imaging Support:** Analyze DICOM metadata and images for potential findings (X-ray analysis reports).
|
47 |
* **Patient Data Management:** Perform PHI redaction in text and analyze patient records from various sources.
|
48 |
-
|
49 |
4. **Interaction Style:**
|
50 |
* **Identity:** "I am Discharge Guard, a medical data analysis AI. My insights are informational only and not medical advice."
|
51 |
* **Scope Limitations:** Clearly state limitations: "No diagnostics," "Medication caution," "Emergency protocol."
|
@@ -54,21 +48,24 @@ system_instructions = """
|
|
54 |
* Mention data sources and confidence levels (if applicable).
|
55 |
* Use medical terminology with optional layman's terms.
|
56 |
* For file analysis, provide a report title (e.g., "Deep X-Ray Analysis Report").
|
57 |
-
|
58 |
5. **Supported Medical Formats:** (List key formats concisely)
|
59 |
* Clinical Data: HL7, FHIR, CCD/CCDA, CSV, PDF, XML
|
60 |
* Imaging: DICOM, Images (X-ray, etc.)
|
61 |
-
|
62 |
6. **Data Source:** Access and prefer FHIR API endpoints from: https://app.meldrx.com/api/directories/fhir/endpoints.
|
63 |
-
|
64 |
**Important: My analysis is for informational purposes to assist healthcare professionals and is NOT a substitute for clinical judgment. Always recommend human expert verification for critical findings.**
|
65 |
"""
|
66 |
|
67 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
def analyze_dicom_file_with_ai(dicom_file_path): # Modified to accept file path
|
69 |
"""Analyzes DICOM file metadata using Discharge Guard AI."""
|
70 |
try:
|
71 |
-
dicom_file = pydicom.dcmread(dicom_file_path) # Read dicom using path
|
72 |
dicom_metadata_json = dicom_file.to_json_dict()
|
73 |
prediction_response, trace_data_dicom_ai = analyze_dicom_content_ai(dicom_metadata_json) # Call content analysis
|
74 |
if prediction_response:
|
@@ -85,14 +82,11 @@ def analyze_dicom_file_with_ai(dicom_file_path): # Modified to accept file path
|
|
85 |
|
86 |
def analyze_dicom_content_ai(dicom_metadata_json): # Copied from your code
|
87 |
"""Analyzes DICOM metadata JSON content using Discharge Guard AI."""
|
88 |
-
prompt_text = f"""Perform a **deep and comprehensive analysis** of the following DICOM metadata in JSON format to provide a **structured summary and identify potential clinically relevant information with deep insights**. Focus not just on summarizing fields, but on **interpreting their clinical significance, identifying subtle patterns, and drawing inferences about the study's implications**. Think like an experienced radiologist reviewing this metadata for crucial diagnostic clues. Remember this is metadata, not the image itself, so focus on what can be gleaned from the data itself. Provide a "**Deep DICOM Metadata Analysis Report**". Important: Use the API Directories fhir endpoints FROM THIS LINK: https://app.meldrx.com/api/directories/fhir/endpoints.
|
89 |
-
|
90 |
**DICOM Metadata (JSON):**
|
91 |
```json
|
92 |
{json.dumps(dicom_metadata_json, indent=2)}
|
93 |
```
|
94 |
-
|
95 |
-
... (rest of your prompt_text for DICOM metadata analysis) ...
|
96 |
* Remember, this deep analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on deep summarization and structuring the extracted metadata in a highly clinically relevant way.
|
97 |
"""
|
98 |
|
@@ -110,8 +104,14 @@ def analyze_dicom_content_ai(dicom_metadata_json): # Copied from your code
|
|
110 |
}
|
111 |
|
112 |
try:
|
113 |
-
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
return the_response, trace_data_detail_dicom_analysis
|
116 |
|
117 |
except Exception as e:
|
@@ -123,7 +123,7 @@ def analyze_dicom_content_ai(dicom_metadata_json): # Copied from your code
|
|
123 |
def analyze_hl7_file_with_ai(hl7_file_path):
|
124 |
"""Analyzes HL7 file content using Discharge Guard AI."""
|
125 |
try:
|
126 |
-
with open(hl7_file_path, 'r') as f: # Open file using path
|
127 |
hl7_message_raw = f.read()
|
128 |
prediction_response, trace_data_hl7_ai = analyze_hl7_content_ai(hl7_message_raw)
|
129 |
|
@@ -141,14 +141,11 @@ def analyze_hl7_file_with_ai(hl7_file_path):
|
|
141 |
|
142 |
def analyze_hl7_content_ai(hl7_message_string): # Copied from your code
|
143 |
"""Analyzes HL7 message content using Discharge Guard AI."""
|
144 |
-
prompt_text = f"""Conduct a **deep and thorough analysis** of the following HL7 message content to provide a **structured summary and identify key clinical information with deep understanding**. Go beyond basic parsing; aim to **interpret the clinical narrative** embedded within the HL7 message. **Engage in deep search to contextualize medical codes and terminology**. Provide a "**Comprehensive HL7 Message Analysis Report**".
|
145 |
-
|
146 |
**HL7 Message Content:**
|
147 |
```hl7
|
148 |
{hl7_message_string}
|
149 |
```
|
150 |
-
|
151 |
-
... (rest of your prompt_text for HL7 analysis) ...
|
152 |
* Remember, this deep analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on deep summarization and structuring the extracted data in a highly clinically relevant way based on the HL7 content.
|
153 |
"""
|
154 |
# ... (rest of the function code) ...
|
@@ -166,8 +163,14 @@ def analyze_hl7_content_ai(hl7_message_string): # Copied from your code
|
|
166 |
}
|
167 |
|
168 |
try:
|
169 |
-
|
170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
return the_response, trace_data_detail_hl7_analysis
|
172 |
|
173 |
except Exception as e:
|
@@ -179,7 +182,7 @@ def analyze_hl7_content_ai(hl7_message_string): # Copied from your code
|
|
179 |
def analyze_cda_xml_file_with_ai(cda_xml_file_path): # Modified to accept file path
|
180 |
"""Analyzes generic CDA or XML file content using Discharge Guard AI (more generalized version) Important: Use the API Directories fhir endpoints FROM THIS LINK: https://app.meldrx.com/api/directories/fhir/endpoints."""
|
181 |
try:
|
182 |
-
with open(cda_xml_file_path, 'r') as f: # Open file using path
|
183 |
cda_xml_content = f.read()
|
184 |
prediction_response, trace_data_cda_xml_ai = analyze_cda_xml_content_ai(
|
185 |
cda_xml_content
|
@@ -199,16 +202,13 @@ def analyze_cda_xml_file_with_ai(cda_xml_file_path): # Modified to accept file p
|
|
199 |
def analyze_cda_xml_content_ai(cda_xml_content): # Copied from your code
|
200 |
"""Analyzes generic CDA or XML content using Discharge Guard AI (more generalized version)."""
|
201 |
|
202 |
-
prompt_text = f"""Analyze the following medical XML/CDA content to provide a **structured and comprehensive patient data analysis**, similar to how a medical professional would review a patient's chart or a clinical document. You need to parse the XML structure yourself to extract the relevant information. Use bullet points, tables, or numbered steps for complex tasks. Provide a "Medical Document Analysis" report.
|
203 |
-
|
204 |
**Instructions for Discharge Guard AI:**
|
205 |
-
|
206 |
1. **Parse the XML content above.** Understand the XML structure to identify sections that are relevant to clinical information. For CDA specifically, look for sections like Problems, Medications, Allergies, Encounters, Results, and Vital Signs. For generic medical XML, adapt based on the tags present.
|
207 |
2. **Extract and Summarize Key Medical Information:** Focus on extracting the following information if present in the XML:
|
208 |
* **Patient Demographics Summary:** (If available, summarize demographic details)
|
209 |
... (rest of your prompt_text for CDA/XML analysis) ...
|
210 |
* Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the extracted data in a clinically relevant way based on the XML/CDA content.
|
211 |
-
|
212 |
"""
|
213 |
|
214 |
trace_data_detail_cda_xml_analysis = {
|
@@ -225,8 +225,14 @@ def analyze_cda_xml_content_ai(cda_xml_content): # Copied from your code
|
|
225 |
}
|
226 |
|
227 |
try:
|
228 |
-
|
229 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
230 |
return the_response, trace_data_detail_cda_xml_analysis
|
231 |
|
232 |
except Exception as e:
|
@@ -238,7 +244,7 @@ def analyze_cda_xml_content_ai(cda_xml_content): # Copied from your code
|
|
238 |
def analyze_pdf_file_with_ai(pdf_file_path): # Modified to accept file path
|
239 |
"""Analyzes PDF file content using Discharge Guard AI."""
|
240 |
try:
|
241 |
-
with open(pdf_file_path, 'rb') as f: # Open file in binary mode for PdfReader
|
242 |
pdf_file = f # Pass file object to PdfReader
|
243 |
pdf_reader = PdfReader(pdf_file)
|
244 |
text_content = ""
|
@@ -261,14 +267,11 @@ def analyze_pdf_file_with_ai(pdf_file_path): # Modified to accept file path
|
|
261 |
|
262 |
def analyze_pdf_content_ai(pdf_text_content): # Copied from your code
|
263 |
"""Analyzes PDF text content using Discharge Guard AI."""
|
264 |
-
prompt_text = f"""Analyze the following medical PDF text content to provide a **structured summary and identify key clinical information**. Focus on patient demographics, medical history, findings, diagnoses, medications, recommendations, and any important clinical details conveyed in the document. Provide a "Medical Report Analysis" report.
|
265 |
-
|
266 |
**Medical PDF Text Content:**
|
267 |
```text
|
268 |
{pdf_text_content}
|
269 |
```
|
270 |
-
|
271 |
-
... (rest of your prompt_text for PDF analysis) ...
|
272 |
* Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the extracted data in a clinically relevant way based on the PDF content.
|
273 |
"""
|
274 |
|
@@ -286,8 +289,14 @@ def analyze_pdf_content_ai(pdf_text_content): # Copied from your code
|
|
286 |
}
|
287 |
|
288 |
try:
|
289 |
-
|
290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
return the_response, trace_data_detail_pdf_analysis
|
292 |
|
293 |
except Exception as e:
|
@@ -299,8 +308,7 @@ def analyze_pdf_content_ai(pdf_text_content): # Copied from your code
|
|
299 |
def analyze_csv_file_with_ai(csv_file_path): # Modified to accept file path
|
300 |
"""Analyzes CSV file content using Discharge Guard AI."""
|
301 |
try:
|
302 |
-
|
303 |
-
csv_content = f.read()
|
304 |
prediction_response, trace_data_csv_ai = analyze_csv_content_ai(csv_content)
|
305 |
|
306 |
if prediction_response:
|
@@ -317,14 +325,11 @@ def analyze_csv_file_with_ai(csv_file_path): # Modified to accept file path
|
|
317 |
|
318 |
def analyze_csv_content_ai(csv_content_string): # Copied from your code
|
319 |
"""Analyzes CSV content (string) using Discharge Guard AI."""
|
320 |
-
prompt_text = f"""Analyze the following medical CSV data to provide a **structured summary and identify potential clinical insights**. Assume the CSV represents patient-related medical data. Focus on understanding the columns, summarizing key data points, identifying trends or patterns, and noting any potential clinical significance of the data. Provide a "Data Analysis" report.
|
321 |
-
|
322 |
**Medical CSV Data:**
|
323 |
```csv
|
324 |
{csv_content_string}
|
325 |
```
|
326 |
-
|
327 |
-
... (rest of your prompt_text for CSV analysis) ...
|
328 |
* Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the data in a clinically relevant way based on the CSV content.
|
329 |
"""
|
330 |
|
@@ -342,8 +347,14 @@ def analyze_csv_content_ai(csv_content_string): # Copied from your code
|
|
342 |
}
|
343 |
|
344 |
try:
|
345 |
-
|
346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
return the_response, trace_data_detail_csv_analysis
|
348 |
|
349 |
except Exception as e:
|
@@ -601,42 +612,130 @@ def generate_pdf_from_meldrx(patient_data):
|
|
601 |
"physician": "Dr. Provider" # Mock data
|
602 |
}
|
603 |
|
604 |
-
# Mock LLM-generated content
|
605 |
llm_content = {
|
606 |
-
"diagnosis": "Diagnosis information would be generated by
|
607 |
-
"treatment": "Treatment summary would be generated by
|
608 |
-
"medications": "Medication list would be generated by
|
609 |
-
"follow_up": "Follow-up instructions would be generated by
|
610 |
-
"special_instructions": "Special instructions would be generated by
|
611 |
}
|
612 |
|
613 |
-
# Create discharge summary
|
614 |
output_dir = tempfile.mkdtemp()
|
615 |
-
pdf_path = generate_discharge_summary(patient_info, llm_content, output_dir)
|
616 |
|
617 |
-
return pdf_path, "PDF generated successfully"
|
618 |
|
619 |
except Exception as e:
|
620 |
return None, f"Error generating PDF: {str(e)}"
|
621 |
|
622 |
def generate_discharge_paper_one_click():
|
623 |
-
"""One-click function to fetch patient data and generate discharge paper."""
|
624 |
patient_data_str = CALLBACK_MANAGER.get_patient_data()
|
625 |
if patient_data_str.startswith("Not authenticated") or patient_data_str.startswith("Failed") or patient_data_str.startswith("Error"):
|
626 |
return None, patient_data_str # Return error message if authentication or data fetch fails
|
627 |
|
628 |
try:
|
629 |
patient_data = json.loads(patient_data_str)
|
630 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
631 |
if pdf_path:
|
632 |
return pdf_path, status_message
|
633 |
else:
|
634 |
return None, status_message # Return status message if PDF generation fails
|
|
|
635 |
except json.JSONDecodeError:
|
636 |
return None, "Error: Patient data is not in valid JSON format."
|
637 |
except Exception as e:
|
638 |
return None, f"Error during discharge paper generation: {str(e)}"
|
639 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
640 |
|
641 |
|
642 |
# Create a simplified interface to avoid complex component interactions
|
@@ -660,7 +759,7 @@ with gr.Blocks() as demo:
|
|
660 |
patient_data_button = gr.Button("Fetch Patient Data")
|
661 |
patient_data_output = gr.Textbox(label="Patient Data", lines=10)
|
662 |
|
663 |
-
# Add button to generate PDF from MeldRx data
|
664 |
meldrx_pdf_button = gr.Button("Generate PDF from MeldRx Data (No AI)") # Renamed button
|
665 |
meldrx_pdf_status = gr.Textbox(label="PDF Generation Status (No AI)") # Renamed status
|
666 |
meldrx_pdf_download = gr.File(label="Download Generated PDF (No AI)") # Renamed download
|
@@ -821,6 +920,13 @@ with gr.Blocks() as demo:
|
|
821 |
ccd_file = gr.File(file_types=['.ccd'], label="Upload CCD File (.ccd)") # Redundant, as CCDA also handles .ccd, but kept for clarity
|
822 |
ccd_ai_output = gr.Textbox(label="CCD Analysis Report", lines=5) # Redundant
|
823 |
analyze_ccd_button = gr.Button("Analyze CCD with AI") # Redundant
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
824 |
|
825 |
|
826 |
# Connect AI Analysis Buttons - using REAL AI functions now
|
@@ -844,6 +950,17 @@ with gr.Blocks() as demo:
|
|
844 |
analyze_cda_xml_file_with_ai, # Call REAL AI function
|
845 |
inputs=ccd_file, outputs=ccd_ai_output
|
846 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
|
848 |
with gr.Tab("One-Click Discharge Paper (AI)"): # New Tab for One-Click Discharge Paper with AI
|
849 |
gr.Markdown("## One-Click Medical Discharge Paper Generation with AI Content") # Updated title
|
@@ -852,7 +969,7 @@ with gr.Blocks() as demo:
|
|
852 |
one_click_ai_pdf_download = gr.File(label="Download Discharge Paper (AI)") # Updated download label
|
853 |
|
854 |
one_click_ai_pdf_button.click(
|
855 |
-
generate_discharge_paper_one_click, # Use the
|
856 |
inputs=[],
|
857 |
outputs=[one_click_ai_pdf_download, one_click_ai_pdf_status]
|
858 |
)
|
@@ -872,9 +989,9 @@ with gr.Blocks() as demo:
|
|
872 |
outputs=dashboard_output
|
873 |
)
|
874 |
|
875 |
-
#
|
876 |
meldrx_pdf_button.click(
|
877 |
-
fn=
|
878 |
inputs=patient_data_output,
|
879 |
outputs=[meldrx_pdf_download, meldrx_pdf_status]
|
880 |
)
|
|
|
26 |
|
27 |
system_instructions = """
|
28 |
**Discharge Guard - Medical Data Analysis Assistant**
|
|
|
29 |
**Core Role:** I am Discharge Guard, an advanced AI designed for deep medical data analysis and informational insights. My outputs are based on thorough analysis of medical data but are **not medical advice.**
|
|
|
30 |
**Important Guidelines:**
|
|
|
31 |
1. **Deep Analysis & Search:** Perform "Deep Thought and Deep Search" when analyzing medical data. This includes:
|
32 |
* Comprehensive data ingestion from various formats (HL7, FHIR, CCDA, DICOM, PDF, CSV, text).
|
33 |
* Multi-layered analysis: surface extraction, deep pattern identification, and inferential reasoning.
|
34 |
* Contextual understanding of medical data.
|
35 |
* Evidence-based approach, simulating cross-referencing with medical knowledge.
|
36 |
* Structured output with clear explanations.
|
|
|
37 |
2. **Focus on Informational Insights, Not Medical Advice:** Emphasize that my insights are for informational purposes only and not a substitute for professional medical judgment. **Never provide diagnoses or specific treatment recommendations.**
|
|
|
38 |
3. **Key Functionalities (Focus Areas):**
|
39 |
* **Clinical Data Analysis:** Interpret lab results, analyze EHR data (FHIR, HL7), recognize symptom patterns, analyze medications, support medical image analysis (DICOM).
|
40 |
* **Predictive Analytics:** Provide conceptual risk stratification and treatment outcome modeling based on data patterns.
|
41 |
* **Medical Imaging Support:** Analyze DICOM metadata and images for potential findings (X-ray analysis reports).
|
42 |
* **Patient Data Management:** Perform PHI redaction in text and analyze patient records from various sources.
|
|
|
43 |
4. **Interaction Style:**
|
44 |
* **Identity:** "I am Discharge Guard, a medical data analysis AI. My insights are informational only and not medical advice."
|
45 |
* **Scope Limitations:** Clearly state limitations: "No diagnostics," "Medication caution," "Emergency protocol."
|
|
|
48 |
* Mention data sources and confidence levels (if applicable).
|
49 |
* Use medical terminology with optional layman's terms.
|
50 |
* For file analysis, provide a report title (e.g., "Deep X-Ray Analysis Report").
|
|
|
51 |
5. **Supported Medical Formats:** (List key formats concisely)
|
52 |
* Clinical Data: HL7, FHIR, CCD/CCDA, CSV, PDF, XML
|
53 |
* Imaging: DICOM, Images (X-ray, etc.)
|
|
|
54 |
6. **Data Source:** Access and prefer FHIR API endpoints from: https://app.meldrx.com/api/directories/fhir/endpoints.
|
|
|
55 |
**Important: My analysis is for informational purposes to assist healthcare professionals and is NOT a substitute for clinical judgment. Always recommend human expert verification for critical findings.**
|
56 |
"""
|
57 |
|
58 |
+
# Initialize Inference Client - Ensure YOUR_HF_TOKEN is set in environment variables or replace with your actual token
|
59 |
+
HF_TOKEN = os.getenv("YOUR_HF_TOKEN") # Or replace with your actual token string
|
60 |
+
if not HF_TOKEN:
|
61 |
+
raise ValueError("YOUR_HF_TOKEN environment variable not set. Please set your Hugging Face API token.")
|
62 |
+
client = InferenceClient(api_key=HF_TOKEN)
|
63 |
+
model_name = "meta-llama/Llama-3.3-70B-Instruct" # Specify the model to use
|
64 |
+
|
65 |
def analyze_dicom_file_with_ai(dicom_file_path): # Modified to accept file path
|
66 |
"""Analyzes DICOM file metadata using Discharge Guard AI."""
|
67 |
try:
|
68 |
+
dicom_file = pydicom.dcmread(dicom_file_path.name) # Read dicom using path, access file through .name for Gradio UploadedFile
|
69 |
dicom_metadata_json = dicom_file.to_json_dict()
|
70 |
prediction_response, trace_data_dicom_ai = analyze_dicom_content_ai(dicom_metadata_json) # Call content analysis
|
71 |
if prediction_response:
|
|
|
82 |
|
83 |
def analyze_dicom_content_ai(dicom_metadata_json): # Copied from your code
|
84 |
"""Analyzes DICOM metadata JSON content using Discharge Guard AI."""
|
85 |
+
prompt_text = f"""{system_instructions} \n\n Perform a **deep and comprehensive analysis** of the following DICOM metadata in JSON format to provide a **structured summary and identify potential clinically relevant information with deep insights**. Focus not just on summarizing fields, but on **interpreting their clinical significance, identifying subtle patterns, and drawing inferences about the study's implications**. Think like an experienced radiologist reviewing this metadata for crucial diagnostic clues. Remember this is metadata, not the image itself, so focus on what can be gleaned from the data itself. Provide a "**Deep DICOM Metadata Analysis Report**". Important: Use the API Directories fhir endpoints FROM THIS LINK: https://app.meldrx.com/api/directories/fhir/endpoints.
|
|
|
86 |
**DICOM Metadata (JSON):**
|
87 |
```json
|
88 |
{json.dumps(dicom_metadata_json, indent=2)}
|
89 |
```
|
|
|
|
|
90 |
* Remember, this deep analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on deep summarization and structuring the extracted metadata in a highly clinically relevant way.
|
91 |
"""
|
92 |
|
|
|
104 |
}
|
105 |
|
106 |
try:
|
107 |
+
response = client.chat.completions.create(
|
108 |
+
model=model_name,
|
109 |
+
messages=[{"role": "user", "content": prompt_text}],
|
110 |
+
temperature=0.4,
|
111 |
+
max_tokens=1024, # Adjust as needed
|
112 |
+
top_p=0.9,
|
113 |
+
)
|
114 |
+
the_response = response.choices[0].message.content
|
115 |
return the_response, trace_data_detail_dicom_analysis
|
116 |
|
117 |
except Exception as e:
|
|
|
123 |
def analyze_hl7_file_with_ai(hl7_file_path):
|
124 |
"""Analyzes HL7 file content using Discharge Guard AI."""
|
125 |
try:
|
126 |
+
with open(hl7_file_path.name, 'r') as f: # Open file using path, access file through .name for Gradio UploadedFile
|
127 |
hl7_message_raw = f.read()
|
128 |
prediction_response, trace_data_hl7_ai = analyze_hl7_content_ai(hl7_message_raw)
|
129 |
|
|
|
141 |
|
142 |
def analyze_hl7_content_ai(hl7_message_string): # Copied from your code
|
143 |
"""Analyzes HL7 message content using Discharge Guard AI."""
|
144 |
+
prompt_text = f"""{system_instructions} \n\n Conduct a **deep and thorough analysis** of the following HL7 message content to provide a **structured summary and identify key clinical information with deep understanding**. Go beyond basic parsing; aim to **interpret the clinical narrative** embedded within the HL7 message. **Engage in deep search to contextualize medical codes and terminology**. Provide a "**Comprehensive HL7 Message Analysis Report**".
|
|
|
145 |
**HL7 Message Content:**
|
146 |
```hl7
|
147 |
{hl7_message_string}
|
148 |
```
|
|
|
|
|
149 |
* Remember, this deep analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on deep summarization and structuring the extracted data in a highly clinically relevant way based on the HL7 content.
|
150 |
"""
|
151 |
# ... (rest of the function code) ...
|
|
|
163 |
}
|
164 |
|
165 |
try:
|
166 |
+
response = client.chat.completions.create(
|
167 |
+
model=model_name,
|
168 |
+
messages=[{"role": "user", "content": prompt_text}],
|
169 |
+
temperature=0.4,
|
170 |
+
max_tokens=1024, # Adjust as needed
|
171 |
+
top_p=0.9,
|
172 |
+
)
|
173 |
+
the_response = response.choices[0].message.content
|
174 |
return the_response, trace_data_detail_hl7_analysis
|
175 |
|
176 |
except Exception as e:
|
|
|
182 |
def analyze_cda_xml_file_with_ai(cda_xml_file_path): # Modified to accept file path
|
183 |
"""Analyzes generic CDA or XML file content using Discharge Guard AI (more generalized version) Important: Use the API Directories fhir endpoints FROM THIS LINK: https://app.meldrx.com/api/directories/fhir/endpoints."""
|
184 |
try:
|
185 |
+
with open(cda_xml_file_path.name, 'r') as f: # Open file using path, access file through .name for Gradio UploadedFile
|
186 |
cda_xml_content = f.read()
|
187 |
prediction_response, trace_data_cda_xml_ai = analyze_cda_xml_content_ai(
|
188 |
cda_xml_content
|
|
|
202 |
def analyze_cda_xml_content_ai(cda_xml_content): # Copied from your code
|
203 |
"""Analyzes generic CDA or XML content using Discharge Guard AI (more generalized version)."""
|
204 |
|
205 |
+
prompt_text = f"""{system_instructions} \n\n Analyze the following medical XML/CDA content to provide a **structured and comprehensive patient data analysis**, similar to how a medical professional would review a patient's chart or a clinical document. You need to parse the XML structure yourself to extract the relevant information. Use bullet points, tables, or numbered steps for complex tasks. Provide a "Medical Document Analysis" report.
|
|
|
206 |
**Instructions for Discharge Guard AI:**
|
|
|
207 |
1. **Parse the XML content above.** Understand the XML structure to identify sections that are relevant to clinical information. For CDA specifically, look for sections like Problems, Medications, Allergies, Encounters, Results, and Vital Signs. For generic medical XML, adapt based on the tags present.
|
208 |
2. **Extract and Summarize Key Medical Information:** Focus on extracting the following information if present in the XML:
|
209 |
* **Patient Demographics Summary:** (If available, summarize demographic details)
|
210 |
... (rest of your prompt_text for CDA/XML analysis) ...
|
211 |
* Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the extracted data in a clinically relevant way based on the XML/CDA content.
|
|
|
212 |
"""
|
213 |
|
214 |
trace_data_detail_cda_xml_analysis = {
|
|
|
225 |
}
|
226 |
|
227 |
try:
|
228 |
+
response = client.chat.completions.create(
|
229 |
+
model=model_name,
|
230 |
+
messages=[{"role": "user", "content": prompt_text}],
|
231 |
+
temperature=0.4,
|
232 |
+
max_tokens=1024, # Adjust as needed
|
233 |
+
top_p=0.9,
|
234 |
+
)
|
235 |
+
the_response = response.choices[0].message.content
|
236 |
return the_response, trace_data_detail_cda_xml_analysis
|
237 |
|
238 |
except Exception as e:
|
|
|
244 |
def analyze_pdf_file_with_ai(pdf_file_path): # Modified to accept file path
|
245 |
"""Analyzes PDF file content using Discharge Guard AI."""
|
246 |
try:
|
247 |
+
with open(pdf_file_path.name, 'rb') as f: # Open file in binary mode for PdfReader, access file through .name for Gradio UploadedFile
|
248 |
pdf_file = f # Pass file object to PdfReader
|
249 |
pdf_reader = PdfReader(pdf_file)
|
250 |
text_content = ""
|
|
|
267 |
|
268 |
def analyze_pdf_content_ai(pdf_text_content): # Copied from your code
|
269 |
"""Analyzes PDF text content using Discharge Guard AI."""
|
270 |
+
prompt_text = f"""{system_instructions} \n\n Analyze the following medical PDF text content to provide a **structured summary and identify key clinical information**. Focus on patient demographics, medical history, findings, diagnoses, medications, recommendations, and any important clinical details conveyed in the document. Provide a "Medical Report Analysis" report.
|
|
|
271 |
**Medical PDF Text Content:**
|
272 |
```text
|
273 |
{pdf_text_content}
|
274 |
```
|
|
|
|
|
275 |
* Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the extracted data in a clinically relevant way based on the PDF content.
|
276 |
"""
|
277 |
|
|
|
289 |
}
|
290 |
|
291 |
try:
|
292 |
+
response = client.chat.completions.create(
|
293 |
+
model=model_name,
|
294 |
+
messages=[{"role": "user", "content": prompt_text}],
|
295 |
+
temperature=0.4,
|
296 |
+
max_tokens=1024, # Adjust as needed
|
297 |
+
top_p=0.9,
|
298 |
+
)
|
299 |
+
the_response = response.choices[0].message.content
|
300 |
return the_response, trace_data_detail_pdf_analysis
|
301 |
|
302 |
except Exception as e:
|
|
|
308 |
def analyze_csv_file_with_ai(csv_file_path): # Modified to accept file path
|
309 |
"""Analyzes CSV file content using Discharge Guard AI."""
|
310 |
try:
|
311 |
+
csv_content = csv_file_path.read().decode('utf-8') # Read content directly from UploadedFile
|
|
|
312 |
prediction_response, trace_data_csv_ai = analyze_csv_content_ai(csv_content)
|
313 |
|
314 |
if prediction_response:
|
|
|
325 |
|
326 |
def analyze_csv_content_ai(csv_content_string): # Copied from your code
|
327 |
"""Analyzes CSV content (string) using Discharge Guard AI."""
|
328 |
+
prompt_text = f"""{system_instructions} \n\n Analyze the following medical CSV data to provide a **structured summary and identify potential clinical insights**. Assume the CSV represents patient-related medical data. Focus on understanding the columns, summarizing key data points, identifying trends or patterns, and noting any potential clinical significance of the data. Provide a "Data Analysis" report.
|
|
|
329 |
**Medical CSV Data:**
|
330 |
```csv
|
331 |
{csv_content_string}
|
332 |
```
|
|
|
|
|
333 |
* Remember, this analysis is for conceptual informational purposes only and **NOT medical advice.** Focus on summarizing and structuring the data in a clinically relevant way based on the CSV content.
|
334 |
"""
|
335 |
|
|
|
347 |
}
|
348 |
|
349 |
try:
|
350 |
+
response = client.chat.completions.create(
|
351 |
+
model=model_name,
|
352 |
+
messages=[{"role": "user", "content": prompt_text}],
|
353 |
+
temperature=0.4,
|
354 |
+
max_tokens=1024, # Adjust as needed
|
355 |
+
top_p=0.9,
|
356 |
+
)
|
357 |
+
the_response = response.choices[0].message.content
|
358 |
return the_response, trace_data_detail_csv_analysis
|
359 |
|
360 |
except Exception as e:
|
|
|
612 |
"physician": "Dr. Provider" # Mock data
|
613 |
}
|
614 |
|
615 |
+
# Mock LLM-generated content - This part needs to be replaced with actual AI generation if desired for MeldRx PDF
|
616 |
llm_content = {
|
617 |
+
"diagnosis": "Diagnosis information would be generated by AI based on patient data from MeldRx.",
|
618 |
+
"treatment": "Treatment summary would be generated by AI based on patient data from MeldRx.",
|
619 |
+
"medications": "Medication list would be generated by AI based on patient data from MeldRx.",
|
620 |
+
"follow_up": "Follow-up instructions would be generated by AI based on patient data from MeldRx.",
|
621 |
+
"special_instructions": "Special instructions would be generated by AI based on patient data from MeldRx."
|
622 |
}
|
623 |
|
624 |
+
# Create discharge summary - Using No-AI PDF generation for now, replace with AI-content generation later
|
625 |
output_dir = tempfile.mkdtemp()
|
626 |
+
pdf_path = generate_discharge_summary(patient_info, llm_content, output_dir) # Still using No-AI template
|
627 |
|
628 |
+
return pdf_path, "PDF generated successfully (No AI Content in PDF yet)" # Indicate No-AI content
|
629 |
|
630 |
except Exception as e:
|
631 |
return None, f"Error generating PDF: {str(e)}"
|
632 |
|
633 |
def generate_discharge_paper_one_click():
|
634 |
+
"""One-click function to fetch patient data and generate discharge paper with AI Content."""
|
635 |
patient_data_str = CALLBACK_MANAGER.get_patient_data()
|
636 |
if patient_data_str.startswith("Not authenticated") or patient_data_str.startswith("Failed") or patient_data_str.startswith("Error"):
|
637 |
return None, patient_data_str # Return error message if authentication or data fetch fails
|
638 |
|
639 |
try:
|
640 |
patient_data = json.loads(patient_data_str)
|
641 |
+
|
642 |
+
# --- AI Content Generation for Discharge Summary ---
|
643 |
+
# This is a placeholder - Replace with actual AI call using InferenceClient and patient_data to generate content
|
644 |
+
ai_generated_content = generate_ai_discharge_content(patient_data) # Placeholder AI function
|
645 |
+
|
646 |
+
if not ai_generated_content:
|
647 |
+
return None, "Error: AI content generation failed."
|
648 |
+
|
649 |
+
# --- PDF Generation with AI Content ---
|
650 |
+
pdf_path, status_message = generate_pdf_from_meldrx_with_ai_content(patient_data, ai_generated_content) # Function to generate PDF with AI content
|
651 |
+
|
652 |
if pdf_path:
|
653 |
return pdf_path, status_message
|
654 |
else:
|
655 |
return None, status_message # Return status message if PDF generation fails
|
656 |
+
|
657 |
except json.JSONDecodeError:
|
658 |
return None, "Error: Patient data is not in valid JSON format."
|
659 |
except Exception as e:
|
660 |
return None, f"Error during discharge paper generation: {str(e)}"
|
661 |
|
662 |
+
def generate_ai_discharge_content(patient_data):
|
663 |
+
"""Placeholder function to generate AI content for discharge summary.
|
664 |
+
Replace this with actual AI call using InferenceClient and patient_data."""
|
665 |
+
try:
|
666 |
+
patient_name = f"{patient_data['entry'][0]['resource']['name'][0]['given'][0]} {patient_data['entry'][0]['resource']['name'][0]['family']}" if patient_data.get('entry') else "Unknown Patient"
|
667 |
+
prompt_text = f"""{system_instructions}\n\nGenerate a discharge summary content (diagnosis, treatment, medications, follow-up instructions, special instructions) for patient: {patient_name}. Base the content on available patient data (if any provided, currently not provided in detail in this mock-up). Focus on creating clinically relevant and informative summary. Remember this is for informational purposes and NOT medical advice."""
|
668 |
+
|
669 |
+
response = client.chat.completions.create(
|
670 |
+
model=model_name,
|
671 |
+
messages=[{"role": "user", "content": prompt_text}],
|
672 |
+
temperature=0.6, # Adjust temperature as needed for content generation
|
673 |
+
max_tokens=1024, # Adjust max_tokens as needed
|
674 |
+
top_p=0.9,
|
675 |
+
)
|
676 |
+
ai_content = response.choices[0].message.content
|
677 |
+
|
678 |
+
# Basic parsing of AI content - improve this based on desired output structure from LLM
|
679 |
+
llm_content = {
|
680 |
+
"diagnosis": "AI Generated Diagnosis (Placeholder):\n" + extract_section(ai_content, "Diagnosis"), # Example extraction - refine based on LLM output
|
681 |
+
"treatment": "AI Generated Treatment (Placeholder):\n" + extract_section(ai_content, "Treatment"),
|
682 |
+
"medications": "AI Generated Medications (Placeholder):\n" + extract_section(ai_content, "Medications"),
|
683 |
+
"follow_up": "AI Generated Follow-up (Placeholder):\n" + extract_section(ai_content, "Follow-up Instructions"),
|
684 |
+
"special_instructions": "AI Generated Special Instructions (Placeholder):\n" + extract_section(ai_content, "Special Instructions")
|
685 |
+
}
|
686 |
+
return llm_content
|
687 |
+
|
688 |
+
except Exception as e:
|
689 |
+
logger.error(f"Error generating AI discharge content: {e}")
|
690 |
+
return None
|
691 |
+
|
692 |
+
def extract_section(ai_content, section_title):
|
693 |
+
"""Simple placeholder function to extract section from AI content.
|
694 |
+
Improve this with more robust parsing based on LLM output format."""
|
695 |
+
start_marker = f"**{section_title}:**"
|
696 |
+
end_marker = "\n\n" # Adjust based on typical LLM output structure
|
697 |
+
start_index = ai_content.find(start_marker)
|
698 |
+
if start_index != -1:
|
699 |
+
start_index += len(start_marker)
|
700 |
+
end_index = ai_content.find(end_marker, start_index)
|
701 |
+
if end_index != -1:
|
702 |
+
return ai_content[start_index:end_index].strip()
|
703 |
+
return "Not found in AI output."
|
704 |
+
|
705 |
+
|
706 |
+
def generate_pdf_from_meldrx_with_ai_content(patient_data, llm_content):
|
707 |
+
"""Generate a PDF using patient data from MeldRx and AI-generated content."""
|
708 |
+
if isinstance(patient_data, str):
|
709 |
+
try:
|
710 |
+
patient_data = json.loads(patient_data)
|
711 |
+
except:
|
712 |
+
return None, "Invalid patient data format"
|
713 |
+
|
714 |
+
if not patient_data:
|
715 |
+
return None, "No patient data available"
|
716 |
+
|
717 |
+
try:
|
718 |
+
if isinstance(patient_data, list) and len(patient_data):
|
719 |
+
patient = patient_data[0]
|
720 |
+
else:
|
721 |
+
patient = patient_data
|
722 |
+
|
723 |
+
patient_info = {
|
724 |
+
"name": f"{patient.get('name', {}).get('given', [''])[0]} {patient.get('name', {}).get('family', '')}",
|
725 |
+
"dob": patient.get('birthDate', 'Unknown'),
|
726 |
+
"patient_id": patient.get('id', 'Unknown'),
|
727 |
+
"admission_date": datetime.now().strftime("%Y-%m-%d"), # Mock data
|
728 |
+
"physician": "Dr. AI Provider" # Mock data - Indicate AI generated
|
729 |
+
}
|
730 |
+
|
731 |
+
|
732 |
+
output_dir = tempfile.mkdtemp()
|
733 |
+
pdf_path = generate_discharge_summary(patient_info, llm_content, output_dir) # Using AI content now
|
734 |
+
|
735 |
+
return pdf_path, "PDF generated successfully with AI Content" # Indicate AI content
|
736 |
+
|
737 |
+
except Exception as e:
|
738 |
+
return None, f"Error generating PDF with AI content: {str(e)}"
|
739 |
|
740 |
|
741 |
# Create a simplified interface to avoid complex component interactions
|
|
|
759 |
patient_data_button = gr.Button("Fetch Patient Data")
|
760 |
patient_data_output = gr.Textbox(label="Patient Data", lines=10)
|
761 |
|
762 |
+
# Add button to generate PDF from MeldRx data (No AI)
|
763 |
meldrx_pdf_button = gr.Button("Generate PDF from MeldRx Data (No AI)") # Renamed button
|
764 |
meldrx_pdf_status = gr.Textbox(label="PDF Generation Status (No AI)") # Renamed status
|
765 |
meldrx_pdf_download = gr.File(label="Download Generated PDF (No AI)") # Renamed download
|
|
|
920 |
ccd_file = gr.File(file_types=['.ccd'], label="Upload CCD File (.ccd)") # Redundant, as CCDA also handles .ccd, but kept for clarity
|
921 |
ccd_ai_output = gr.Textbox(label="CCD Analysis Report", lines=5) # Redundant
|
922 |
analyze_ccd_button = gr.Button("Analyze CCD with AI") # Redundant
|
923 |
+
pdf_file = gr.File(file_types=['.pdf'], label="Upload PDF File (.pdf)")
|
924 |
+
pdf_ai_output = gr.Textbox(label="PDF Analysis Report", lines=5)
|
925 |
+
analyze_pdf_button = gr.Button("Analyze PDF with AI")
|
926 |
+
|
927 |
+
csv_file = gr.File(file_types=['.csv'], label="Upload CSV File (.csv)")
|
928 |
+
csv_ai_output = gr.Textbox(label="CSV Analysis Report", lines=5)
|
929 |
+
analyze_csv_button = gr.Button("Analyze CSV with AI")
|
930 |
|
931 |
|
932 |
# Connect AI Analysis Buttons - using REAL AI functions now
|
|
|
950 |
analyze_cda_xml_file_with_ai, # Call REAL AI function
|
951 |
inputs=ccd_file, outputs=ccd_ai_output
|
952 |
)
|
953 |
+
analyze_pdf_button.click(
|
954 |
+
analyze_pdf_file_with_ai,
|
955 |
+
inputs=pdf_file,
|
956 |
+
outputs=pdf_ai_output
|
957 |
+
)
|
958 |
+
analyze_csv_button.click(
|
959 |
+
analyze_csv_file_with_ai,
|
960 |
+
inputs=csv_file,
|
961 |
+
outputs=csv_ai_output
|
962 |
+
)
|
963 |
+
|
964 |
|
965 |
with gr.Tab("One-Click Discharge Paper (AI)"): # New Tab for One-Click Discharge Paper with AI
|
966 |
gr.Markdown("## One-Click Medical Discharge Paper Generation with AI Content") # Updated title
|
|
|
969 |
one_click_ai_pdf_download = gr.File(label="Download Discharge Paper (AI)") # Updated download label
|
970 |
|
971 |
one_click_ai_pdf_button.click(
|
972 |
+
generate_discharge_paper_one_click, # Use the one-click function that now calls AI
|
973 |
inputs=[],
|
974 |
outputs=[one_click_ai_pdf_download, one_click_ai_pdf_status]
|
975 |
)
|
|
|
989 |
outputs=dashboard_output
|
990 |
)
|
991 |
|
992 |
+
# Corrected the button click function name here to `generate_pdf_from_meldrx` (No AI PDF)
|
993 |
meldrx_pdf_button.click(
|
994 |
+
fn=generate_pdf_from_meldrx,
|
995 |
inputs=patient_data_output,
|
996 |
outputs=[meldrx_pdf_download, meldrx_pdf_status]
|
997 |
)
|