import gradio as gr import requests import os import uuid # --- Configuration --- MODAL_BACKEND_URL = os.getenv("MODAL_BACKEND_URL", "").strip() # --- Dynamic Theme CSS --- CUSTOM_CSS = """ @media (prefers-color-scheme: dark) { body { background-color: #1a1a2e; color: #E0E0E0; } .gradio-container { background-color: #21213b; color: #E0E0E0; } #app-header h1 { color: #8aa8ff; } #app-header p { color: #aeb8d8; } #role-selector { border: 1px solid #3a3a5e; background-color: #2b2b4d; } .gradio-label, .gradio-radio input[type='radio'] + label { color: #E0E0E0 !important; } .gradio-radio input[type='radio']:checked + label { color: #8aa8ff !important; } #chatbot { background-color: #2b2b4d; border: 1px solid #3a3a5e; } .message { padding: 1rem 1.25rem; border-radius: 12px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .message.user { background: linear-gradient(to right, #4a4a8a, #5c5cb8) !important; color: #FFFFFF; } .message.bot { background: #3a3a5e !important; color: #E0E0E0; border: 1px solid #4a4a8a; } .message.bot h3 { color: #8aa8ff; border-bottom: 2px solid #5c5cb8; } .message.bot ul { padding-left: 20px; list-style-type: disc; } .message.bot li { margin-bottom: 0.5rem; line-height: 1.6; } .message.bot a { color: #8aa8ff; text-decoration: none; font-weight: 500; } .message.bot a:hover { text-decoration: underline; color: #768fff; } .message.bot strong { color: #8aa8ff; } .message.bot em { color: #b0b0d0; background-color: #4a4a8a; padding: 2px 6px; border-radius: 4px; } #send-button { background-color: #8aa8ff !important; color: white !important; font-weight: 600; } #send-button:hover { background-color: #768fff !important; } .gradio-textbox textarea { background-color: #2b2b4d !important; color: #E0E0E0 !important; border: 1px solid #3a3a5e !important; } .gradio-textbox textarea::placeholder { color: #A0A0A0 !important; } footer { display: none !important; } } """ # --- Gradio UI Definition --- with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), css=CUSTOM_CSS, title="MediAgent AI") as demo: conversation_state = gr.State(value={"history": []}) session_id = gr.State(lambda: str(uuid.uuid4())) gr.Markdown("""

🧬 MediAgent AI

Your Smart, Role-Aware AI Health Navigator

""") with gr.Row(): gr.Markdown(""" 💡 Example Prompts: """) with gr.Group(elem_id="role-selector"): user_role = gr.Radio( ["patient", "doctor"], label="👤 Select Your Role", value="patient", info="The AI will adapt its tools and communication style based on your role.", elem_id="user-role-radio", show_label=True ) gr.Markdown("ℹ️") chatbot = gr.Chatbot( label="Conversation", elem_id="chatbot", bubble_full_width=False, avatar_images=(None, "https://i.imgur.com/9k2p4t7.png"), show_copy_button=True ) with gr.Row(elem_id="input-row"): user_textbox = gr.Textbox( scale=4, show_label=False, placeholder="Type your health-related question here...", container=False, ) submit_btn = gr.Button("Send", variant="primary", scale=1, min_width=150, elem_id="send-button") loading_spinner = gr.Markdown("") with gr.Row(): clear_btn = gr.ClearButton( value="🔄 Start New Conversation", components=[chatbot, user_textbox, conversation_state] ) def handle_user_turn(user_input, chat_history, user_role_selection, current_state, sid): import time from gradio import processing # Show spinner gr.update(elem_id="loading-spinner", value="Thinking...") if not user_input.strip(): gr.update(elem_id="loading-spinner", value="") yield {chatbot: chat_history, conversation_state: current_state, user_textbox: user_input} return user_message_html = f"
{user_input}
" chat_history.append((user_message_html, None)) yield {chatbot: chat_history, user_textbox: ""} if not MODAL_BACKEND_URL: error_message = "### ❗ Configuration Error\n**Reason**: `MODAL_BACKEND_URL` environment variable is not set." error_message_html = f"
{error_message}
" chat_history[-1] = (user_message_html, error_message_html) gr.update(elem_id="loading-spinner", value="") yield {chatbot: chat_history} return headers = {"Content-Type": "application/json"} payload = {"user_input": user_input, "session_id": sid, "role": user_role_selection} try: response = requests.post(MODAL_BACKEND_URL, headers=headers, json=payload, timeout=300) response.raise_for_status() backend_response = response.json() bot_response_text = backend_response.get("final_markdown", "Sorry, I received an empty response.") except requests.exceptions.RequestException as e: bot_response_text = f"### ❗ Network Error\n**Reason**: Could not connect to the backend.\n**Details**: {str(e)}" bot_message_html = f"
{bot_response_text}
" chat_history[-1] = (user_message_html, bot_message_html) gr.update(elem_id="loading-spinner", value="") yield {chatbot: chat_history, conversation_state: current_state} submit_btn.click( fn=handle_user_turn, inputs=[user_textbox, chatbot, user_role, conversation_state, session_id], outputs=[chatbot, conversation_state, user_textbox], show_progress="hidden" ) user_textbox.submit( fn=handle_user_turn, inputs=[user_textbox, chatbot, user_role, conversation_state, session_id], outputs=[chatbot, conversation_state, user_textbox], show_progress="hidden" ) @clear_btn.click def clear_chat(): return {"history": []} if __name__ == "__main__": print("Gradio App Starting...") if not MODAL_BACKEND_URL: print("\nWARNING: The `MODAL_BACKEND_URL` environment variable is not set.") print("The application will run, but will show a configuration error.\n") demo.queue() demo.launch()