lyimo commited on
Commit
3d4910d
·
verified ·
1 Parent(s): 94bdf93

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +234 -0
app.py ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import base64
3
+ import gradio as gr
4
+ import pandas as pd
5
+ from groq import Groq
6
+ from PIL import Image
7
+ import io
8
+
9
+ # Initialize Groq client
10
+ client = Groq(
11
+ api_key=os.environ.get("GROQ_API_KEY")
12
+ )
13
+
14
+ # Function to encode images to base64
15
+ def encode_image(image):
16
+ buffered = io.BytesIO()
17
+ image.save(buffered, format="JPEG")
18
+ return base64.b64encode(buffered.getvalue()).decode('utf-8')
19
+
20
+ # Extract ECG readings from image using Llama Vision model
21
+ def analyze_ecg_image(image, vision_model="llama-3.2-90b-vision-preview"):
22
+ if image is None:
23
+ return "No image provided."
24
+
25
+ # Convert to PIL Image if needed
26
+ if not isinstance(image, Image.Image):
27
+ image = Image.open(image)
28
+
29
+ # Encode the image
30
+ base64_image = encode_image(image)
31
+
32
+ # Create chat completion with vision model
33
+ vision_prompt = "Analyze this ECG image carefully. Extract and report all visible parameters, intervals, rhythm patterns, and any abnormalities. Report exact numerical values where visible. Format your response as a structured report with clear sections for different measurements and observations."
34
+
35
+ try:
36
+ vision_completion = client.chat.completions.create(
37
+ messages=[
38
+ {
39
+ "role": "user",
40
+ "content": [
41
+ {"type": "text", "text": vision_prompt},
42
+ {
43
+ "type": "image_url",
44
+ "image_url": {
45
+ "url": f"data:image/jpeg;base64,{base64_image}",
46
+ },
47
+ },
48
+ ],
49
+ }
50
+ ],
51
+ model=vision_model,
52
+ temperature=0.2, # Lower temperature for more factual responses
53
+ max_completion_tokens=1024,
54
+ )
55
+
56
+ ecg_analysis = vision_completion.choices[0].message.content
57
+ return ecg_analysis
58
+
59
+ except Exception as e:
60
+ return f"Error analyzing ECG image: {str(e)}"
61
+
62
+ # Generate medical assessment based on ECG readings and patient history
63
+ def generate_assessment(ecg_analysis, patient_history=None, chat_model="llama-3.3-70b-versatile"):
64
+ if not ecg_analysis or ecg_analysis.startswith("Error"):
65
+ return "Please analyze an ECG image first."
66
+
67
+ # Construct prompt based on available information
68
+ if patient_history:
69
+ prompt = f"""You are a highly trained cardiologist assistant. Based on the ECG analysis below and the patient's history, provide a comprehensive assessment of the patient's cardiac status. Indicate clearly if there are any concerning findings that require immediate medical attention.
70
+
71
+ ECG ANALYSIS:
72
+ {ecg_analysis}
73
+
74
+ PATIENT HISTORY:
75
+ {patient_history}
76
+
77
+ Provide your assessment in the following format:
78
+ 1. Summary of findings
79
+ 2. Key abnormalities (if any)
80
+ 3. Potential clinical implications
81
+ 4. Recommendation (including urgency level)
82
+ """
83
+ else:
84
+ prompt = f"""You are a highly trained cardiologist assistant. Based on the ECG analysis below, provide a comprehensive assessment of the patient's cardiac status. Indicate clearly if there are any concerning findings that require immediate medical attention.
85
+
86
+ ECG ANALYSIS:
87
+ {ecg_analysis}
88
+
89
+ Provide your assessment in the following format:
90
+ 1. Summary of findings
91
+ 2. Key abnormalities (if any)
92
+ 3. Potential clinical implications
93
+ 4. Recommendation (including urgency level)
94
+ """
95
+
96
+ try:
97
+ assessment_completion = client.chat.completions.create(
98
+ messages=[
99
+ {
100
+ "role": "system",
101
+ "content": "You are a medical AI assistant specialized in cardiology. Provide accurate, clinically relevant interpretations of ECG data. If there are concerning findings that might indicate a medical emergency, clearly highlight them. Avoid definitive diagnoses but provide reasoned medical assessments based on the data provided."
102
+ },
103
+ {
104
+ "role": "user",
105
+ "content": prompt
106
+ }
107
+ ],
108
+ model=chat_model,
109
+ temperature=0.2, # Lower temperature for more factual responses
110
+ max_completion_tokens=2048,
111
+ )
112
+
113
+ return assessment_completion.choices[0].message.content
114
+
115
+ except Exception as e:
116
+ return f"Error generating assessment: {str(e)}"
117
+
118
+ # Doctor's chat interaction with the model about the patient
119
+ def doctor_chat(message, chat_history, ecg_analysis, patient_history, chat_model="llama-3.3-70b-versatile"):
120
+ if not ecg_analysis or ecg_analysis.startswith("Error"):
121
+ return "Please analyze an ECG image first before starting a chat.", chat_history
122
+
123
+ # Prepare chat context
124
+ context = f"""ECG ANALYSIS:
125
+ {ecg_analysis}
126
+
127
+ """
128
+
129
+ if patient_history:
130
+ context += f"""PATIENT HISTORY:
131
+ {patient_history}
132
+
133
+ """
134
+
135
+ # Construct full chat history for context
136
+ messages = [
137
+ {
138
+ "role": "system",
139
+ "content": f"You are a medical AI assistant specialized in cardiology. You are helping a doctor interpret ECG results and patient data. Answer the doctor's questions based on the following information:\n\n{context}"
140
+ }
141
+ ]
142
+
143
+ # Add chat history to the context
144
+ for entry in chat_history:
145
+ messages.append({"role": "user", "content": entry[0]})
146
+ messages.append({"role": "assistant", "content": entry[1]})
147
+
148
+ # Add the current message
149
+ messages.append({"role": "user", "content": message})
150
+
151
+ try:
152
+ chat_completion = client.chat.completions.create(
153
+ messages=messages,
154
+ model=chat_model,
155
+ temperature=0.3,
156
+ max_completion_tokens=1024,
157
+ )
158
+
159
+ response = chat_completion.choices[0].message.content
160
+ chat_history.append((message, response))
161
+ return "", chat_history
162
+
163
+ except Exception as e:
164
+ error_message = f"Error in chat: {str(e)}"
165
+ chat_history.append((message, error_message))
166
+ return "", chat_history
167
+
168
+ # Create Gradio interface
169
+ with gr.Blocks(title="Cardiac ECG Analysis System") as app:
170
+ gr.Markdown("# Cardiac ECG Analysis System")
171
+ gr.Markdown("Upload an ECG image and optional patient history to get an automated analysis and assessment.")
172
+
173
+ with gr.Row():
174
+ with gr.Column(scale=1):
175
+ # Input components
176
+ ecg_image = gr.Image(type="pil", label="Upload ECG Image")
177
+ vision_model = gr.Dropdown(
178
+ choices=["llama-3.2-90b-vision-preview", "llama-3.2-11b-vision-preview"],
179
+ value="llama-3.2-90b-vision-preview",
180
+ label="Vision Model"
181
+ )
182
+ analyze_button = gr.Button("Analyze ECG Image")
183
+
184
+ patient_history = gr.Textbox(
185
+ lines=10,
186
+ label="Patient History (optional)",
187
+ placeholder="Enter patient's medical history, age, sex, symptoms, medications, etc."
188
+ )
189
+
190
+ chat_model = gr.Dropdown(
191
+ choices=["llama-3.3-70b-versatile", "llama-3.3-8b-versatile"],
192
+ value="llama-3.3-70b-versatile",
193
+ label="Chat Model"
194
+ )
195
+ assess_button = gr.Button("Generate Assessment")
196
+
197
+ with gr.Column(scale=1):
198
+ # Output components
199
+ ecg_analysis_output = gr.Textbox(label="ECG Analysis", lines=15)
200
+ assessment_output = gr.Textbox(label="Medical Assessment", lines=15)
201
+
202
+ gr.Markdown("## Doctor's Consultation")
203
+ gr.Markdown("Ask follow-up questions about the patient's ECG results and medical condition.")
204
+
205
+ chatbot = gr.Chatbot(label="Consultation")
206
+ message = gr.Textbox(
207
+ lines=2,
208
+ label="Doctor's Question",
209
+ placeholder="Ask a question about this patient's cardiac status..."
210
+ )
211
+ chat_button = gr.Button("Send")
212
+
213
+ # Set up event handlers
214
+ analyze_button.click(
215
+ analyze_ecg_image,
216
+ inputs=[ecg_image, vision_model],
217
+ outputs=ecg_analysis_output
218
+ )
219
+
220
+ assess_button.click(
221
+ generate_assessment,
222
+ inputs=[ecg_analysis_output, patient_history, chat_model],
223
+ outputs=assessment_output
224
+ )
225
+
226
+ chat_button.click(
227
+ doctor_chat,
228
+ inputs=[message, chatbot, ecg_analysis_output, patient_history, chat_model],
229
+ outputs=[message, chatbot]
230
+ )
231
+
232
+ # Launch the app
233
+ if __name__ == "__main__":
234
+ app.launch()