Dina-Raslan's picture
Update app.py
8b5f678 verified
Raw
History Blame Contribute Delete
13.2 kB
import gradio as gr
import pickle
import numpy as np
import pandas as pd
import os
from groq import Groq
# ============================================================
# Load models and helper files
# ============================================================
# --- Diabetes ---
with open('models/diabetes_model.pkl', 'rb') as f:
diabetes_model = pickle.load(f)
with open('models/diabetes_columns.pkl', 'rb') as f:
diabetes_columns = pickle.load(f)
# --- CKD ---
with open('models/ckd_model.pkl', 'rb') as f:
ckd_model = pickle.load(f)
with open('models/ckd_scaler.pkl', 'rb') as f:
ckd_scaler = pickle.load(f)
# --- Heart ---
with open('models/heart_model.pkl', 'rb') as f:
heart_model = pickle.load(f)
with open('models/heart_scaler.pkl', 'rb') as f:
heart_scaler = pickle.load(f)
with open('models/heart_columns.pkl', 'rb') as f:
heart_columns = pickle.load(f)
with open('models/heart_encoding_maps.pkl', 'rb') as f:
heart_encoding_maps = pickle.load(f)
CKD_COLUMNS = ['age', 'bp', 'sg', 'al', 'su', 'rbc', 'pc', 'pcc', 'ba', 'bgr',
'bu', 'sc', 'sod', 'pot', 'hemo', 'pcv', 'wc', 'rc',
'htn', 'dm', 'cad', 'appet', 'pe', 'ane']
# ============================================================
# Groq client setup
# GROQ_API_KEY must be set as a secret in the Space settings
# ============================================================
groq_client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
SYSTEM_PROMPT = """You are a helpful medical information assistant embedded in a website
that predicts risk for Diabetes, Chronic Kidney Disease (CKD), and Heart Disease using
machine learning models. You can explain general medical information about these three
conditions, their symptoms, risk factors, and prevention, and explain how to use the site.
You are not a doctor and must never provide a diagnosis or replace professional medical advice.
If a user describes symptoms suggesting an emergency, advise them to seek immediate medical care.
Keep answers concise and clear."""
def risk_label(prob):
if prob < 0.3:
return "Low risk"
elif prob < 0.6:
return "Moderate risk"
else:
return "High risk"
def result_markdown(prob):
return (f"## {risk_label(prob)}\n\n"
f"### Risk score: {prob*100:.1f}%\n\n"
f"*This is a preliminary indicator, not a medical diagnosis. "
f"If the risk is high, please consult a doctor.*")
# ============================================================
# 1. Diabetes Prediction
# ============================================================
def predict_diabetes(gender, age, hypertension, heart_disease, smoking_history, bmi, hba1c, glucose):
row = {
'age': age,
'hypertension': 1 if hypertension == "Yes" else 0,
'heart_disease': 1 if heart_disease == "Yes" else 0,
'bmi': bmi,
'HbA1c_level': hba1c,
'blood_glucose_level': glucose,
'gender_Male': 1 if gender == "Male" else 0,
'smoking_history_ever': 1 if smoking_history == "Ever" else 0,
'smoking_history_former': 1 if smoking_history == "Former" else 0,
'smoking_history_never': 1 if smoking_history == "Never" else 0,
'smoking_history_not current': 1 if smoking_history == "Not Current" else 0,
}
input_df = pd.DataFrame([row])[diabetes_columns]
prob = diabetes_model.predict_proba(input_df)[0][1]
return result_markdown(prob)
# ============================================================
# 2. CKD Prediction
# ============================================================
def predict_ckd(age, bp, sg, al, su, rbc, pc, pcc, ba, bgr, bu, sc, sod, pot,
hemo, pcv, wc, rc, htn, dm, cad, appet, pe, ane):
binary_map_normal = {"Normal": 1, "Abnormal": 0}
binary_map_present = {"Present": 1, "Not present": 0}
binary_map_yesno = {"Yes": 1, "No": 0}
binary_map_appet = {"Good": 1, "Poor": 0}
row = {
'age': age, 'bp': bp, 'sg': sg, 'al': al, 'su': su,
'rbc': binary_map_normal[rbc], 'pc': binary_map_normal[pc],
'pcc': binary_map_present[pcc], 'ba': binary_map_present[ba],
'bgr': bgr, 'bu': bu, 'sc': sc, 'sod': sod, 'pot': pot,
'hemo': hemo, 'pcv': pcv, 'wc': wc, 'rc': rc,
'htn': binary_map_yesno[htn], 'dm': binary_map_yesno[dm],
'cad': binary_map_yesno[cad], 'appet': binary_map_appet[appet],
'pe': binary_map_yesno[pe], 'ane': binary_map_yesno[ane],
}
input_df = pd.DataFrame([row])[CKD_COLUMNS]
input_scaled = ckd_scaler.transform(input_df)
prob = ckd_model.predict_proba(input_scaled)[0][1]
return result_markdown(prob)
# ============================================================
# 3. Heart Disease Prediction
# ============================================================
def predict_heart(age, sex, cp, trestbps, chol, fbs, restecg, thalch, exang, oldpeak, slope, thal):
row = {
'age': age,
'sex': heart_encoding_maps['sex'][sex],
'cp': heart_encoding_maps['cp'][cp],
'trestbps': trestbps,
'chol': chol,
'fbs': heart_encoding_maps['fbs'][fbs],
'restecg': heart_encoding_maps['restecg'][restecg],
'thalch': thalch,
'exang': heart_encoding_maps['exang'][exang],
'oldpeak': oldpeak,
'slope': heart_encoding_maps['slope'][slope],
'thal': heart_encoding_maps['thal'][thal],
}
input_df = pd.DataFrame([row])[heart_columns]
input_scaled = heart_scaler.transform(input_df)
prob = heart_model.predict_proba(input_scaled)[0][1]
return result_markdown(prob)
# ============================================================
# 4. Chatbot (Groq API)
# ============================================================
def chatbot_response(message, history):
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
for turn in history:
if isinstance(turn, dict):
messages.append({"role": turn["role"], "content": turn["content"]})
else:
user_msg, bot_msg = turn
messages.append({"role": "user", "content": user_msg})
if bot_msg:
messages.append({"role": "assistant", "content": bot_msg})
messages.append({"role": "user", "content": message})
try:
completion = groq_client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=messages,
temperature=0.5,
max_tokens=500,
)
return completion.choices[0].message.content
except Exception as e:
return f"Sorry, the assistant is temporarily unavailable. Error: {str(e)}"
# ============================================================
# Gradio UI
# ============================================================
with gr.Blocks(title="Medical Diagnosis Assistant") as demo:
gr.Markdown("# Medical Diagnosis Assistant")
gr.Markdown("A tool that estimates risk for three conditions based on your health data. "
"This tool does not replace professional medical advice.")
with gr.Tabs():
# ---------------- Diabetes Tab ----------------
with gr.Tab("Diabetes Check"):
with gr.Row():
with gr.Column():
d_gender = gr.Radio(["Male", "Female"], label="Gender", value="Male")
d_age = gr.Number(label="Age", value=30)
d_hyper = gr.Radio(["Yes", "No"], label="Hypertension", value="No")
d_heart = gr.Radio(["Yes", "No"], label="Heart Disease", value="No")
d_smoke = gr.Dropdown(
["Never", "Former", "Ever", "Not Current", "Current"],
label="Smoking History", value="Never")
d_bmi = gr.Number(label="BMI", value=25.0)
d_hba1c = gr.Number(label="HbA1c Level", value=5.5)
d_glucose = gr.Number(label="Blood Glucose Level", value=100)
d_btn = gr.Button("Predict", variant="primary")
with gr.Column():
d_output = gr.Markdown()
d_btn.click(predict_diabetes,
inputs=[d_gender, d_age, d_hyper, d_heart, d_smoke, d_bmi, d_hba1c, d_glucose],
outputs=d_output)
# ---------------- CKD Tab ----------------
with gr.Tab("CKD Check"):
with gr.Row():
with gr.Column():
c_age = gr.Number(label="Age", value=40)
c_bp = gr.Number(label="Blood Pressure", value=80)
c_sg = gr.Number(label="Specific Gravity", value=1.02)
c_al = gr.Number(label="Albumin", value=0)
c_su = gr.Number(label="Sugar", value=0)
c_rbc = gr.Radio(["Normal", "Abnormal"], label="Red Blood Cells", value="Normal")
c_pc = gr.Radio(["Normal", "Abnormal"], label="Pus Cell", value="Normal")
c_pcc = gr.Radio(["Present", "Not present"], label="Pus Cell Clumps", value="Not present")
c_ba = gr.Radio(["Present", "Not present"], label="Bacteria", value="Not present")
c_bgr = gr.Number(label="Blood Glucose Random", value=100)
c_bu = gr.Number(label="Blood Urea", value=30)
with gr.Column():
c_sc = gr.Number(label="Serum Creatinine", value=1.0)
c_sod = gr.Number(label="Sodium", value=140)
c_pot = gr.Number(label="Potassium", value=4.5)
c_hemo = gr.Number(label="Hemoglobin", value=14.0)
c_pcv = gr.Number(label="Packed Cell Volume", value=40)
c_wc = gr.Number(label="White Blood Cell Count", value=8000)
c_rc = gr.Number(label="Red Blood Cell Count", value=5.0)
c_htn = gr.Radio(["Yes", "No"], label="Hypertension", value="No")
c_dm = gr.Radio(["Yes", "No"], label="Diabetes Mellitus", value="No")
c_cad = gr.Radio(["Yes", "No"], label="Coronary Artery Disease", value="No")
c_appet = gr.Radio(["Good", "Poor"], label="Appetite", value="Good")
c_pe = gr.Radio(["Yes", "No"], label="Pedal Edema", value="No")
c_ane = gr.Radio(["Yes", "No"], label="Anemia", value="No")
c_btn = gr.Button("Predict", variant="primary")
c_output = gr.Markdown()
c_btn.click(predict_ckd,
inputs=[c_age, c_bp, c_sg, c_al, c_su, c_rbc, c_pc, c_pcc, c_ba, c_bgr,
c_bu, c_sc, c_sod, c_pot, c_hemo, c_pcv, c_wc, c_rc,
c_htn, c_dm, c_cad, c_appet, c_pe, c_ane],
outputs=c_output)
# ---------------- Heart Tab ----------------
with gr.Tab("Heart Disease Check"):
gr.Markdown("This check relies on clinical test values (ECG, imaging). "
"If you do not have these results, consult your doctor.")
with gr.Row():
with gr.Column():
h_age = gr.Number(label="Age", value=45)
h_sex = gr.Radio(["Male", "Female"], label="Sex", value="Male")
h_cp = gr.Dropdown(["typical angina", "atypical angina", "non-anginal", "asymptomatic"],
label="Chest Pain Type", value="non-anginal")
h_trestbps = gr.Number(label="Resting Blood Pressure", value=120)
h_chol = gr.Number(label="Cholesterol", value=200)
h_fbs = gr.Radio(["True", "False"], label="Fasting Blood Sugar > 120", value="False")
with gr.Column():
h_restecg = gr.Dropdown(["normal", "stt abnormality", "lv hypertrophy"],
label="Resting ECG Result", value="normal")
h_thalch = gr.Number(label="Max Heart Rate Achieved", value=150)
h_exang = gr.Radio(["True", "False"], label="Exercise Induced Angina", value="False")
h_oldpeak = gr.Number(label="ST Depression (oldpeak)", value=0.0)
h_slope = gr.Dropdown(["upsloping", "flat", "downsloping"], label="Slope of ST Segment", value="upsloping")
h_thal = gr.Dropdown(["normal", "fixed defect", "reversable defect"], label="Thalassemia", value="normal")
h_btn = gr.Button("Predict", variant="primary")
h_output = gr.Markdown()
h_btn.click(predict_heart,
inputs=[h_age, h_sex, h_cp, h_trestbps, h_chol, h_fbs, h_restecg,
h_thalch, h_exang, h_oldpeak, h_slope, h_thal],
outputs=h_output)
# ---------------- Chatbot Tab ----------------
with gr.Tab("Assistant"):
gr.ChatInterface(
fn=chatbot_response,
examples=["Tell me about diabetes", "Symptoms of heart disease", "How do I use this site"],
)
demo.launch()