med / app.py
mgbam's picture
Update app.py
c6163b1 verified
raw
history blame
10.8 kB
import streamlit as st
import google.generativeai as genai
import os
# from PIL import Image # Removing image focus for this agentic text example
import io
from typing import Optional, Tuple, Any # For type hinting
# --- Configuration and Initialization ---
# Securely load API key (Prioritize Secrets, then Env Vars)
GEMINI_API_KEY = st.secrets.get("GEMINI_API_KEY", os.environ.get("GEMINI_API_KEY"))
# Configure Gemini Client
genai_client_configured = False
if GEMINI_API_KEY:
try:
genai.configure(api_key=GEMINI_API_KEY)
genai_client_configured = True
except Exception as e:
st.error(f"Fatal Error: Failed to configure Google Generative AI. Check API Key and permissions. Details: {e}")
st.stop()
else:
st.error("⚠️ Gemini API Key not found. Please configure `GEMINI_API_KEY` in Streamlit secrets or environment variables.")
st.stop()
# Initialize models (Using specific models for consistency)
# Using a potentially more powerful model like 1.5 Pro might be beneficial for complex reasoning
MODEL_NAME = 'gemini-1.5-pro-latest' # Or 'gemini-1.5-flash' if speed is critical
if genai_client_configured:
try:
model = genai.GenerativeModel(MODEL_NAME)
# vision_model = genai.GenerativeModel('gemini-pro-vision') # Keep commented unless adding image capability back
except Exception as e:
st.error(f"Fatal Error: Failed to initialize Gemini model ({MODEL_NAME}). Details: {e}")
st.stop()
else:
st.error("AI Model could not be initialized due to configuration issues.")
st.stop()
# --- Core Agentic AI Simulation Function ---
# This prompt instructs the LLM to simulate a structured, agent-like reasoning process
# focused on differential diagnosis support.
AGENTIC_ANALYSIS_PROMPT_TEMPLATE = """
**Simulated Clinical Reasoning Agent Task:**
**Role:** You are an AI assistant simulating an agentic clinical reasoning process to support a healthcare professional. Your goal is NOT to diagnose, but to structure information, generate possibilities, and suggest logical next steps based *strictly* on the provided information.
**Input Data:** You will receive unstructured clinical information (e.g., symptoms, history, basic findings). Assume this is the *only* information available unless stated otherwise.
**Simulated Agentic Steps (Perform these sequentially in your response):**
1. **Information Extraction & Structuring:**
* Identify and list the key patient demographics (age, sex, if provided).
* List the primary symptoms and signs presented.
* Summarize relevant medical history points.
* Note any explicitly mentioned negative findings (pertinent negatives).
2. **Differential Considerations Generation:**
* Based *only* on the structured information from Step 1, generate a list of **potential differential considerations** (possible conditions that *could* explain the findings).
* **Use cautious and probabilistic language:** "could be consistent with," "warrants consideration," "less likely but possible," "should be ruled out." **AVOID definitive statements.**
* Briefly state the primary rationale linking each consideration to the key findings.
3. **Information Gap Analysis:**
* Identify critical pieces of information typically needed for assessment that are missing from the input (e.g., specific lab results, imaging details, physical exam specifics, duration/onset details).
4. **Suggested Next Steps for Investigation (for the Clinician):**
* Propose logical next steps a **healthcare professional might consider** to narrow down the possibilities or gather missing information.
* Categorize suggestions (e.g., Further History Taking, Physical Examination Points, Laboratory Tests, Imaging Studies).
* Frame these as *suggestions* for the clinician's judgment (e.g., "Consider ordering...", "Assessment of X may be informative", "Further questioning about Y could clarify...").
5. **Mandatory Disclaimer:** Conclude with: "This AI-generated analysis is for informational support only. It is **NOT** a diagnosis and cannot replace the judgment of a qualified healthcare professional who must consider the full clinical context, conduct necessary examinations, and interpret investigations."
**Input Clinical Information:**
---
{text_input}
---
**Agentic Analysis:**
"""
def run_agentic_reasoning(text_input: str) -> Tuple[Optional[str], Optional[str]]:
"""
Simulates an agentic reasoning process on clinical text using the Gemini model.
Args:
text_input: The clinical information provided by the user.
Returns:
A tuple containing:
- The structured analysis text (str) if successful, None otherwise.
- An error message (str) if an error occurred, None otherwise.
"""
if not text_input or not text_input.strip():
return None, "Input text cannot be empty."
try:
prompt = AGENTIC_ANALYSIS_PROMPT_TEMPLATE.format(text_input=text_input)
# Consider adding safety settings if dealing with potentially sensitive outputs
# safety_settings = [...]
# response = model.generate_content(prompt, safety_settings=safety_settings)
response = model.generate_content(prompt)
# Check for blocked content or other issues
if response.parts:
return response.text, None
elif response.prompt_feedback.block_reason:
return None, f"Analysis blocked by safety filters: {response.prompt_feedback.block_reason.name}. Please review input for potentially harmful content or adjust safety settings if appropriate."
else:
# Handle cases where the response might be empty but not explicitly blocked
candidate = response.candidates[0] if response.candidates else None
if candidate and candidate.finish_reason != "STOP":
return None, f"Analysis stopped prematurely. Reason: {candidate.finish_reason.name}. The input might be too complex or ambiguous."
else:
return None, "Received an empty or unexpected response from the AI model. The model may not have been able to process the request."
except Exception as e:
st.error(f"Critical Error during AI Analysis: {e}", icon="🚨") # Log for debugging
# Provide a user-friendly error message
return None, f"An error occurred while communicating with the AI model. Please try again later or check the input. Details: {e}"
# --- Streamlit User Interface ---
def main():
st.set_page_config(
page_title="Agentic AI Clinical Reasoning Support",
layout="wide",
initial_sidebar_state="expanded"
)
# --- Header ---
st.title("πŸ€– Agentic AI: Clinical Reasoning Support Tool")
st.caption(f"Powered by Google Gemini ({MODEL_NAME})")
st.markdown("---")
# --- CRITICAL DISCLAIMER ---
st.warning(
"""
**πŸ”΄ EXTREMELY IMPORTANT DISCLAIMER πŸ”΄**
* This tool **SIMULATES** an AI reasoning process. It **DOES NOT DIAGNOSE** diseases or provide medical advice.
* Outputs are based **SOLELY** on the text input and the AI's internal knowledge, which may be incomplete or contain inaccuracies. **It lacks real-world clinical context.**
* **NEVER** use this tool for actual patient diagnosis, treatment decisions, or clinical management. It is intended for **educational and conceptual purposes ONLY**, potentially aiding clinicians in organizing thoughts or exploring possibilities.
* **ALWAYS rely on the expertise and judgment of qualified healthcare professionals.**
* **PRIVACY ALERT:** Do **NOT** enter identifiable patient information (PHI) unless you comply with all legal and ethical requirements (e.g., HIPAA, GDPR, patient consent). You are responsible for the data you input.
""",
icon="⚠️"
)
st.markdown("---")
# --- Input Area ---
st.header("Clinical Information Input")
st.markdown("Enter de-identified clinical information below (e.g., symptoms, brief history, key findings). The AI will attempt a structured analysis.")
text_input = st.text_area(
"Enter Clinical Data:",
height=300,
placeholder="Example: A 68-year-old male presents with sudden onset shortness of breath and pleuritic chest pain. History of recent long-haul flight. Vitals show tachycardia (HR 110) and mild hypoxia (SpO2 92% on room air). No significant cardiac history mentioned...",
key="clinical_text_input"
)
# --- Action Button ---
analyze_button = st.button("▢️ Run Agentic Analysis", key="analyze_button", type="primary", help="Click to start the simulated reasoning process.")
st.markdown("---") # Separator before results
# --- Output Area ---
st.header("Analysis Results")
if analyze_button:
if text_input:
with st.spinner("🧠 Simulating agentic reasoning... Please wait."):
analysis_result, error_message = run_agentic_reasoning(text_input)
if error_message:
st.error(f"Analysis Failed: {error_message}", icon="❌")
elif analysis_result:
st.markdown("**Simulated Agent Analysis Output:**")
st.markdown(analysis_result) # Use markdown for better formatting
else:
st.error("An unexpected issue occurred. No analysis was returned.", icon="❓")
else:
st.warning("Please enter clinical information in the text area above before analyzing.", icon="☝️")
else:
st.info("Analysis results will appear here after you enter information and click 'Run Agentic Analysis'.")
# --- Sidebar for Explanation/Prompt ---
st.sidebar.header("About This Tool")
st.sidebar.info(
"This application demonstrates how an AI model (Gemini) can be prompted to simulate "
"a structured, agent-like approach to analyzing clinical information. It focuses on "
"differential considerations and suggesting investigation pathways for **clinician review**."
)
with st.sidebar.expander("View the Agentic Prompt Structure"):
st.markdown(f"```plaintext\n{AGENTIC_ANALYSIS_PROMPT_TEMPLATE.split('---')[0]} ... [Input Text] ...\n```")
st.caption("The prompt guides the AI to break down the task into logical steps.")
st.sidebar.header("Ethical Considerations")
st.sidebar.error(
"**Crucial Reminder:** This AI is a tool, not a clinician. It has limitations and biases. "
"Clinical decisions require human expertise, empathy, and comprehensive patient assessment. "
"Misuse can lead to harm."
)
if __name__ == "__main__":
main()