import torch.utils.data as _tud from pytorch_tabular.tabular_datamodule import TabularDatamodule from streamlit_option_menu import option_menu import google.generativeai as genai import os from deep_translator import GoogleTranslator translator = GoogleTranslator() genai.configure(api_key=os.getenv("GEMINI_API_KEY")) _OriginalDataLoader = _tud.DataLoader class SafeDataLoader(_OriginalDataLoader): def __init__(self, *args, **kwargs): kwargs.pop("batch_size", None) kwargs.pop("num_workers", None) super().__init__(*args, **kwargs) _tud.DataLoader = SafeDataLoader _old_prepare = TabularDatamodule.prepare_inference_dataloader def _patched_prepare(self, df): if not hasattr(self.config, "dataloader_kwargs"): self.config.dataloader_kwargs = {} return _old_prepare(self, df) TabularDatamodule.prepare_inference_dataloader = _patched_prepare import streamlit as st import pandas as pd import numpy as np import torch import json import pickle from pytorch_tabular import TabularModel from sklearn.preprocessing import LabelEncoder from omegaconf import OmegaConf, DictConfig from types import SimpleNamespace # Load model model = TabularModel.load_model("FTTransformerModel") dm = model.datamodule if hasattr(dm, "label_encoder") and isinstance(dm.label_encoder, LabelEncoder): dm.label_encoder = [dm.label_encoder] dm._inferred_config = SimpleNamespace(output_cardinality=[2]) # Load threshold with open("FTTransformerModel/threshold.json", "r") as f: threshold = json.load(f)["threshold"] # Sidebar: language selection with st.sidebar: lang = st.selectbox("🌐 Language / 語言 / Bahasa", ["English", "中文", "Malay"]) # Label dictionary for multilingual UI LABELS = { "user_type": {"English": "I am a...", "中文": "我的身份是...", "Malay": "Saya seorang..."}, "user_type_options": {"English": ["Patient", "Medical Professional"], "中文": ["病患", "醫護人員"], "Malay": ["Pesakit", "Profesional Perubatan"]}, "input_header": {"English": "Enter Health Info", "中文": "輸入健康資料", "Malay": "Masukkan Maklumat Kesihatan"}, "age": {"English": "Patient's Age", "中文": "年齡", "Malay": "Umur"}, "height": {"English": "Patient's Height (cm)", "中文": "身高 (cm)", "Malay": "Tinggi (cm)"}, "weight": {"English": "Patient's Weight (kg)", "中文": "體重 (kg)", "Malay": "Berat (kg)"}, "systolic": {"English": "Patient's Systolic BP", "中文": "收縮壓", "Malay": "Tekanan Sistolik"}, "diastolic": {"English": "Patient's Diastolic BP", "中文": "舒張壓", "Malay": "Tekanan Diastolik"}, "cholesterol": {"English": "Patient's Cholesterol", "中文": "膽固醇", "Malay": "Kolesterol"}, "gluc": {"English": "Patient's Glucose", "中文": "血糖", "Malay": "Glukosa"}, "gender": {"English": "Patient's Gender", "中文": "性別", "Malay": "Jantina"}, "smoke": {"English": "Do patient smoke?", "中文": "是否吸菸?", "Malay": "Adakah merokok?"}, "alco": {"English": "Do patient drink alcohol?", "中文": "是否喝酒?", "Malay": "Adakah minum alkohol?"}, "active": {"English": "Are patient physically active?", "中文": "是否有運動習慣?", "Malay": "Adakah aktif secara fizikal?"}, "predict": {"English": "Predict CVD Risk", "中文": "預測心血管風險", "Malay": "Ramalkan Risiko CVD"} } MENU = { "English": ["Prediction Tool", "Let's know more about CVD!"], "中文": ["預測工具", "了解更多心血管資訊"], "Malay": ["Alat Ramalan", "Ketahui lebih lanjut tentang CVD"] } chol_options = { "English": {0: "Normal", 1: "High", 2: "Very High"}, "中文": {0: "正常", 1: "偏高", 2: "非常高"}, "Malay": {0: "Normal", 1: "Tinggi", 2: "Sangat Tinggi"} } gluc_options = chol_options.copy() gender_options = { "English": {0: "Female", 1: "Male"}, "中文": {0: "女性", 1: "男性"}, "Malay": {0: "Perempuan", 1: "Lelaki"} } yn_options = { "English": {0: "No", 1: "Yes"}, "中文": {0: "否", 1: "是"}, "Malay": {0: "Tidak", 1: "Ya"} } # User input with st.sidebar: selected = option_menu( menu_title="Menu", options=MENU[lang], icons=["activity", "book"], menu_icon="cast", default_index=0, ) if selected == MENU[lang][0]: with st.sidebar: st.header(LABELS["input_header"][lang]) user_type = st.selectbox(LABELS["user_type"][lang], LABELS["user_type_options"][lang]) age = st.number_input(LABELS["age"][lang], min_value=18, max_value=100, value=50) height = st.number_input(LABELS["height"][lang], min_value=100, max_value=250, value=170) weight = st.number_input(LABELS["weight"][lang], min_value=30, max_value=200, value=70) systolic = st.number_input(LABELS["systolic"][lang], min_value=80, max_value=250, value=120) diastolic = st.number_input(LABELS["diastolic"][lang], min_value=40, max_value=150, value=80) cholesterol = st.selectbox(LABELS["cholesterol"][lang], [0, 1, 2], format_func=lambda x: chol_options[lang][x]) gluc = st.selectbox(LABELS["gluc"][lang], [0, 1, 2], format_func=lambda x: gluc_options[lang][x]) gender = st.selectbox(LABELS["gender"][lang], [0, 1], format_func=lambda x: gender_options[lang][x]) smoke = st.selectbox(LABELS["smoke"][lang], [0, 1], format_func=lambda x: yn_options[lang][x]) alco = st.selectbox(LABELS["alco"][lang], [0, 1], format_func=lambda x: yn_options[lang][x]) active = st.selectbox(LABELS["active"][lang], [0, 1], format_func=lambda x: yn_options[lang][x]) input_data = pd.DataFrame([{ "age": age * 365, "height": height, "weight": weight, "ap_hi": systolic, "ap_lo": diastolic, "cholesterol": cholesterol, "gluc": gluc, "gender": gender, "smoke": smoke, "alco": alco, "active": active }]) predict_clicked = st.button(LABELS["predict"][lang]) if predict_clicked: input_data["bmi"] = input_data["weight"] / ((input_data["height"]/100)**2) input_data["pulse_pressure"] = input_data["ap_hi"] - input_data["ap_lo"] input_data["hypertension"] = ((input_data["ap_hi"] > 140) | (input_data["ap_lo"] > 90)).astype(int) preds = model.predict(input_data) proba = preds["cardio_1_probability"].iloc[0] result = "❌ At Risk of CVD" if proba >= threshold else " ✅ Low Risk" with st.container(): st.markdown("### 🧬Prediction Result🧬") st.markdown(f"