File size: 10,793 Bytes
bdb09c8
 
 
c6163b1
 
b9dbc6c
bdb09c8
b9dbc6c
bdb09c8
c6163b1
b9dbc6c
 
c6163b1
b9dbc6c
bdb09c8
b9dbc6c
 
 
 
c6163b1
 
b9dbc6c
 
c6163b1
b9dbc6c
c6163b1
 
 
b9dbc6c
 
 
c6163b1
 
b9dbc6c
c6163b1
b9dbc6c
bdb09c8
c6163b1
bdb09c8
 
b9dbc6c
c6163b1
b9dbc6c
c6163b1
 
 
 
b9dbc6c
c6163b1
b9dbc6c
c6163b1
b9dbc6c
c6163b1
 
 
 
 
 
 
 
 
 
 
 
b9dbc6c
c6163b1
 
b9dbc6c
c6163b1
 
 
 
b9dbc6c
c6163b1
 
 
b9dbc6c
c6163b1
b9dbc6c
 
c6163b1
b9dbc6c
 
c6163b1
b9dbc6c
c6163b1
b9dbc6c
 
c6163b1
b9dbc6c
 
 
c6163b1
b9dbc6c
 
c6163b1
b9dbc6c
bdb09c8
c6163b1
 
 
 
b9dbc6c
 
c6163b1
b9dbc6c
 
 
c6163b1
b9dbc6c
c6163b1
 
 
 
 
 
b9dbc6c
bdb09c8
c6163b1
 
 
b9dbc6c
 
 
bdb09c8
 
c6163b1
 
 
 
 
b9dbc6c
c6163b1
 
 
 
b9dbc6c
 
 
 
c6163b1
 
 
 
 
 
 
 
b9dbc6c
c6163b1
 
 
 
 
b9dbc6c
c6163b1
 
 
 
 
b9dbc6c
 
c6163b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bdb09c8
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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()