# In app.py import gradio as gr import requests import os import uuid import time MODAL_BACKEND_URL = os.getenv("MODAL_BACKEND_URL", "").strip() CUSTOM_CSS = """ :root { --primary: #8aa8ff; --bg-dark: #1a1a2e; --bg-light: #ffffff; --text-dark: #e0e0e0; --text-light: #2b2b4d; } @media (prefers-color-scheme: dark) { body, .gradio-container { background-color: var(--bg-dark); color: var(--text-dark); } .chatbot-box { background-color: #2b2b4d; border: 1px solid #3a3a5e; border-radius: 12px; padding: 10px; } .chatbot-message.bot { background-color: #3a3a5e !important; color: var(--text-dark); padding: 8px; border-radius: 8px; } .chatbot-message.user { background: linear-gradient(to right, #4a4a8a, #5c5cb8); color: #fff; padding: 8px; border-radius: 8px; } } #send-button { background-color: #F97316 !important; color: white !important; font-weight: 600 !important; } #send-button:hover { background-color: #EA580C !important; } """ def handle_user_turn(user_input: str, chat_history: list, user_role: str, sid: str): """ Handles a single turn of the conversation. """ if not user_input.strip(): return chat_history, "" # Initialize chat_history if it's the first turn (it will be None) if chat_history is None: chat_history = [] # Append the user's message in the correct dictionary format chat_history.append({"role": "user", "content": user_input}) # Immediately yield the updated history to show the user's message yield chat_history, "" if not MODAL_BACKEND_URL: chat_history.append({"role": "assistant", "content": "❗ Configuration error: `MODAL_BACKEND_URL` is not set."}) yield chat_history, "" return # --- Streaming "Thinking" Animation --- chat_history.append({"role": "assistant", "content": ""}) # Add an empty placeholder for the bot response thinking_steps = ["Analyzing your query...", "Searching medical databases...", "Consulting research papers...", "Synthesizing the answer..."] for step in thinking_steps: # Update the last message (the bot's placeholder) with the current thinking step chat_history[-1]["content"] = f"{step}" yield chat_history, "" time.sleep(0.4) # --- End of Animation --- try: response = requests.post(MODAL_BACKEND_URL, json={ "user_input": user_input, "session_id": sid, "role": user_role }, timeout=600) response.raise_for_status() reply = response.json().get("final_markdown", "No valid response was received from the backend.") except requests.exceptions.RequestException as e: reply = f"❗ **Error Communicating with Backend:**\n\nCould not get a response. The server may be starting up or experiencing an issue. Please try again in a moment. \n\n*Details: {str(e)}*" except Exception as e: reply = f"❗ **An Unexpected Error Occurred:**\n\n*Details: {str(e)}*" # Update the final bot message with the actual reply chat_history[-1]["content"] = reply yield chat_history, "" # --- The rest of your Gradio app code remains the same --- with gr.Blocks(css=CUSTOM_CSS, title="MediAgent AI: Conversational Health Navigator & MCP Tool Server") as demo: session_id = gr.State(lambda: str(uuid.uuid4())) gr.Markdown(""" # 🧬 MediAgent AI: Conversational Health Navigator & MCP Tool Server