""" PrimaCare AI - Interactive Demo MedGemma Impact Challenge | All 4 Award Tracks Showcases the 5-agent CXR diagnostic pipeline, patient education, and edge AI deployment built on MedGemma 1.5 4B and MedSigLIP. """ import gradio as gr # ── Pre-computed example outputs (from Kaggle T4 runs) ────────────── PIPELINE_DEMO = { "case": "65-year-old male, current smoker (30 pack-years). Productive cough with yellow-green sputum for 2 weeks. Low-grade fever (100.4F). Progressive dyspnea on exertion. Night sweats.", "intake": """**HISTORY OF PRESENT ILLNESS** **Chief Complaint:** Productive cough for 2 weeks with fever and dyspnea **HPI:** 65-year-old male presenting with a 2-week history of productive cough with yellow-green sputum. Associated symptoms include low-grade fever (100.4\u00b0F), progressive dyspnea on exertion, and night sweats. Patient is a current smoker with a 30 pack-year history. Denies hemoptysis or recent travel. **RED FLAGS IDENTIFIED:** - Age >60 with new respiratory symptoms - Fever with productive cough (infection concern) - Night sweats (consider TB, malignancy) - Heavy smoking history (malignancy risk) **Urgency:** MODERATE-HIGH \u2014 Evaluation within 24 hours recommended""", "imaging": """**SYSTEMATIC CXR ANALYSIS** **Airway:** Trachea midline, no deviation. Main bronchi patent. **Breathing/Lungs:** Right lower lobe opacity with air bronchograms, consistent with consolidation. No pneumothorax. Left lung fields clear. **Cardiac:** Heart size within normal limits. No pericardial effusion. **Diaphragm:** Right hemidiaphragm partially obscured by consolidation. Left hemidiaphragm sharp. **Everything else:** No pleural effusion. Osseous structures unremarkable. **IMPRESSION:** Right lower lobe consolidation, most consistent with community-acquired pneumonia in the clinical context. **MedSigLIP Classification:** pneumonia: 0.847 normal: 0.153""", "reasoning": """**DIFFERENTIAL DIAGNOSIS** 1. Community-acquired pneumonia (CAP) \u2014 HIGH probability - Right lower lobe consolidation + productive cough + fever + smoking history 2. Lung malignancy \u2014 MODERATE probability - Age, smoking history, night sweats; post-obstructive pneumonia possible 3. Tuberculosis \u2014 LOW-MODERATE probability - Night sweats, but location atypical for reactivation TB **RECOMMENDED WORKUP** - CBC with differential, CMP, procalcitonin - Sputum culture and Gram stain - Blood cultures x2 (before antibiotics) - CT chest if no improvement in 48-72 hours **DISPOSITION:** Outpatient with close follow-up if stable; admit if hypoxic, tachycardic, or elderly with comorbidities (CURB-65 score \u22652) **RISK STRATIFICATION:** CURB-65 = 1-2 (age >65). Consider admission.""", "guidelines": """**EVIDENCE-BASED RECOMMENDATIONS** Based on ATS/IDSA Community-Acquired Pneumonia Guidelines: 1. **Empiric antibiotics:** Amoxicillin/clavulanate + macrolide (e.g., azithromycin), OR respiratory fluoroquinolone monotherapy 2. **Duration:** 5-7 days minimum, continue until afebrile 48-72 hours 3. **Follow-up CXR:** At 6-8 weeks to confirm resolution (important given smoking history and age) 4. **Smoking cessation:** Counsel and offer pharmacotherapy 5. **Pneumococcal vaccination:** Verify PCV20 status given age >65 **Conditions Matched:** community-acquired pneumonia, smoking cessation **Retrieval Mode:** semantic + keyword fallback""", } EDUCATION_EXAMPLES = { "basic": { "diagnosis": "Your chest X-ray shows an infection in your right lung called pneumonia. This is causing your cough, fever, and trouble breathing.", "what_it_means": "Pneumonia is when germs get into your lungs and cause swelling and fluid buildup. The good news is that this type of pneumonia usually gets better with the right medicine.", "next_steps": "Your doctor will give you antibiotic medicine to fight the infection. Take all the medicine even if you start feeling better. Rest, drink plenty of fluids, and avoid smoking.", "when_to_seek_help": "Go to the emergency room right away if you have: trouble breathing that gets worse, chest pain, high fever over 103\u00b0F, confusion, or coughing up blood.", "glossary": { "Pneumonia": "An infection in your lungs that causes cough, fever, and trouble breathing", "Consolidation": "An area of your lung that has filled with fluid from the infection", "Antibiotics": "Medicines that kill the germs causing your infection", "CXR": "Chest X-ray \u2014 a picture of your lungs taken with a special camera", }, }, "intermediate": { "diagnosis": "Chest X-ray reveals right lower lobe consolidation consistent with community-acquired pneumonia (CAP). MedSigLIP classification shows 84.7% probability of pneumonia.", "what_it_means": "Community-acquired pneumonia is a lung infection picked up outside of a hospital. The right lower lobe of your lung shows an area of consolidation where air spaces have filled with inflammatory fluid. Your smoking history is a contributing risk factor.", "next_steps": "Empiric antibiotic therapy targeting common CAP pathogens. Sputum and blood cultures to identify the specific organism. Follow-up chest X-ray in 6-8 weeks to confirm resolution. Smoking cessation counseling.", "when_to_seek_help": "Seek immediate care for: worsening dyspnea, oxygen saturation below 92%, persistent fever >72 hours on antibiotics, hemoptysis, altered mental status.", "glossary": { "Community-acquired pneumonia": "Lung infection contracted outside hospital settings", "Consolidation": "Area of lung where alveoli fill with fluid, pus, or inflammatory cells", "Empiric therapy": "Treatment started before the exact cause is identified, based on likely pathogens", "Dyspnea": "Difficulty breathing or shortness of breath", "Hemoptysis": "Coughing up blood", }, }, "detailed": { "diagnosis": "Radiographic findings demonstrate right lower lobe consolidation with air bronchograms on PA chest radiograph, highly suggestive of community-acquired pneumonia (CAP) in the setting of productive cough, fever, and significant smoking history (30 pack-years). Zero-shot MedSigLIP classification yields P(pneumonia) = 0.847.", "what_it_means": "The consolidation pattern with air bronchograms indicates alveolar filling, most commonly infectious in etiology. The clinical presentation (subacute productive cough, low-grade fever, night sweats) combined with imaging findings and smoking history raises the differential of CAP versus post-obstructive pneumonia secondary to endobronchial lesion. The night sweats warrant consideration of mycobacterial infection, though the radiographic pattern is atypical for reactivation tuberculosis.", "next_steps": "Initiate empiric antibiotics per ATS/IDSA guidelines (amoxicillin-clavulanate plus macrolide, or respiratory fluoroquinolone). Obtain sputum Gram stain/culture, blood cultures x2 prior to antibiotic administration. Consider CT chest if no clinical improvement at 48-72 hours to evaluate for underlying mass or abscess. Follow-up CXR at 6-8 weeks is mandatory given age and smoking history to exclude malignancy.", "when_to_seek_help": "Return for: progressive respiratory distress, SpO2 <92% on room air, fever >103\u00b0F or persistent fever >72h on appropriate antibiotics, hemoptysis, pleuritic chest pain, confusion or altered sensorium.", "glossary": { "Air bronchograms": "Air-filled bronchi visible within surrounding opacified (consolidated) lung parenchyma", "Alveolar filling": "Replacement of air in the alveoli with fluid, pus, blood, or cells", "Post-obstructive pneumonia": "Pneumonia occurring distal to an endobronchial obstruction such as a tumor", "ATS/IDSA": "American Thoracic Society / Infectious Diseases Society of America", "Reactivation TB": "Tuberculosis that reactivates from a prior latent infection, typically in upper lobes", "CURB-65": "Severity score: Confusion, Urea, Respiratory rate, Blood pressure, Age \u226565", }, }, } EDGE_RESULTS = [ {"sample": "Sample 1", "true": "normal", "pred": "normal", "p_pneumonia": 0.12, "match": "OK"}, {"sample": "Sample 2", "true": "normal", "pred": "normal", "p_pneumonia": 0.08, "match": "OK"}, {"sample": "Sample 3", "true": "normal", "pred": "normal", "p_pneumonia": 0.21, "match": "OK"}, {"sample": "Sample 4", "true": "pneumonia", "pred": "pneumonia", "p_pneumonia": 0.89, "match": "OK"}, {"sample": "Sample 5", "true": "pneumonia", "pred": "pneumonia", "p_pneumonia": 0.93, "match": "OK"}, {"sample": "Sample 6", "true": "pneumonia", "pred": "pneumonia", "p_pneumonia": 0.76, "match": "OK"}, ] # ── Gradio interface functions ────────────────────────────────────── def run_pipeline_demo(): d = PIPELINE_DEMO output = f"""## Patient Presentation > {d['case']} --- ### Agent 1: IntakeAgent \u2014 Structured HPI {d['intake']} --- ### Agent 2: ImagingAgent \u2014 CXR Analysis + Classification {d['imaging']} --- ### Agent 3: ReasoningAgent \u2014 Differential Diagnosis {d['reasoning']} --- ### Agent 4: GuidelinesAgent \u2014 Evidence-Based Recommendations {d['guidelines']} """ return output def show_education(level): edu = EDUCATION_EXAMPLES.get(level, EDUCATION_EXAMPLES["basic"]) glossary_text = "\n".join(f"- **{k}:** {v}" for k, v in edu["glossary"].items()) return f"""## Patient Education \u2014 {level.title()} Level ### Simplified Diagnosis {edu['diagnosis']} ### What It Means {edu['what_it_means']} ### Next Steps {edu['next_steps']} ### When to Seek Help {edu['when_to_seek_help']} ### Glossary {glossary_text} """ def show_edge_demo(): rows = "" for r in EDGE_RESULTS: rows += f"| {r['sample']} | {r['true']} | {r['pred']} | {r['p_pneumonia']:.2f} | {r['match']} |\n" return f"""## Edge AI \u2014 CPU-Only Pneumonia Screening **Model:** MedSigLIP ONNX FP32 via ONNX Runtime (CPU) | Sample | True Label | Prediction | P(pneumonia) | Status | |--------|-----------|------------|-------------|--------| {rows} ### Deployment Comparison | Metric | GPU (Cloud) | Edge (CPU) | |--------|------------|------------| | Model Size | 3,500 MB | 1,635 MB (FP32) / 422 MB (INT8) | | Latency | ~17s | ~4s | | Hardware | NVIDIA T4 | Any CPU | | Accuracy | Full pipeline | Binary screening | ### How It Works 1. **Export** MedSigLIP vision encoder to ONNX FP32 2. **Quantize** to INT8 (74% size reduction, technique demo) 3. **Pre-compute** text embeddings for "normal" / "pneumonia" 4. **Inference:** Vision encoder on CPU + cosine similarity FP32 ONNX is used for production edge inference (INT8 degrades attention pooling precision). """ def show_metrics(): return """## Evaluation Results ### Binary Pneumonia Classification (100 balanced samples) | Metric | 10-Label Mode | Binary Mode | |--------|:---:|:---:| | Accuracy | 53.0% | **63.0%** | | Precision | 71.4% | **57.5%** | | Recall | 10.0% | **100.0%** | | Specificity | 96.0% | **26.0%** | | F1 | 0.175 | **0.73** | **Threshold:** 0.30 (recall-priority \u2014 no pneumonia cases missed) **F1 95% CI:** [0.64, 0.80] (500 bootstrap resamples) ### Pipeline Latency (Kaggle T4) | Stage | Median Time | |-------|:---:| | IntakeAgent | 23.3s | | ImagingAgent | 16.9s | | ReasoningAgent | 38.0s | | GuidelinesAgent | 32.9s | | EducationAgent | ~15s | | **Total** | **~126s** | ### Test Coverage - **42 tests passing**, 1 skipped (GPU) - All tests run with mocks \u2014 no GPU required - Framework: pytest with shared fixtures """ # ── Build the Gradio app ──────────────────────────────────────────── HEADER_MD = """ # PrimaCare AI ### Multi-Agent CXR Diagnostic Support with Patient Education and Edge Deployment **MedGemma Impact Challenge** | Main Track \u00b7 Agentic Workflow \u00b7 Novel Task \u00b7 Edge AI Built on **MedGemma 1.5 4B** + **MedSigLIP 448** + **sentence-transformers** ``` Patient \u2192 IntakeAgent \u2192 ImagingAgent \u2192 ReasoningAgent \u2192 GuidelinesAgent \u2192 EducationAgent \u2192 Report ``` [GitHub](https://github.com/thestai-admin/Med-Gemma) \u00b7 [Kaggle Notebook](https://www.kaggle.com/competitions/med-gemma-impact-challenge/writeups) \u00b7 Solo submission by Tarkeshwar Narayan Sharma --- """ DISCLAIMER = """ --- *PrimaCare AI is clinician decision support, not autonomous diagnosis. All outputs require verification by qualified healthcare professionals. Pre-computed outputs shown from Kaggle T4 GPU runs.* """ with gr.Blocks( title="PrimaCare AI Demo", theme=gr.themes.Soft(primary_hue="blue", neutral_hue="slate"), ) as demo: gr.Markdown(HEADER_MD) with gr.Tabs(): # ── Tab 1: Full Pipeline ── with gr.Tab("5-Agent Pipeline"): gr.Markdown("### Full CXR Diagnostic Pipeline (Tracks 1 & 2)") gr.Markdown( "Demonstrates all 5 agents processing a pneumonia case. " "Each agent's output chains into the next." ) btn_pipeline = gr.Button("Run Pipeline Demo", variant="primary") output_pipeline = gr.Markdown() btn_pipeline.click(fn=run_pipeline_demo, outputs=output_pipeline) # ── Tab 2: Patient Education ── with gr.Tab("Patient Education"): gr.Markdown("### Track 3: Novel Task \u2014 Health Literacy Translation") gr.Markdown( "The same clinical findings translated to 3 reading levels. " "~36% of US adults have limited health literacy." ) level_select = gr.Radio( choices=["basic", "intermediate", "detailed"], value="basic", label="Reading Level", ) output_edu = gr.Markdown() level_select.change(fn=show_education, inputs=level_select, outputs=output_edu) demo.load(fn=show_education, inputs=level_select, outputs=output_edu) # ── Tab 3: Edge AI ── with gr.Tab("Edge AI"): gr.Markdown("### Track 4: CPU-Only Pneumonia Screening") btn_edge = gr.Button("Show Edge Results", variant="primary") output_edge = gr.Markdown() btn_edge.click(fn=show_edge_demo, outputs=output_edge) # ── Tab 4: Evaluation ── with gr.Tab("Evaluation & Metrics"): gr.Markdown("### Quantitative Results & Reproducibility") btn_metrics = gr.Button("Show Metrics", variant="primary") output_metrics = gr.Markdown() btn_metrics.click(fn=show_metrics, outputs=output_metrics) gr.Markdown(DISCLAIMER) demo.launch()