from utils import chatbot_prompt, report_prompt from lab_logic import analyze_lab_json from rag_engine import match_disease import gradio as gr import os import json from huggingface_hub import InferenceClient # ЁЯФР Load HF Token token = os.getenv("HF_TOKEN") if token is None: raise ValueError("HF_TOKEN not found in environment variables") # ЁЯФе Create client once client = InferenceClient( model="Intelligent-Internet/II-Medical-8B", provider="featherless-ai", token=token, timeout=120 ) # ========================= # ЁЯФе LLM CALL # ========================= def call_model(prompt, system_instruction, max_tokens=300): try: response = client.chat_completion( messages=[ {"role": "system", "content": system_instruction}, {"role": "user", "content": prompt} ], max_tokens=max_tokens, temperature=0.02 ) text = "" if response and response.choices: msg = response.choices[0].message # normal response if hasattr(msg, "content") and msg.content: text = msg.content # fallback (featherless models) elif hasattr(msg, "reasoning") and msg.reasoning: text = msg.reasoning if not text: print("MODEL RESPONSE EMPTY:", response) return "" text = text.replace("", "").replace("", "").strip() return text except Exception as e: print("MODEL ERROR:", e) return clean_response(text) def clean_response(text): if not text: return "" # remove reasoning style sentences lines = text.split("\n") filtered = [] for line in lines: line_lower = line.lower() if line_lower.startswith("okay"): continue if "the user" in line_lower: continue if "let's" in line_lower: continue if "i need to" in line_lower: continue filtered.append(line) return " ".join(filtered).strip() # ========================= # ЁЯй║ SYMPTOM CHECKER # ========================= def run_symptom(symptoms): if not symptoms.strip(): return "Please enter symptoms." symptoms_lower = symptoms.lower() emergency_keywords = [ "chest pain", "severe chest pain", "breathing difficulty", "shortness of breath", "unable to breathe", "unconscious", "fainting", "loss of consciousness", "severe bleeding", "blood vomiting", "vomiting blood", "stroke", "paralysis", "heart attack", "seizure", "fits" ] if any(k in symptoms_lower for k in emergency_keywords): return """тЪая╕П Possible Medical Emergency Detected Immediate medical attention is required. Please go to the nearest hospital. тЪая╕П рд╕рдВрднрд╛рд╡рд┐рдд рдЖрдкрд╛рддрдХрд╛рд▓реАрди рд╕реНрдерд┐рддрд┐ рддреБрд░рдВрдд рдЪрд┐рдХрд┐рддреНрд╕рд╛ рд╕рд╣рд╛рдпрддрд╛ рд▓реЗрдВред рдирд┐рдХрдЯрддрдо рдЕрд╕реНрдкрддрд╛рд▓ рдЬрд╛рдПрдБред """ extraction_prompt = f""" Extract key medical symptoms from the sentence. Return only comma separated symptoms. Input: {symptoms} """ key_symptoms = call_model( extraction_prompt, system_instruction="Return only symptoms separated by comma. No explanation.", max_tokens=40 ) if not key_symptoms: key_symptoms = symptoms matches = match_disease(key_symptoms) if not matches: return "No matching condition found." unique = {} for m in matches: disease = m["disease"] score = m["score"] if disease not in unique or score > unique[disease]: unique[disease] = score sorted_matches = sorted(unique.items(), key=lambda x: x[1], reverse=True) top3 = sorted_matches[:3] output = "Top Possible Conditions:\n\n" for i, (disease, score) in enumerate(top3, start=1): output += f"{i}. {disease} тАФ {score}%\n" main_disease = top3[0][0] output += "\nEnglish Summary:\n" output += ( f"Your symptoms ({key_symptoms}) most closely match {main_disease}. " "Other possible conditions are listed above. " "If symptoms continue or worsen, consult a healthcare professional.\n" ) output += "\nHindi Summary:\n" output += ( f"рдЖрдкрдХреЗ рд▓рдХреНрд╖рдг ({key_symptoms}) рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ {main_disease} рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред " "рдКрдкрд░ рдЕрдиреНрдп рд╕рдВрднрд╛рд╡рд┐рдд рд╕реНрдерд┐рддрд┐рдпрд╛рдБ рднреА рджрд┐рдЦрд╛рдИ рдЧрдИ рд╣реИрдВред " "рдпрджрд┐ рд▓рдХреНрд╖рдг рдмрдиреЗ рд░рд╣рддреЗ рд╣реИрдВ рдпрд╛ рдмрдврд╝рддреЗ рд╣реИрдВ рддреЛ рдбреЙрдХреНрдЯрд░ рд╕реЗ рд╕рд▓рд╛рд╣ рд▓реЗрдВред" ) return output # ========================= # ЁЯУД REPORT ANALYZER # ========================= def run_report(report_json_text): if not report_json_text.strip(): return "No report data received." try: report_json = json.loads(report_json_text) except: return "Invalid JSON format." if "report_info" not in report_json: return "Invalid report structure." abnormal = analyze_lab_json(report_json) if not abnormal: return "All parameters are within normal range." patient_name = report_json.get("patient_info", {}).get("name", "Patient") prompt = report_prompt(patient_name, abnormal) result = call_model( prompt, system_instruction="Follow format exactly. No extra text.", max_tokens=300 ) if not result: return "Unable to analyze report right now." return result # ========================= # ЁЯТм CHATBOT # ========================= def run_chat(message): if not message.strip(): return "Please enter your question." prompt = chatbot_prompt(message) result = call_model( prompt, system_instruction="Respond like a medical doctor giving short advice.", max_tokens=120 ) if not result: return "AI could not generate a response." return result # ========================= # ЁЯОи UI # ========================= with gr.Blocks(fill_height=True) as demo: gr.Markdown("# ЁЯй║ Sehat Smartcare AI") with gr.Tabs(): with gr.Tab("Symptom Checker"): symptom_input = gr.Textbox(label="Enter your symptoms") symptom_btn = gr.Button("Analyze") symptom_output = gr.Textbox(label="Result", lines=18) symptom_btn.click(run_symptom, symptom_input, symptom_output) with gr.Tab("Report Analyzer (JSON Input)"): report_input = gr.Textbox(label="Paste Structured JSON Report", lines=15) report_btn = gr.Button("Analyze Report") report_output = gr.Textbox(label="Clinical Summary", lines=12) report_btn.click(run_report, report_input, report_output) with gr.Tab("Medical Chatbot"): chat_input = gr.Textbox(label="Ask your health question", lines=4) chat_btn = gr.Button("Send") chat_output = gr.Textbox(label="Response", lines=8) chat_btn.click(run_chat, chat_input, chat_output) demo.launch()