Tufan1/CVD-Predictor-Probablity
0
1import streamlit as st2import torch3from transformers import AutoTokenizer, AutoModelForSequenceClassification4import re5from peft import PeftModel6from pydub import AudioSegment7import speech_recognition as sr8import io9from audio_recorder_streamlit import audio_recorder10 11# Load model and tokenizer from local fine-tuned directory12BASE_MODEL = "stanford-crfm/BioMedLM" #Huggingface13ADAPTER_ID = "Tufan1/BioMedLM-Cardio-Classifier-Fold1"14tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)15tokenizer.pad_token = tokenizer.eos_token16 17 18# Load base model as a sequence classification model19base_model = AutoModelForSequenceClassification.from_pretrained(20 BASE_MODEL,21 torch_dtype="float32",22 num_labels=1,23 low_cpu_mem_usage=True,24 device_map="cpu"25)26 27model = PeftModel.from_pretrained(28 base_model,29 ADAPTER_ID,30 device_map="cpu",31 adapter_name="cardio_adapter"32)33tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)34if tokenizer.pad_token is None:35 tokenizer.pad_token = tokenizer.eos_token36# Dictionaries to decode user inputs37gender_map = {1: "Female", 2: "Male"}38cholesterol_map = {1: "Normal", 2: "Elevated", 3: "Peak"}39glucose_map = {1: "Normal", 2: "High", 3: "Extreme"}40binary_map = {0: "No", 1: "Yes"}41 42def get_prediction(age, gender, height, weight, ap_hi, ap_lo,43 cholesterol, glucose, smoke, alco, active):44 input_text = f"""Patient Record:45- Age: {age} years46- Gender: {gender_map[gender]}47- Height: {height} cm48- Weight: {weight} kg49- Systolic BP: {ap_hi} mmHg50- Diastolic BP: {ap_lo} mmHg51- Cholesterol Level: {cholesterol_map[cholesterol]}52- Glucose Level: {glucose_map[glucose]}53- Smokes: {binary_map[smoke]}54- Alcohol Intake: {binary_map[alco]}55- Physically Active: {binary_map[active]}"""56 57 inputs = tokenizer(input_text, return_tensors="pt", padding=True, truncation=True).to("cpu")58 model.eval()59 with torch.no_grad():60 outputs = model(**inputs)61 logits = outputs.logits.squeeze().item()62 prob = torch.sigmoid(torch.tensor(logits)).item()63 64 diagnosis = f"CVD Probability: {prob:.2%} โ {'๐ Cardiovascular Disease Detected' if prob > 0.7 else 'โ
No Cardiovascular Disease'}"65 return diagnosis66 67def extract_details_from_text(text):68 age = int(re.search(r'(\d+)\s*year', text).group(1)) if re.search(r'(\d+)\s*year', text) else None69 gender = 2 if "man" in text.lower() else (1 if "female" in text.lower() else None)70 height = int(re.search(r'(\d+)\s*cm', text).group(1)) if re.search(r'(\d+)\s*cm', text) else None71 weight = int(re.search(r'(\d+)\s*kg', text).group(1)) if re.search(r'(\d+)\s*kg', text) else None72 bp_match = re.search(r'BP\s*(\d+)[/](\d+)', text)73 ap_hi, ap_lo = (int(bp_match.group(1)), int(bp_match.group(2))) if bp_match else (None, None)74 cholesterol = 3 if "peak" in text.lower() else 2 if "elevated" in text.lower() else 175 glucose = 3 if "extreme" in text.lower() else 2 if "high" in text.lower() else 176 smoke = 1 if "smoke" in text.lower() else 077 alco = 1 if "alcohol" in text.lower() else 078 active = 1 if "exercise" in text.lower() or "active" in text.lower() else 079 return age, gender, height, weight, ap_hi, ap_lo, cholesterol, glucose, smoke, alco, active80 81st.set_page_config(page_title="Cardiovascular Disease Predictor", layout="centered")82st.title("๐ซ Cardiovascular Disease Predictor (LLM Powered)")83st.markdown("This tool uses a fine-tuned BioMedLM model to predict cardiovascular conditions from structured, text, or voice input.")84 85input_mode = st.radio("Choose input method:", ["Manual Input", "Text Phrase", "Audio Upload"])86 87if input_mode == "Manual Input":88 age = st.number_input("Age (years)", min_value=1, max_value=120)89 gender = st.selectbox("Gender", [("Female", 1), ("Male", 2)], format_func=lambda x: x[0])[1]90 height = st.number_input("Height (cm)", min_value=50, max_value=250)91 weight = st.number_input("Weight (kg)", min_value=10, max_value=200)92 ap_hi = st.number_input("Systolic BP", min_value=80, max_value=250)93 ap_lo = st.number_input("Diastolic BP", min_value=40, max_value=150)94 cholesterol = st.selectbox("Cholesterol", [("Normal", 1), ("Elevated", 2), ("Peak", 3)], format_func=lambda x: x[0])[1]95 glucose = st.selectbox("Glucose", [("Normal", 1), ("High", 2), ("Extreme", 3)], format_func=lambda x: x[0])[1]96 smoke = st.radio("Smoker?", [("No", 0), ("Yes", 1)], format_func=lambda x: x[0])[1]97 alco = st.radio("Alcohol Intake?", [("No", 0), ("Yes", 1)], format_func=lambda x: x[0])[1]98 active = st.radio("Physically Active?", [("No", 0), ("Yes", 1)], format_func=lambda x: x[0])[1]99 100 if st.button("Predict Diagnosis"):101 diagnosis = get_prediction(age, gender, height, weight, ap_hi, ap_lo,102 cholesterol, glucose, smoke, alco, active)103 st.success(f"๐ฉบ **{diagnosis}**")104 105elif input_mode == "Text Phrase":106 phrase = st.text_area("Enter patient details in natural language:", height=200)107 if st.button("Extract & Predict"):108 try:109 values = extract_details_from_text(phrase)110 if all(v is not None for v in values):111 diagnosis = get_prediction(*values)112 st.success(f"๐ฉบ **{diagnosis}**")113 else:114 st.warning("Couldn't extract all fields from the text. Please revise.")115 except Exception as e:116 st.error(f"Error: {e}")117 118elif input_mode == "Audio Upload":119 audio_input_mode = st.radio("Choose audio input type:", ["Upload Audio File", "Record Audio"])120 121 if audio_input_mode == "Upload Audio File":122 uploaded_file = st.file_uploader("Upload audio file (WAV, MP3, M4A, MPEG)", type=["wav", "mp3", "m4a", "mpeg"])123 124 if uploaded_file:125 st.audio(uploaded_file, format='audio/wav')126 audio = AudioSegment.from_file(uploaded_file)127 if audio and len(audio) > 0:128 wav_io = io.BytesIO()129 audio.export(wav_io, format="wav")130 wav_io.seek(0)131 132 recognizer = sr.Recognizer()133 with sr.AudioFile(wav_io) as source:134 audio_data = recognizer.record(source)135 136 try:137 text = recognizer.recognize_google(audio_data)138 st.markdown(f"**Transcribed Text:** _{text}_")139 values = extract_details_from_text(text)140 if all(v is not None for v in values):141 diagnosis = get_prediction(*values)142 st.success(f"๐ฉบ **{diagnosis}**")143 else:144 st.warning("Could not extract complete information from audio.")145 except Exception as e:146 st.error(f"Audio processing error: {e}")147 else:148 st.error("Uploaded audio file is empty or not valid.")149 150 elif audio_input_mode == "Record Audio":151 audio = audio_recorder("Click to record", "Recording...")152 153 if audio and len(audio) > 0:154 st.audio(audio, format="audio/wav")155 wav_io = io.BytesIO(audio)156 157 recognizer = sr.Recognizer()158 with sr.AudioFile(wav_io) as source:159 audio_data = recognizer.record(source)160 161 try:162 text = recognizer.recognize_google(audio_data)163 st.markdown(f"**Transcribed Text:** _{text}_")164 values = extract_details_from_text(text)165 if all(v is not None for v in values):166 diagnosis = get_prediction(*values)167 st.success(f"๐ฉบ **{diagnosis}**")168 else:169 st.warning("Could not extract complete information from recorded audio.")170 except Exception as e:171 st.error(f"Recording processing error: {e}")172 else:173 st.error("No audio recorded or audio is empty.")174 