Download app.py from aneesqumar/TyphoidGuardAI-Developed-By_ChinarAI: direct link, hf CLI and curl.
- Browser
- Download file 15.4 kB
-
https://huggingface.co/spaces/aneesqumar/TyphoidGuardAI-Developed-By_ChinarAI/resolve/main/app.py
- Command line
-
hf download hf://spaces/aneesqumar/TyphoidGuardAI-Developed-By_ChinarAI/app.py
-
curl -L -o app.py https://huggingface.co/spaces/aneesqumar/TyphoidGuardAI-Developed-By_ChinarAI/resolve/main/app.py
15.4 kB
| import gradio as gr | |
| import joblib | |
| import pandas as pd | |
| import os | |
| from groq import Groq | |
| from reportlab.platypus import ( | |
| SimpleDocTemplate, Paragraph, Spacer, | |
| Table, TableStyle, Image | |
| ) | |
| from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet | |
| from reportlab.lib import colors | |
| from reportlab.lib.units import inch | |
| # =============================== | |
| # LOAD MODEL | |
| # =============================== | |
| model = joblib.load("typhoidguard_model_reduced2.pkl") | |
| client = Groq(api_key=os.environ.get("GROQ_API_KEY")) | |
| last_llm_report = "" | |
| last_basic_data = {} | |
| LOGO_PATH = "logo1.png" # 🔹 Place your logo file in HF repo | |
| # =============================== | |
| # LLM FUNCTION | |
| # =============================== | |
| def generate_llm_report(patient_info, prob_pct, risk_label, recommendation, factors): | |
| prompt = f""" | |
| You are a responsible medical AI assistant helping rural healthcare units in Pakistan. | |
| Patient Details: | |
| {patient_info} | |
| Predicted Risk: {prob_pct}% | |
| Risk Category: {risk_label} | |
| Clinical Risk Factors: | |
| {", ".join(factors) if factors else "None"} | |
| Agent Recommendation: | |
| {recommendation} | |
| Generate structured sections: | |
| Clinical Interpretation | |
| Possible Complications | |
| Immediate Precautions | |
| Preventative Measures | |
| Follow-up Recommendations | |
| Keep headings clear. | |
| End with this line: "Remember, this advice is generated based on the provided information and should not replace the judgment of a qualified doctor. | |
| It is essential to consult a qualified doctor for personalized advice and treatment reminder to consult qualified doctor." | |
| """ | |
| response = client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.4, | |
| ) | |
| return response.choices[0].message.content | |
| # =============================== | |
| # BASIC PREDICTION | |
| # =============================== | |
| def predict_basic(name, age, gender, platelets, hb, duration, | |
| blood_bacteria, severity, medication): | |
| global last_basic_data, last_llm_report | |
| last_llm_report = "" | |
| data = pd.DataFrame([{ | |
| "Age": age, | |
| "Platelet Count": platelets, | |
| "Hemoglobin (g/dL)": hb, | |
| "Treatment Duration": duration, | |
| "Gender": gender, | |
| "Blood Culture Bacteria": blood_bacteria, | |
| "Symptoms Severity": severity, | |
| "Current Medication": medication | |
| }]) | |
| prob = model.predict_proba(data)[0][1] | |
| prob_pct = round(prob * 100, 2) | |
| low_platelets = platelets < 150000 | |
| low_hb = hb < 10 | |
| if low_platelets or low_hb: | |
| prob_pct = 90.0 | |
| risk_label = "HIGH RISK" | |
| color = "#b00020" | |
| recommendation = "Immediate referral to secondary care facility recommended." | |
| elif prob >= 0.65: | |
| risk_label = "HIGH RISK" | |
| color = "#b00020" | |
| recommendation = "Urgent clinical evaluation required." | |
| elif prob >= 0.35: | |
| risk_label = "MODERATE RISK" | |
| color = "#f57c00" | |
| recommendation = "Close monitoring advised." | |
| else: | |
| risk_label = "LOW RISK" | |
| color = "#2e7d32" | |
| recommendation = "Continue standard treatment protocol." | |
| factors = [] | |
| if low_platelets: | |
| factors.append("Low Platelet Count") | |
| if low_hb: | |
| factors.append("Low Hemoglobin") | |
| last_basic_data = { | |
| "name": name, | |
| "age": age, | |
| "gender": gender, | |
| "platelets": platelets, | |
| "hb": hb, | |
| "duration": duration, | |
| "bacteria": blood_bacteria, | |
| "severity": severity, | |
| "medication": medication, | |
| "prob_pct": prob_pct, | |
| "risk_label": risk_label, | |
| "recommendation": recommendation, | |
| "factors": factors, | |
| "color": color | |
| } | |
| urdu = f""" | |
| <div style='background:#eef3fb;padding:10px;border-radius:8px;'> | |
| <b>اردو خلاصہ:</b><br> | |
| علاج ناکامی کا خطرہ <b>{prob_pct}%</b> ہے۔ درجہ: <b>{risk_label}</b>۔<br> | |
| ڈاکٹر سے مشورہ ضرور کریں۔ | |
| </div> | |
| """ | |
| return f""" | |
| <div style="font-family:Arial;padding:15px;"> | |
| <h2 style="color:{color};">Patient: {name}</h2> | |
| <h3> | |
| Risk of Treatment Failure: | |
| <span style="background:{color};color:white;padding:6px 12px;border-radius:6px;"> | |
| {prob_pct}% - {risk_label} | |
| </span> | |
| </h3> | |
| <h4>Clinical Risk Factors:</h4> | |
| <ul> | |
| {''.join([f"<li>{f}</li>" for f in factors]) if factors else "<li>None</li>"} | |
| </ul> | |
| <h4>Agent Recommendation:</h4> | |
| <p><b>{recommendation}</b></p> | |
| {urdu} | |
| </div> | |
| """ | |
| # =============================== | |
| # DETAILED BUTTON | |
| # =============================== | |
| def generate_detailed(*inputs): | |
| global last_basic_data, last_llm_report | |
| basic_html = predict_basic(*inputs) | |
| d = last_basic_data | |
| patient_info = f""" | |
| Age: {d['age']} | |
| Gender: {d['gender']} | |
| Platelets: {d['platelets']} | |
| Hemoglobin: {d['hb']} | |
| Duration: {d['duration']} | |
| Bacteria: {d['bacteria']} | |
| Severity: {d['severity']} | |
| Medication: {d['medication']} | |
| """ | |
| last_llm_report = generate_llm_report( | |
| patient_info, | |
| d["prob_pct"], | |
| d["risk_label"], | |
| d["recommendation"], | |
| d["factors"] | |
| ) | |
| lines = last_llm_report.split("\n") | |
| formatted_parts = [] | |
| disclaimer_html = "" | |
| for line in lines: | |
| line = line.strip() | |
| if not line: | |
| continue | |
| # Detect disclaimer line | |
| if "consult a qualified doctor" in line.lower(): | |
| disclaimer_html = f""" | |
| <div style=" | |
| margin-top:15px; | |
| padding:12px; | |
| background:#fff3cd; | |
| border-left:5px solid #ff9800; | |
| border-radius:6px; | |
| font-size:14px;"> | |
| <b>Disclaimer:</b><br> | |
| {line} | |
| </div> | |
| """ | |
| continue | |
| # Detect headings starting with ## | |
| if line.startswith("##"): | |
| clean_heading = line.replace("##", "").strip() | |
| formatted_parts.append( | |
| f"<br><b style='font-size:16px;color:#003366;'>{clean_heading}:</b><br>" | |
| ) | |
| else: | |
| formatted_parts.append(f"{line}<br>") | |
| formatted = "".join(formatted_parts) | |
| return basic_html + f""" | |
| <hr> | |
| <h3 style="color:#003366;">Detailed AI Report & Recommendations</h3> | |
| <div style="background:#f9f9f9;padding:15px;border-radius:8px;"> | |
| {formatted} | |
| {disclaimer_html} | |
| </div> | |
| """ | |
| # =============================== | |
| # PDF GENERATION | |
| # =============================== | |
| def generate_pdf(*inputs): | |
| global last_basic_data, last_llm_report | |
| d = last_basic_data | |
| file_path = f"{d['name']}_Typhoid_Report.pdf" | |
| doc = SimpleDocTemplate(file_path) | |
| elements = [] | |
| styles = getSampleStyleSheet() | |
| # ---- Custom Styles ---- | |
| heading_style = ParagraphStyle( | |
| name="CustomHeading", | |
| parent=styles["Heading2"], | |
| fontSize=14, | |
| spaceAfter=6, | |
| textColor=colors.black | |
| ) | |
| bullet_style = ParagraphStyle( | |
| name="BulletStyle", | |
| parent=styles["Normal"], | |
| leftIndent=15, | |
| bulletIndent=5, | |
| spaceAfter=4 | |
| ) | |
| disclaimer_heading_style = ParagraphStyle( | |
| name="DisclaimerHeading", | |
| parent=styles["Heading2"], | |
| textColor=colors.red, | |
| fontSize=13, | |
| spaceBefore=15 | |
| ) | |
| disclaimer_text_style = ParagraphStyle( | |
| name="DisclaimerText", | |
| parent=styles["Normal"], | |
| fontSize=10, | |
| textColor=colors.grey | |
| ) | |
| # ---- LOGO ---- | |
| if os.path.exists(LOGO_PATH): | |
| elements.append(Image(LOGO_PATH, width=1.6*inch, height=1.2*inch)) | |
| elements.append(Spacer(1,0.2*inch)) | |
| elements.append(Paragraph("<b>TyphoidGuard AI Clinical Report</b>", styles["Title"])) | |
| elements.append(Spacer(1, 0.3 * inch)) | |
| # ---- RISK BADGE (Improved Height & Padding) ---- | |
| risk_color = colors.HexColor(d["color"]) | |
| badge_style = ParagraphStyle( | |
| name="Badge", | |
| parent=styles["Normal"], | |
| backColor=risk_color, | |
| textColor=colors.white, | |
| fontSize=13, | |
| leading=18, | |
| leftIndent=10, | |
| rightIndent=10, | |
| spaceBefore=10, | |
| spaceAfter=15 | |
| ) | |
| elements.append(Paragraph( | |
| f"<b>Risk: {d['prob_pct']}% - {d['risk_label']}</b>", | |
| badge_style | |
| )) | |
| elements.append(Spacer(1,0.3*inch)) | |
| # ---- PATIENT TABLE ---- | |
| table_data = [ | |
| ["Patient Name", d["name"]], | |
| ["Age", d["age"]], | |
| ["Gender", d["gender"]], | |
| ["Platelet Count", d["platelets"]], | |
| ["Hemoglobin", d["hb"]], | |
| ["Treatment Duration", d["duration"]], | |
| ["Bacteria", d["bacteria"]], | |
| ["Severity", d["severity"]], | |
| ["Medication", d["medication"]], | |
| ] | |
| table = Table(table_data, colWidths=[2.5*inch, 3*inch]) | |
| table.setStyle(TableStyle([ | |
| ('GRID',(0,0),(-1,-1),1,colors.grey), | |
| ('FONTNAME',(0,0),(-1,-1),'Helvetica') | |
| ])) | |
| elements.append(table) | |
| elements.append(Spacer(1,0.4*inch)) | |
| # ---- AGENT RECOMMENDATION ---- | |
| elements.append(Paragraph("<b>Agent Recommendation</b>", heading_style)) | |
| elements.append(Paragraph(d["recommendation"], styles["Normal"])) | |
| elements.append(Spacer(1,0.4*inch)) | |
| # ---- DETAILED AI REPORT ---- | |
| if last_llm_report: | |
| elements.append(Paragraph("<b>Detailed AI Report</b>", heading_style)) | |
| elements.append(Spacer(1,0.2*inch)) | |
| lines = last_llm_report.split("\n") | |
| for line in lines: | |
| line = line.strip() | |
| if not line: | |
| continue | |
| if "qualified doctor" in line.lower(): | |
| continue | |
| if line.startswith("##"): | |
| clean_heading = line.replace("##", "").strip() | |
| elements.append(Spacer(1,0.2*inch)) | |
| elements.append( | |
| Paragraph(f"<b>{clean_heading}:</b>", heading_style) | |
| ) | |
| else: | |
| elements.append(Paragraph(line, styles["Normal"])) | |
| elements.append(Spacer(1,0.5*inch)) | |
| # ---- DISCLAIMER ---- | |
| elements.append(Paragraph("Disclaimer", disclaimer_heading_style)) | |
| elements.append(Spacer(1,0.1*inch)) | |
| elements.append(Paragraph( | |
| "Remember to consult a qualified doctor for personalized advice and treatment. " | |
| "They will be able to provide guidance tailored to the patient's specific needs and circumstances.", | |
| disclaimer_text_style | |
| )) | |
| elements.append(Spacer(1,0.5*inch)) | |
| # ---- TEAM ---- | |
| elements.append(Paragraph("<b>Team Chinar AI (AJK)</b>", styles["Normal"])) | |
| elements.append(Paragraph( | |
| "Anees Qumar Abbasi (Team Lead) | Sharafat Hussain | Salma Asghar | " | |
| "Kaleem Hussain | Munazza Zahra | Kokub Khhurishid", | |
| styles["Normal"] | |
| )) | |
| doc.build(elements) | |
| # ✅ SUCCESS POPUP MESSAGE (Added Feature) | |
| gr.Info("Report Generated Successfully! Please download it below.") | |
| return file_path | |
| # =============================== | |
| # INTERFACE | |
| # =============================== | |
| # =============================== | |
| # PREMIUM MEDICAL INTERFACE (UPDATED) | |
| # =============================== | |
| with gr.Blocks( | |
| theme=gr.themes.Soft(), | |
| css=""" | |
| body { | |
| background: linear-gradient(135deg, #e3f2fd, #f4f9ff); | |
| } | |
| .center-header { | |
| text-align: center; | |
| } | |
| #header-center { | |
| text-align: center; | |
| } | |
| .instruction-text { | |
| text-align: center; | |
| font-size: 16px; | |
| color: #37474f; | |
| margin-bottom: 20px; | |
| } | |
| .gr-button { | |
| border-radius: 10px !important; | |
| font-weight: 600 !important; | |
| padding: 10px 18px !important; | |
| font-size: 15px !important; | |
| } | |
| .gr-textbox, .gr-number, .gr-dropdown { | |
| border-radius: 8px !important; | |
| } | |
| .footer-team { | |
| background: #ffffff; | |
| padding: 15px; | |
| border-radius: 10px; | |
| margin-top: 20px; | |
| text-align: center; | |
| font-size: 14px; | |
| box-shadow: 0 2px 8px rgba(0,0,0,0.05); | |
| } | |
| """ | |
| ) as demo: | |
| # ---- LOGO (Guaranteed to Display in HF) ---- | |
| # ---- LOGO (Centered) ---- | |
| '''gr.Markdown('<div style="text-align:center;">') | |
| gr.Image(LOGO_PATH, width=300, show_label=False, container=False) | |
| gr.Markdown('</div>') | |
| # ---- CENTERED HEADER ---- | |
| gr.Markdown(""" | |
| <div class="center-header"> | |
| <h1 style="color:#0d47a1;">🏥 TyphoidGuard AI</h1> | |
| <h4 style="color:#37474f;">HEC Generative AI Hackathon – Pakistan</h4> | |
| <h4 style="color:#00695c;">Team Chinar AI (AJK)</h4> | |
| </div> | |
| """)''' | |
| # ---- CENTERED LOGO + HEADER ---- | |
| with gr.Row(): | |
| with gr.Column(scale=1, elem_id="header-center"): | |
| gr.Image(LOGO_PATH, width=300, show_label=False) | |
| gr.Markdown(""" | |
| <div style="text-align:center;"> | |
| <h1 style="color:#0d47a1; margin-top:15px;">🏥 TyphoidGuard AI</h1> | |
| <h4 style="color:#37474f; margin:5px 0;">HEC Generative AI Hackathon – Pakistan</h4> | |
| <h4 style="color:#00695c; margin:5px 0;">Team Chinar AI (AJK)</h4> | |
| </div> | |
| """) | |
| # ---- INSTRUCTION TEXT ---- | |
| gr.Markdown(""" | |
| <div class="instruction-text"> | |
| Please enter the patient clinical values below to assess | |
| the risk of typhoid treatment failure and receive AI-based recommendations. | |
| </div> | |
| """) | |
| # ---- INPUT FIELDS ---- | |
| with gr.Row(): | |
| name = gr.Textbox(label="Patient Name") | |
| age = gr.Number(label="Age") | |
| gender = gr.Radio(["Male", "Female"], label="Gender") | |
| with gr.Row(): | |
| platelets = gr.Number(label="Platelet Count") | |
| hb = gr.Number(label="Hemoglobin (g/dL)") | |
| duration = gr.Number(label="Treatment Duration (Days)") | |
| with gr.Row(): | |
| blood_bacteria = gr.Dropdown( | |
| ["Escherichia coli","Salmonella typhi","Unknown","Staphylococcus"], | |
| label="Blood Culture Bacteria" | |
| ) | |
| severity = gr.Dropdown( | |
| ["Low","Moderate","High","Unknown"], | |
| label="Symptoms Severity" | |
| ) | |
| medication = gr.Dropdown( | |
| ["Amoxicillin","Ceftriaxone","Azithromycin"], | |
| label="Current Medication" | |
| ) | |
| # ---- BUTTONS ---- | |
| with gr.Row(): | |
| predict_btn = gr.Button("Basic Risk Assessment") | |
| detailed_btn = gr.Button("Detailed Report & Recommendations") | |
| pdf_btn = gr.Button("Generate PDF Report") | |
| output = gr.HTML() | |
| predict_btn.click(predict_basic, | |
| inputs=[name,age,gender,platelets,hb,duration, | |
| blood_bacteria,severity,medication], | |
| outputs=output) | |
| detailed_btn.click(generate_detailed, | |
| inputs=[name,age,gender,platelets,hb,duration, | |
| blood_bacteria,severity,medication], | |
| outputs=output) | |
| pdf_btn.click(generate_pdf, | |
| inputs=[name,age,gender,platelets,hb,duration, | |
| blood_bacteria,severity,medication], | |
| outputs=gr.File()) | |
| # ---- TEAM FOOTER ---- | |
| gr.Markdown(""" | |
| <div class="footer-team"> | |
| <b>Team Chinar AI (AJK)</b><br> | |
| Anees Qumar Abbasi (Team Lead) | Sharafat Hussain | Salma Asghar | | |
| Kaleem Hussain | Munazza Zahra | Kokub Khurishid | |
| </div> | |
| """) | |
| demo.launch() |