Update app.py
Browse files
app.py
CHANGED
|
@@ -15,7 +15,6 @@ import requests
|
|
| 15 |
import json
|
| 16 |
import base64
|
| 17 |
import tempfile
|
| 18 |
-
from groq import Groq
|
| 19 |
|
| 20 |
# Set page config first
|
| 21 |
st.set_page_config(
|
|
@@ -100,55 +99,93 @@ def init_session_state():
|
|
| 100 |
st.session_state.risk_scores = {}
|
| 101 |
if 'chat_history' not in st.session_state:
|
| 102 |
st.session_state.chat_history = []
|
| 103 |
-
if '
|
| 104 |
-
st.session_state.
|
| 105 |
|
| 106 |
# Load trained models
|
| 107 |
@st.cache_resource(show_spinner=False)
|
| 108 |
def load_models():
|
| 109 |
try:
|
| 110 |
-
#
|
| 111 |
-
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
models['diabetes'] = diabetes_model
|
| 126 |
-
except:
|
| 127 |
-
st.error("❌ Diabetes model not found. Please ensure 'diabetes_model.pkl' is in the directory.")
|
| 128 |
-
return None, None, None
|
| 129 |
|
| 130 |
-
#
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
st.
|
| 136 |
-
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
-
return
|
| 139 |
|
| 140 |
except Exception as e:
|
| 141 |
st.error(f"❌ Error loading models: {str(e)}")
|
| 142 |
-
|
|
|
|
| 143 |
|
| 144 |
-
#
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
|
| 153 |
# Urdu translations
|
| 154 |
URDU_TRANSLATIONS = {
|
|
@@ -262,57 +299,86 @@ class OCRProcessor:
|
|
| 262 |
return min(95, accuracy) # Cap at 95% for realistic estimates
|
| 263 |
|
| 264 |
class HealthcareChatbot:
|
| 265 |
-
def __init__(self, groq_client):
|
| 266 |
self.client = groq_client
|
| 267 |
self.system_prompt = """You are a helpful and professional healthcare assistant designed for Pakistani patients.
|
| 268 |
Provide accurate, culturally appropriate medical advice in both English and Urdu.
|
| 269 |
Focus on preventive care, symptom explanation, and when to seek medical attention.
|
| 270 |
Always emphasize that you are an AI assistant and recommend consulting healthcare professionals for serious conditions."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
|
| 272 |
def get_response(self, query, language='English'):
|
| 273 |
-
"""Generate healthcare chatbot response using Groq API"""
|
| 274 |
try:
|
| 275 |
if self.client is None:
|
| 276 |
-
return
|
| 277 |
|
| 278 |
# Enhanced system prompt based on language
|
| 279 |
enhanced_system_prompt = self.system_prompt
|
| 280 |
if language == 'Urdu':
|
| 281 |
-
enhanced_system_prompt += " Respond in Urdu with proper medical terminology."
|
| 282 |
else:
|
| 283 |
-
enhanced_system_prompt += " Respond in English with clear medical advice."
|
| 284 |
|
| 285 |
# Create conversation context
|
| 286 |
messages = [
|
| 287 |
{"role": "system", "content": enhanced_system_prompt},
|
| 288 |
-
{"role": "user", "content":
|
| 289 |
]
|
| 290 |
|
| 291 |
-
# Generate response using Groq
|
| 292 |
-
|
| 293 |
messages=messages,
|
| 294 |
-
model="llama3-8b-8192",
|
| 295 |
temperature=0.3,
|
| 296 |
-
max_tokens=512
|
| 297 |
-
top_p=0.9
|
| 298 |
)
|
| 299 |
|
| 300 |
-
|
| 301 |
|
| 302 |
# Add disclaimer
|
| 303 |
if language == 'Urdu':
|
| 304 |
-
|
| 305 |
else:
|
| 306 |
-
|
| 307 |
|
| 308 |
-
return
|
| 309 |
|
| 310 |
except Exception as e:
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
|
| 317 |
def calculate_priority_score(heart_risk, diabetes_risk, hypertension_risk):
|
| 318 |
"""Calculate integrated priority score with clinical weighting"""
|
|
@@ -358,10 +424,48 @@ def validate_patient_data(age, bp_systolic, bp_diastolic, heart_rate):
|
|
| 358 |
|
| 359 |
return errors
|
| 360 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
def prepare_features_for_models(age, bp_systolic, bp_diastolic, heart_rate, cholesterol, glucose, bmi, symptoms):
|
| 362 |
"""Prepare feature arrays for different models based on their training requirements"""
|
| 363 |
|
| 364 |
-
# Heart Disease Model Features
|
| 365 |
heart_features = np.array([[
|
| 366 |
age,
|
| 367 |
bp_systolic,
|
|
@@ -421,16 +525,16 @@ def main():
|
|
| 421 |
st.markdown("---")
|
| 422 |
st.subheader("API Configuration")
|
| 423 |
groq_api_key = st.text_input("Enter Groq API Key:", type="password",
|
|
|
|
| 424 |
help="Get your API key from https://console.groq.com")
|
| 425 |
|
| 426 |
if groq_api_key:
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
chatbot = HealthcareChatbot(st.session_state.groq_client)
|
| 432 |
else:
|
| 433 |
-
st.warning("⚠️ Please enter Groq API key to enable chatbot")
|
| 434 |
chatbot = HealthcareChatbot(None)
|
| 435 |
|
| 436 |
language = st.radio(
|
|
@@ -508,7 +612,7 @@ def main():
|
|
| 508 |
help="Systolic blood pressure in mmHg")
|
| 509 |
bp_diastolic = st.number_input("Blood Pressure (diastolic)",
|
| 510 |
min_value=40, max_value=150, value=80,
|
| 511 |
-
|
| 512 |
heart_rate = st.number_input("Heart Rate (bpm)",
|
| 513 |
min_value=30, max_value=200, value=72,
|
| 514 |
help="Heart beats per minute")
|
|
@@ -573,8 +677,6 @@ def main():
|
|
| 573 |
if validation_errors:
|
| 574 |
for error in validation_errors:
|
| 575 |
st.error(f"❌ {error}")
|
| 576 |
-
elif heart_model is None or diabetes_model is None or hypertension_model is None:
|
| 577 |
-
st.error("❌ AI models are not loaded properly. Please check model files.")
|
| 578 |
else:
|
| 579 |
try:
|
| 580 |
with st.spinner("🔍 Analyzing patient data and calculating risks..."):
|
|
@@ -588,15 +690,21 @@ def main():
|
|
| 588 |
'blurred_vision': 1 if blurred_vision else 0
|
| 589 |
}
|
| 590 |
|
| 591 |
-
#
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 600 |
|
| 601 |
# Apply symptom modifiers for clinical severity
|
| 602 |
if chest_pain:
|
|
@@ -704,7 +812,6 @@ def main():
|
|
| 704 |
|
| 705 |
except Exception as e:
|
| 706 |
st.error(f"❌ Error in risk assessment: {str(e)}")
|
| 707 |
-
st.info("💡 Please ensure all model files are properly formatted and compatible.")
|
| 708 |
|
| 709 |
with tab2:
|
| 710 |
# Prescription OCR
|
|
@@ -784,70 +891,67 @@ def main():
|
|
| 784 |
st.header("💬 ہیلتھ کیئر اسسٹنٹ چیٹ بوٹ")
|
| 785 |
st.write("صحت سے متعلق سوالات پوچھیں اور انگریزی یا اردو میں ذاتی مشورہ حاصل کریں")
|
| 786 |
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
-
):
|
| 804 |
-
# Add user message to chat history
|
| 805 |
-
st.session_state.chat_history.append({"role": "user", "content": prompt})
|
| 806 |
-
|
| 807 |
-
# Generate bot response
|
| 808 |
-
with st.chat_message("assistant"):
|
| 809 |
-
with st.spinner("💭 Analyzing your question..." if language == "English" else "💭 آپ کا سوال تجزیہ ہو رہا ہے..."):
|
| 810 |
-
response = chatbot.get_response(prompt, language)
|
| 811 |
-
st.markdown(f"**🤖 Healthcare Assistant:**\n\n{response}")
|
| 812 |
-
|
| 813 |
-
# Add assistant response to chat history
|
| 814 |
-
st.session_state.chat_history.append({"role": "assistant", "content": response})
|
| 815 |
-
|
| 816 |
-
# Limit chat history to last 10 messages
|
| 817 |
-
if len(st.session_state.chat_history) > 10:
|
| 818 |
-
st.session_state.chat_history = st.session_state.chat_history[-10:]
|
| 819 |
|
| 820 |
-
#
|
| 821 |
-
|
| 822 |
-
st.
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
| 829 |
-
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
|
| 834 |
-
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
|
| 848 |
-
|
| 849 |
-
|
| 850 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 851 |
|
| 852 |
with tab4:
|
| 853 |
# Analytics Dashboard
|
|
|
|
| 15 |
import json
|
| 16 |
import base64
|
| 17 |
import tempfile
|
|
|
|
| 18 |
|
| 19 |
# Set page config first
|
| 20 |
st.set_page_config(
|
|
|
|
| 99 |
st.session_state.risk_scores = {}
|
| 100 |
if 'chat_history' not in st.session_state:
|
| 101 |
st.session_state.chat_history = []
|
| 102 |
+
if 'groq_api_key' not in st.session_state:
|
| 103 |
+
st.session_state.groq_api_key = ""
|
| 104 |
|
| 105 |
# Load trained models
|
| 106 |
@st.cache_resource(show_spinner=False)
|
| 107 |
def load_models():
|
| 108 |
try:
|
| 109 |
+
# Try to load models with multiple possible file extensions
|
| 110 |
+
model_files = {
|
| 111 |
+
'heart': [
|
| 112 |
+
'heart_disease_model.pkl', 'heart_model.pkl', 'heart_disease_model.joblib',
|
| 113 |
+
'models/heart_disease_model.pkl', 'models/heart_model.pkl'
|
| 114 |
+
],
|
| 115 |
+
'diabetes': [
|
| 116 |
+
'diabetes_model.pkl', 'diabetes_model.joblib',
|
| 117 |
+
'models/diabetes_model.pkl', 'models/diabetes_model.joblib'
|
| 118 |
+
],
|
| 119 |
+
'hypertension': [
|
| 120 |
+
'hypertension_model.pkl', 'hypertension_model.joblib',
|
| 121 |
+
'models/hypertension_model.pkl', 'models/hypertension_model.joblib'
|
| 122 |
+
]
|
| 123 |
+
}
|
| 124 |
|
| 125 |
+
def find_and_load_model(file_list, model_name):
|
| 126 |
+
for file_path in file_list:
|
| 127 |
+
if os.path.exists(file_path):
|
| 128 |
+
try:
|
| 129 |
+
if file_path.endswith('.pkl'):
|
| 130 |
+
return joblib.load(file_path)
|
| 131 |
+
elif file_path.endswith('.joblib'):
|
| 132 |
+
return joblib.load(file_path)
|
| 133 |
+
except Exception as e:
|
| 134 |
+
st.warning(f"Warning loading {model_name} from {file_path}: {str(e)}")
|
| 135 |
+
continue
|
| 136 |
+
return None
|
| 137 |
|
| 138 |
+
heart_model = find_and_load_model(model_files['heart'], "Heart Disease")
|
| 139 |
+
diabetes_model = find_and_load_model(model_files['diabetes'], "Diabetes")
|
| 140 |
+
hypertension_model = find_and_load_model(model_files['hypertension'], "Hypertension")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
+
# If no models found, create simple rule-based models as fallback
|
| 143 |
+
if heart_model is None:
|
| 144 |
+
st.info("🔍 Using rule-based heart disease assessment")
|
| 145 |
+
heart_model = "rule_based"
|
| 146 |
+
if diabetes_model is None:
|
| 147 |
+
st.info("🔍 Using rule-based diabetes assessment")
|
| 148 |
+
diabetes_model = "rule_based"
|
| 149 |
+
if hypertension_model is None:
|
| 150 |
+
st.info("🔍 Using rule-based hypertension assessment")
|
| 151 |
+
hypertension_model = "rule_based"
|
| 152 |
|
| 153 |
+
return heart_model, diabetes_model, hypertension_model
|
| 154 |
|
| 155 |
except Exception as e:
|
| 156 |
st.error(f"❌ Error loading models: {str(e)}")
|
| 157 |
+
# Return rule-based fallback
|
| 158 |
+
return "rule_based", "rule_based", "rule_based"
|
| 159 |
|
| 160 |
+
# Groq API client using direct HTTP requests
|
| 161 |
+
class GroqClient:
|
| 162 |
+
def __init__(self, api_key):
|
| 163 |
+
self.api_key = api_key
|
| 164 |
+
self.base_url = "https://api.groq.com/openai/v1"
|
| 165 |
+
self.headers = {
|
| 166 |
+
"Authorization": f"Bearer {api_key}",
|
| 167 |
+
"Content-Type": "application/json"
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
def chat_completions_create(self, messages, model="llama3-8b-8192", temperature=0.3, max_tokens=512):
|
| 171 |
+
try:
|
| 172 |
+
url = f"{self.base_url}/chat/completions"
|
| 173 |
+
data = {
|
| 174 |
+
"messages": messages,
|
| 175 |
+
"model": model,
|
| 176 |
+
"temperature": temperature,
|
| 177 |
+
"max_tokens": max_tokens,
|
| 178 |
+
"top_p": 0.9
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
response = requests.post(url, headers=self.headers, json=data, timeout=30)
|
| 182 |
+
response.raise_for_status()
|
| 183 |
+
|
| 184 |
+
result = response.json()
|
| 185 |
+
return result
|
| 186 |
+
|
| 187 |
+
except Exception as e:
|
| 188 |
+
raise Exception(f"Groq API error: {str(e)}")
|
| 189 |
|
| 190 |
# Urdu translations
|
| 191 |
URDU_TRANSLATIONS = {
|
|
|
|
| 299 |
return min(95, accuracy) # Cap at 95% for realistic estimates
|
| 300 |
|
| 301 |
class HealthcareChatbot:
|
| 302 |
+
def __init__(self, groq_client=None):
|
| 303 |
self.client = groq_client
|
| 304 |
self.system_prompt = """You are a helpful and professional healthcare assistant designed for Pakistani patients.
|
| 305 |
Provide accurate, culturally appropriate medical advice in both English and Urdu.
|
| 306 |
Focus on preventive care, symptom explanation, and when to seek medical attention.
|
| 307 |
Always emphasize that you are an AI assistant and recommend consulting healthcare professionals for serious conditions."""
|
| 308 |
+
|
| 309 |
+
# Fallback responses in case API is not available
|
| 310 |
+
self.fallback_responses = {
|
| 311 |
+
'heart': {
|
| 312 |
+
'English': "**Heart Health Tips:**\n\n• Maintain a healthy diet low in saturated fats\n• Exercise regularly for 30 minutes daily\n• Monitor blood pressure regularly\n• Avoid smoking and limit alcohol\n• Manage stress through relaxation techniques\n\n⚠️ For chest pain or severe symptoms, seek immediate medical attention.",
|
| 313 |
+
'Urdu': "**دل کی صحت کے نکات:**\n\n• سیر شدہ چکنائی سے پاک صحت مند غذا کھائیں\n• روزانہ 30 منٹ باقاعدگی سے ورزش کریں\n• بلڈ پریشر کو باقاعدگی سے چیک کریں\n• تمباکو نوشی سے پرہیز کریں\n• آرام کی تکنیکوں کے ذریعے تناؤ کا انتظام کریں\n\n⚠️ سینے میں درد یا شدید علامات کی صورت میں فوری طبی امداد حاصل کریں۔"
|
| 314 |
+
},
|
| 315 |
+
'diabetes': {
|
| 316 |
+
'English': "**Diabetes Management Tips:**\n\n• Monitor blood sugar levels regularly\n• Follow a balanced diet with controlled carbs\n• Take medications as prescribed\n• Stay physically active\n• Get regular eye and foot checkups\n\n⚠️ Consult your doctor for personalized diabetes management.",
|
| 317 |
+
'Urdu': "**ذیابیطس کے انتظام کے نکات:**\n\n• خون میں شکر کی سطح کو باقاعدگی سے چیک کریں\n• کنٹرول کاربوہائیڈریٹ کے ساتھ متوازن غذا کھائیں\n• دوائیں ڈاکٹر کے مشورے کے مطابق لیں\n• جسمانی طور پر متحرک رہیں\n• آنکھوں اور پاؤں کی باقاعدہ جانچ کروائیں\n\n⚠️ ذاتی نوعیت کے ذیابیطس کے انتظام کے لیے اپنے ڈاکٹر سے مشورہ کریں۔"
|
| 318 |
+
},
|
| 319 |
+
'hypertension': {
|
| 320 |
+
'English': "**Blood Pressure Management:**\n\n• Reduce salt intake to less than 5g daily\n• Practice stress management techniques\n• Maintain healthy body weight\n• Limit caffeine and alcohol\n• Take prescribed medications consistently\n\n⚠️ Regularly monitor your blood pressure readings.",
|
| 321 |
+
'Urdu': "**بلڈ پریشر کے انتظام کے نکات:**\n\n• روزانہ نمک کی مقدار 5 گرام سے کم رکھیں\n• تناؤ کے انتظام کی تکنیکیں اپنائیں\n• صحت مند جسمانی وزن برقرار رکھیں\n• کیفین اور الکحل کو محدود کریں\n• تجویز کردہ دوائیں مسلسل لیں\n\n⚠️ اپنے بلڈ پریشر کی پیمائش کو باقاعدگی سے مانیٹر کریں۔"
|
| 322 |
+
},
|
| 323 |
+
'general': {
|
| 324 |
+
'English': "**General Health Tips:**\n\n• Get 7-9 hours of quality sleep each night\n• Stay hydrated by drinking 8-10 glasses of water daily\n• Practice good hygiene and regular hand washing\n• Get regular health check-ups and screenings\n• Maintain a positive outlook and social connections\n\n⚠️ For specific health concerns, consult a healthcare professional.",
|
| 325 |
+
'Urdu': "**عام صحت کے نکات:**\n\n• ہر رات 7-9 گھنٹے کی معیاری نیند لیں\n• روزانہ 8-10 گلاس پانی پی کر ہائیڈریٹ رہیں\n• اچھی حفظان صحت اور باقاعدہ ہاتھ دھونے کی مشق کریں\n• باقاعدہ صحت کی جانچ اور اسکریننگ کروائیں\n• مثبت نقطہ نظر اور سماجی رابطے برقرار رکھیں\n\n⚠️ مخصوص صحت کے مسائل کے لیے ہیلتھ کیئر پروفیشنل سے مشورہ کریں۔"
|
| 326 |
+
}
|
| 327 |
+
}
|
| 328 |
|
| 329 |
def get_response(self, query, language='English'):
|
| 330 |
+
"""Generate healthcare chatbot response using Groq API or fallback"""
|
| 331 |
try:
|
| 332 |
if self.client is None:
|
| 333 |
+
return self._get_fallback_response(query, language)
|
| 334 |
|
| 335 |
# Enhanced system prompt based on language
|
| 336 |
enhanced_system_prompt = self.system_prompt
|
| 337 |
if language == 'Urdu':
|
| 338 |
+
enhanced_system_prompt += " Respond in Urdu with proper medical terminology and cultural sensitivity."
|
| 339 |
else:
|
| 340 |
+
enhanced_system_prompt += " Respond in English with clear, professional medical advice."
|
| 341 |
|
| 342 |
# Create conversation context
|
| 343 |
messages = [
|
| 344 |
{"role": "system", "content": enhanced_system_prompt},
|
| 345 |
+
{"role": "user", "content": query}
|
| 346 |
]
|
| 347 |
|
| 348 |
+
# Generate response using Groq API
|
| 349 |
+
response = self.client.chat_completions_create(
|
| 350 |
messages=messages,
|
| 351 |
+
model="llama3-8b-8192",
|
| 352 |
temperature=0.3,
|
| 353 |
+
max_tokens=512
|
|
|
|
| 354 |
)
|
| 355 |
|
| 356 |
+
bot_response = response['choices'][0]['message']['content']
|
| 357 |
|
| 358 |
# Add disclaimer
|
| 359 |
if language == 'Urdu':
|
| 360 |
+
bot_response += "\n\n⚠️ براہ کرم نوٹ کریں: یہ ایک AI اسسٹنٹ ہے۔ سنگین طبی حالات کے لیے ہمیشہ کوالیفائیڈ ڈاکٹر سے مشورہ کریں۔"
|
| 361 |
else:
|
| 362 |
+
bot_response += "\n\n⚠️ Please note: This is an AI assistant. Always consult qualified doctors for serious medical conditions."
|
| 363 |
|
| 364 |
+
return bot_response
|
| 365 |
|
| 366 |
except Exception as e:
|
| 367 |
+
st.error(f"Chatbot error: {str(e)}")
|
| 368 |
+
return self._get_fallback_response(query, language)
|
| 369 |
+
|
| 370 |
+
def _get_fallback_response(self, query, language):
|
| 371 |
+
"""Provide fallback responses when API is unavailable"""
|
| 372 |
+
query_lower = query.lower()
|
| 373 |
+
|
| 374 |
+
if any(word in query_lower for word in ['heart', 'cardiac', 'chest pain', 'cholesterol']):
|
| 375 |
+
return self.fallback_responses['heart'][language]
|
| 376 |
+
elif any(word in query_lower for word in ['diabetes', 'sugar', 'glucose', 'insulin']):
|
| 377 |
+
return self.fallback_responses['diabetes'][language]
|
| 378 |
+
elif any(word in query_lower for word in ['blood pressure', 'hypertension', 'bp']):
|
| 379 |
+
return self.fallback_responses['hypertension'][language]
|
| 380 |
+
else:
|
| 381 |
+
return self.fallback_responses['general'][language]
|
| 382 |
|
| 383 |
def calculate_priority_score(heart_risk, diabetes_risk, hypertension_risk):
|
| 384 |
"""Calculate integrated priority score with clinical weighting"""
|
|
|
|
| 424 |
|
| 425 |
return errors
|
| 426 |
|
| 427 |
+
def predict_risk_rule_based(age, bp_systolic, bp_diastolic, cholesterol, glucose, bmi, symptoms):
|
| 428 |
+
"""Rule-based risk prediction as fallback when models are not available"""
|
| 429 |
+
|
| 430 |
+
# Heart disease risk calculation
|
| 431 |
+
heart_risk = 0.0
|
| 432 |
+
heart_risk += min(0.3, (age - 30) / 200) # Age factor
|
| 433 |
+
heart_risk += min(0.2, (bp_systolic - 120) / 300) # BP factor
|
| 434 |
+
heart_risk += min(0.2, (cholesterol - 150) / 500) # Cholesterol factor
|
| 435 |
+
heart_risk += min(0.3, (bmi - 20) / 50) # BMI factor
|
| 436 |
+
if symptoms['chest_pain']:
|
| 437 |
+
heart_risk += 0.3
|
| 438 |
+
if symptoms['shortness_breath']:
|
| 439 |
+
heart_risk += 0.2
|
| 440 |
+
if symptoms['palpitations']:
|
| 441 |
+
heart_risk += 0.1
|
| 442 |
+
|
| 443 |
+
# Diabetes risk calculation
|
| 444 |
+
diabetes_risk = 0.0
|
| 445 |
+
diabetes_risk += min(0.3, (age - 30) / 200)
|
| 446 |
+
diabetes_risk += min(0.4, (glucose - 80) / 300)
|
| 447 |
+
diabetes_risk += min(0.3, (bmi - 20) / 50)
|
| 448 |
+
if symptoms['fatigue']:
|
| 449 |
+
diabetes_risk += 0.2
|
| 450 |
+
if symptoms['blurred_vision']:
|
| 451 |
+
diabetes_risk += 0.1
|
| 452 |
+
|
| 453 |
+
# Hypertension risk calculation
|
| 454 |
+
hypertension_risk = 0.0
|
| 455 |
+
hypertension_risk += min(0.3, (age - 30) / 200)
|
| 456 |
+
hypertension_risk += min(0.4, (bp_systolic - 120) / 200)
|
| 457 |
+
hypertension_risk += min(0.3, (bmi - 20) / 50)
|
| 458 |
+
if symptoms['dizziness']:
|
| 459 |
+
hypertension_risk += 0.2
|
| 460 |
+
if symptoms['palpitations']:
|
| 461 |
+
hypertension_risk += 0.1
|
| 462 |
+
|
| 463 |
+
return min(1.0, heart_risk), min(1.0, diabetes_risk), min(1.0, hypertension_risk)
|
| 464 |
+
|
| 465 |
def prepare_features_for_models(age, bp_systolic, bp_diastolic, heart_rate, cholesterol, glucose, bmi, symptoms):
|
| 466 |
"""Prepare feature arrays for different models based on their training requirements"""
|
| 467 |
|
| 468 |
+
# Heart Disease Model Features
|
| 469 |
heart_features = np.array([[
|
| 470 |
age,
|
| 471 |
bp_systolic,
|
|
|
|
| 525 |
st.markdown("---")
|
| 526 |
st.subheader("API Configuration")
|
| 527 |
groq_api_key = st.text_input("Enter Groq API Key:", type="password",
|
| 528 |
+
value=st.session_state.groq_api_key,
|
| 529 |
help="Get your API key from https://console.groq.com")
|
| 530 |
|
| 531 |
if groq_api_key:
|
| 532 |
+
st.session_state.groq_api_key = groq_api_key
|
| 533 |
+
groq_client = GroqClient(groq_api_key)
|
| 534 |
+
chatbot = HealthcareChatbot(groq_client)
|
| 535 |
+
st.success("✅ Groq API configured successfully!")
|
|
|
|
| 536 |
else:
|
| 537 |
+
st.warning("⚠️ Please enter Groq API key to enable advanced chatbot")
|
| 538 |
chatbot = HealthcareChatbot(None)
|
| 539 |
|
| 540 |
language = st.radio(
|
|
|
|
| 612 |
help="Systolic blood pressure in mmHg")
|
| 613 |
bp_diastolic = st.number_input("Blood Pressure (diastolic)",
|
| 614 |
min_value=40, max_value=150, value=80,
|
| 615 |
+
help="Diastolic blood pressure in mmHg")
|
| 616 |
heart_rate = st.number_input("Heart Rate (bpm)",
|
| 617 |
min_value=30, max_value=200, value=72,
|
| 618 |
help="Heart beats per minute")
|
|
|
|
| 677 |
if validation_errors:
|
| 678 |
for error in validation_errors:
|
| 679 |
st.error(f"❌ {error}")
|
|
|
|
|
|
|
| 680 |
else:
|
| 681 |
try:
|
| 682 |
with st.spinner("🔍 Analyzing patient data and calculating risks..."):
|
|
|
|
| 690 |
'blurred_vision': 1 if blurred_vision else 0
|
| 691 |
}
|
| 692 |
|
| 693 |
+
# Get predictions based on available models
|
| 694 |
+
if heart_model != "rule_based" and diabetes_model != "rule_based" and hypertension_model != "rule_based":
|
| 695 |
+
# Use trained models
|
| 696 |
+
heart_features, diabetes_features, hypertension_features = prepare_features_for_models(
|
| 697 |
+
age, bp_systolic, bp_diastolic, heart_rate, cholesterol, glucose, bmi, symptoms_dict
|
| 698 |
+
)
|
| 699 |
+
|
| 700 |
+
heart_risk_proba = heart_model.predict_proba(heart_features)[0][1]
|
| 701 |
+
diabetes_risk_proba = diabetes_model.predict_proba(diabetes_features)[0][1]
|
| 702 |
+
hypertension_risk_proba = hypertension_model.predict_proba(hypertension_features)[0][1]
|
| 703 |
+
else:
|
| 704 |
+
# Use rule-based prediction
|
| 705 |
+
heart_risk_proba, diabetes_risk_proba, hypertension_risk_proba = predict_risk_rule_based(
|
| 706 |
+
age, bp_systolic, bp_diastolic, cholesterol, glucose, bmi, symptoms_dict
|
| 707 |
+
)
|
| 708 |
|
| 709 |
# Apply symptom modifiers for clinical severity
|
| 710 |
if chest_pain:
|
|
|
|
| 812 |
|
| 813 |
except Exception as e:
|
| 814 |
st.error(f"❌ Error in risk assessment: {str(e)}")
|
|
|
|
| 815 |
|
| 816 |
with tab2:
|
| 817 |
# Prescription OCR
|
|
|
|
| 891 |
st.header("💬 ہیلتھ کیئر اسسٹنٹ چیٹ بوٹ")
|
| 892 |
st.write("صحت سے متعلق سوالات پوچھیں اور انگریزی یا اردو میں ذاتی مشورہ حاصل کریں")
|
| 893 |
|
| 894 |
+
# Display chat history
|
| 895 |
+
for message in st.session_state.chat_history:
|
| 896 |
+
with st.chat_message(message["role"]):
|
| 897 |
+
if message["role"] == "user":
|
| 898 |
+
st.markdown(message["content"])
|
| 899 |
+
else:
|
| 900 |
+
# Format bot response with better styling
|
| 901 |
+
st.markdown(f"**🤖 Healthcare Assistant:**\n\n{message['content']}")
|
| 902 |
+
|
| 903 |
+
# Chat input
|
| 904 |
+
if prompt := st.chat_input(
|
| 905 |
+
"Type your health question here..." if language == "English"
|
| 906 |
+
else "اپنا صحت کا سوال یہاں ٹائپ کریں..."
|
| 907 |
+
):
|
| 908 |
+
# Add user message to chat history
|
| 909 |
+
st.session_state.chat_history.append({"role": "user", "content": prompt})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 910 |
|
| 911 |
+
# Generate bot response
|
| 912 |
+
with st.chat_message("assistant"):
|
| 913 |
+
with st.spinner("💭 Analyzing your question..." if language == "English" else "💭 آپ کا سوال تجزیہ ہو رہا ہے..."):
|
| 914 |
+
response = chatbot.get_response(prompt, language)
|
| 915 |
+
st.markdown(f"**🤖 Healthcare Assistant:**\n\n{response}")
|
| 916 |
+
|
| 917 |
+
# Add assistant response to chat history
|
| 918 |
+
st.session_state.chat_history.append({"role": "assistant", "content": response})
|
| 919 |
+
|
| 920 |
+
# Limit chat history to last 10 messages
|
| 921 |
+
if len(st.session_state.chat_history) > 10:
|
| 922 |
+
st.session_state.chat_history = st.session_state.chat_history[-10:]
|
| 923 |
+
|
| 924 |
+
# Quick action buttons
|
| 925 |
+
if language == "English":
|
| 926 |
+
st.subheader("Quick Health Topics")
|
| 927 |
+
else:
|
| 928 |
+
st.subheader("فوری صحت کے موضوعات")
|
| 929 |
+
|
| 930 |
+
col_qa1, col_qa2, col_qa3 = st.columns(3)
|
| 931 |
+
|
| 932 |
+
with col_qa1:
|
| 933 |
+
if st.button("❤️ Heart Health", use_container_width=True):
|
| 934 |
+
st.session_state.chat_history.append({
|
| 935 |
+
"role": "user",
|
| 936 |
+
"content": "Tell me about heart health and prevention tips"
|
| 937 |
+
})
|
| 938 |
+
st.rerun()
|
| 939 |
+
|
| 940 |
+
with col_qa2:
|
| 941 |
+
if st.button("🩺 Diabetes", use_container_width=True):
|
| 942 |
+
st.session_state.chat_history.append({
|
| 943 |
+
"role": "user",
|
| 944 |
+
"content": "What are the symptoms and management of diabetes?"
|
| 945 |
+
})
|
| 946 |
+
st.rerun()
|
| 947 |
+
|
| 948 |
+
with col_qa3:
|
| 949 |
+
if st.button("💓 Blood Pressure", use_container_width=True):
|
| 950 |
+
st.session_state.chat_history.append({
|
| 951 |
+
"role": "user",
|
| 952 |
+
"content": "How to control high blood pressure naturally?"
|
| 953 |
+
})
|
| 954 |
+
st.rerun()
|
| 955 |
|
| 956 |
with tab4:
|
| 957 |
# Analytics Dashboard
|