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, chat_history, user_role, sid): if not user_input.strip(): return chat_history, "" # Gradio's 'messages' type for chatbot expects dictionaries # Ensure chat_history is initialized with dictionaries or converted if not chat_history or not isinstance(chat_history[0], dict): # Convert existing tuples to dictionaries if needed, or start fresh new_chat_history = [] for user_msg, bot_msg in chat_history: if user_msg is not None: new_chat_history.append({"role": "user", "content": user_msg}) if bot_msg is not None: new_chat_history.append({"role": "assistant", "content": bot_msg}) chat_history = new_chat_history chat_history.append({"role": "user", "content": user_input}) # Changed to dictionary format if not MODAL_BACKEND_URL: # For an error, append as assistant message chat_history.append({"role": "assistant", "content": "❗ Configuration error: `MODAL_BACKEND_URL` not set."}) return chat_history, "" thinking_steps = ["Analyzing...", "Searching sources...", "Synthesizing..."] # Store the last user message to update it later # This assumes the last message is always the user's latest input last_user_message_index = len(chat_history) - 1 for step in thinking_steps: # Create a temporary 'thinking' message from the assistant temp_message = {"role": "assistant", "content": f"
{step}
"} # If there's an existing assistant thinking message, update it in place # Otherwise, append a new one if len(chat_history) > last_user_message_index + 1 and chat_history[last_user_message_index + 1]["role"] == "assistant": chat_history[last_user_message_index + 1] = temp_message else: chat_history.append(temp_message) yield chat_history, "" # Yield with the temporary thinking message time.sleep(0.4) 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 response received.") except Exception as e: reply = f"❗ Error: {str(e)}" # Update the last assistant message with the final reply # This should replace the thinking message or be appended if no thinking message was added if len(chat_history) > last_user_message_index + 1 and chat_history[last_user_message_index + 1]["role"] == "assistant": chat_history[last_user_message_index + 1] = {"role": "assistant", "content": reply} else: chat_history.append({"role": "assistant", "content": reply}) # Should not typically happen if thinking steps run yield chat_history, "" with gr.Blocks(css=CUSTOM_CSS, title="MediAgent AI") as demo: session_id = gr.State(lambda: str(uuid.uuid4())) gr.Markdown(""" # 🧬 MediAgent AI **Your AI Health Navigator**
MediAgent AI is a multilingual, role-based assistant that gives clear, cited medical answers.
""") # Changed Markdown content with gr.Row(): with gr.Column(scale=1): user_role = gr.Radio( choices=["patient", "doctor"], value="patient", label="Select Role", info="Choose your user type for tailored responses" ) with gr.Column(scale=3): chatbot = gr.Chatbot(label="Conversation", height=480, type='messages') # Added type='messages' with gr.Row(): user_textbox = gr.Textbox( placeholder="Ask your health question...", lines=1, scale=4 ) submit_btn = gr.Button("Send", elem_id="send-button", scale=1) examples = gr.Examples( examples=[ "What are the side effects of metformin?", "Explain Crohn’s disease vs Ulcerative Colitis for a doctor", "¿Cuáles son los síntomas de la hipertensión?", "Can I take ibuprofen with lisinopril? (for interactions)", # New example "What is the FDA label information for acetaminophen?", # New example "Are there any ongoing clinical trials for breast cancer?", # New example ], inputs=[user_textbox] ) # Changed Examples content gr.ClearButton([chatbot, user_textbox], value="🔄 Clear") submit_btn.click( fn=handle_user_turn, inputs=[user_textbox, chatbot, user_role, session_id], outputs=[chatbot, user_textbox] ) user_textbox.submit( fn=handle_user_turn, inputs=[user_textbox, chatbot, user_role, session_id], outputs=[chatbot, user_textbox] ) if __name__ == "__main__": demo.queue() demo.launch()