Spaces:
Sleeping
Sleeping
| # gradio_app.py | |
| """ | |
| Simplified Gradio Interface for Medical Brain with Background Spiritual Monitoring. | |
| Single unified medical interface with invisible spiritual monitoring. | |
| No mode selector - just medical dialog with automatic spiritual support. | |
| Requirements: 1.3, 4.1, 4.2, 12.1, 12.2 | |
| """ | |
| import os | |
| import sys | |
| # Ensure project root is in Python path | |
| project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| if project_root not in sys.path: | |
| sys.path.insert(0, project_root) | |
| from dotenv import load_dotenv | |
| # Load environment variables | |
| load_dotenv() | |
| import gradio as gr | |
| # Import modularized components | |
| from src.interface.session_manager import SimplifiedSessionData | |
| from src.interface import stats_handlers | |
| from src.interface import chat_handlers | |
| from src.interface import prompt_handlers | |
| from src.interface import verification_handlers | |
| from src.interface import profile_handlers | |
| from src.interface import model_handlers | |
| from src.core.simplified_medical_app import SimplifiedMedicalApp | |
| from src.core.spiritual_state import SpiritualState | |
| from src.interface.enhanced_verification_interface import create_enhanced_verification_tab | |
| from src.interface.help_content import HELP_CONTENT | |
| try: | |
| from app_config import ( | |
| GRADIO_CONFIG, | |
| ENHANCED_VERIFICATION_CONFIG, | |
| FEATURE_FLAGS, | |
| is_feature_enabled | |
| ) | |
| except ImportError: | |
| GRADIO_CONFIG = {"theme": "soft", "show_api": False} | |
| ENHANCED_VERIFICATION_CONFIG = {"enabled": True} | |
| FEATURE_FLAGS = { | |
| "enhanced_verification_enabled": True, | |
| "standard_verification_enabled": True, | |
| "show_mode_navigation_hints": True, | |
| } | |
| def is_feature_enabled(feature_name: str) -> bool: | |
| return FEATURE_FLAGS.get(feature_name, False) | |
| def create_simplified_interface(): | |
| """ | |
| Create simplified Gradio interface. | |
| Single medical assistant interface with background spiritual monitoring. | |
| No mode selector - spiritual support is automatic and invisible. | |
| Requirements: 1.3, 4.1, 12.1 | |
| """ | |
| debug_mode = os.getenv("LOG_PROMPTS", "false").lower() == "true" | |
| # Theme setup | |
| theme_name = GRADIO_CONFIG.get("theme", "soft") | |
| if theme_name.lower() == "soft": | |
| theme = gr.themes.Soft() | |
| else: | |
| theme = gr.themes.Default() | |
| demo = gr.Blocks( | |
| title="π₯ Medical Assistant with Spiritual Support", | |
| analytics_enabled=False | |
| ) | |
| demo.theme = theme | |
| with demo: | |
| # Session state | |
| session_data = gr.State(value=None) | |
| # Header | |
| gr.Markdown("# π₯ Medical Assistant with Spiritual Support ποΈ") | |
| gr.Markdown("Your personal healthcare companion with integrated wellness support") | |
| if debug_mode: | |
| gr.Markdown("β οΈ **DEBUG MODE:** Prompts and responses are logged") | |
| # Session info | |
| session_info = gr.Markdown("π **Initializing session...**") | |
| # Initialize session | |
| def initialize_session(): | |
| """Initialize new user session.""" | |
| new_session = SimplifiedSessionData() | |
| session_info_text = f""" | |
| β **Session Ready** | |
| π Session: `{new_session.session_id[:8]}...` | |
| π Started: {new_session.created_at[:19]} | |
| """ | |
| return new_session, session_info_text | |
| # Main interface - using Tabs with elem_id for navigation | |
| main_tabs = gr.Tabs(elem_id="main_tabs") | |
| with main_tabs: | |
| # Note: The following tabs are intentionally hidden for now: | |
| # - βοΈ Edit Enhanced Datasets | |
| # - β Standard Verification | |
| # We keep the rest of the interface focused on Chat + Conversation Verification. | |
| # Chat tab | |
| with gr.TabItem("π¬ Chat", id="chat"): | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| chatbot = gr.Chatbot( | |
| label="π¬ Conversation", | |
| height=450 | |
| ) | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| label="Your message", | |
| placeholder="Type your health question...", | |
| scale=4 | |
| ) | |
| send_btn = gr.Button("π€ Send", scale=1, variant="primary") | |
| with gr.Row(): | |
| clear_btn = gr.Button("ποΈ Clear Chat", scale=1) | |
| # Conversation logging section | |
| gr.Markdown("### π Conversation Logs:") | |
| with gr.Row(): | |
| download_json_btn = gr.DownloadButton("π₯ Download JSON", scale=1, size="sm") | |
| download_csv_btn = gr.DownloadButton("π Download CSV", scale=1, size="sm") | |
| # Conversation verification is available in the dedicated | |
| # "π§Ύ Conversation Verification" tab. | |
| # Quick examples | |
| gr.Markdown("### β‘ Quick Start:") | |
| with gr.Row(): | |
| example_medical = gr.Button("π’ I am fine", size="sm") | |
| example_wellness = gr.Button("π‘ I'm feeling stressed", size="sm") | |
| example_help = gr.Button("π΄ Emotional crisis", size="sm") | |
| with gr.Column(scale=1): | |
| status_box = gr.Markdown( | |
| value="π Loading...", | |
| label="π Status" | |
| ) | |
| refresh_btn = gr.Button("π Check Status & Summary", size="sm") | |
| # Conversation statistics | |
| gr.Markdown("### π Conversation Stats") | |
| conversation_stats = gr.Markdown( | |
| value="No conversation yet", | |
| label="Statistics" | |
| ) | |
| # Debug info (only in debug mode) | |
| if debug_mode: | |
| gr.Markdown("### π§ Debug Info") | |
| debug_info = gr.Markdown(value="") | |
| # Provider Summary Panel (for RED flags) - always visible but content controlled | |
| with gr.Column(scale=1) as provider_summary_column: | |
| with gr.Group(visible=False) as provider_summary_content: | |
| gr.Markdown("### π Provider Summary") | |
| gr.Markdown("*For Spiritual Care Team*", elem_classes=["provider-subtitle"]) | |
| provider_summary_status = gr.Markdown( | |
| value="**Provider Summary Generated**\n\nA detailed summary has been generated for the spiritual care team. Use the Download button below to access the full summary." | |
| ) | |
| # Tabs for different summary views (Medical Brain Summary first by default) | |
| with gr.Tabs(): | |
| # Coherent Paragraph Tab (FIRST - Requirements 2.1-2.8) - Medical Brain compatibility | |
| with gr.TabItem("π Medical Brain Summary"): | |
| gr.Markdown("*Single paragraph format for Medical Brain compatibility - **Default View***") | |
| coherent_summary_display = gr.Textbox( | |
| value="", | |
| lines=8, | |
| label="Medical Brain Compatible Summary", | |
| interactive=False | |
| ) | |
| with gr.Row(): | |
| regenerate_coherent_btn = gr.Button( | |
| "π Regenerate Medical Brain Summary", | |
| size="sm", | |
| variant="secondary" | |
| ) | |
| download_coherent_btn = gr.DownloadButton( | |
| "π₯ Download Medical Brain Summary", | |
| size="sm", | |
| variant="secondary" | |
| ) | |
| # Structured Summary Tab (moved to second position) | |
| with gr.TabItem("π Structured Summary"): | |
| provider_summary_display = gr.HTML(value="") | |
| with gr.Row(): | |
| download_summary_btn = gr.DownloadButton( | |
| "π₯ Download Full Summary", | |
| size="sm", | |
| variant="secondary" | |
| ) | |
| clear_summary_btn = gr.Button( | |
| "ποΈ Clear", | |
| size="sm" | |
| ) | |
| # Conversation Verification tab (chat-derived) | |
| with gr.TabItem("π§Ύ Conversation Verification", id="conversation_verification"): | |
| gr.Markdown("## π§Ύ Conversation Verification (from Chat)") | |
| gr.Markdown( | |
| "Click **Generate** to build a verification session from the current chat. " | |
| "Review each exchange, mark it correct/incorrect, and download the session JSON." | |
| ) | |
| conv_verify_state = gr.State(value=None) # holds exported JSON path | |
| conv_verify_index = gr.State(value=0) | |
| conv_verify_records = gr.State(value=[]) | |
| with gr.Row(): | |
| generate_conv_verification_btn = gr.Button("π Generate from current chat", variant="primary") | |
| conv_verify_download_btn = gr.DownloadButton("β¬οΈ Download reviewed JSON", variant="secondary") | |
| conv_verify_download_csv_btn = gr.DownloadButton("π Download CSV", variant="secondary") | |
| conv_verify_status = gr.Markdown(value="", visible=True) | |
| conv_verify_exchange = gr.HTML(value="", label="Current Exchange") | |
| with gr.Row(): | |
| conv_correct_btn = gr.Button("β Correct", variant="primary") | |
| conv_incorrect_btn = gr.Button("β Incorrect") | |
| conv_prev_btn = gr.Button("β¬ οΈ Previous") | |
| conv_next_btn = gr.Button("Next β‘οΈ") | |
| # Shown only when marking Incorrect | |
| with gr.Row(visible=False) as conv_incorrect_comment_row: | |
| with gr.Column(scale=3): | |
| gr.Markdown("### Select Correct Classification:") | |
| conv_correct_classification = gr.Radio( | |
| choices=[ | |
| "π’ Should be GREEN - No distress", | |
| "π‘ Should be YELLOW - Needs clarification", | |
| "π΄ Should be RED - Spiritual distress" | |
| ], | |
| label="Correct Classification", | |
| interactive=True | |
| ) | |
| conv_incorrect_comment = gr.Textbox( | |
| label="Comment (why incorrect / what to fix)", | |
| placeholder="Add a short note for this exchange...", | |
| lines=3, | |
| ) | |
| with gr.Column(scale=1): | |
| conv_save_comment_btn = gr.Button("πΎ Save comment", variant="secondary") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| conv_position = gr.Markdown(value="") | |
| with gr.Column(scale=1): | |
| conv_stats = gr.HTML(value="") | |
| # Enhanced Verification Modes tab (hidden sub-tabs; kept but moved after Conversation Verification) | |
| if is_feature_enabled("enhanced_verification_enabled"): | |
| with gr.TabItem("π Enhanced Verification", id="enhanced_verification"): | |
| enhanced_verification_interface = create_enhanced_verification_tab() | |
| # Model Selection tab (second tab) | |
| with gr.TabItem("βοΈ Model Settings", id="model_settings"): | |
| gr.Markdown("## βοΈ AI Model Configuration") | |
| gr.Markdown("Select which AI models to use for different tasks. Changes apply to your current session.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### π Spiritual Monitor (Classifier)") | |
| spiritual_model = gr.Dropdown( | |
| choices=[ | |
| "gemini-2.5-flash", | |
| "gemini-2.0-flash", | |
| "gemini-3-flash-preview", | |
| "claude-sonnet-4-5-20250929", | |
| "claude-sonnet-4-20250514", | |
| "claude-3-7-sonnet-20250219" | |
| ], | |
| value="gemini-2.5-flash", | |
| label="Spiritual Distress Analyzer", | |
| interactive=True | |
| ) | |
| gr.Markdown("### π‘ Soft Spiritual Triage") | |
| soft_spiritual_triage_model = gr.Dropdown( | |
| choices=[ | |
| "claude-sonnet-4-5-20250929", | |
| "claude-sonnet-4-20250514", | |
| "claude-3-7-sonnet-20250219", | |
| "gemini-2.5-flash", | |
| "gemini-2.0-flash", | |
| "gemini-3-flash-preview" | |
| ], | |
| value="claude-sonnet-4-5-20250929", | |
| label="Soft Spiritual Triage", | |
| interactive=True | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("### π Triage Response Evaluator") | |
| triage_evaluate_model = gr.Dropdown( | |
| choices=[ | |
| "gemini-2.5-flash", | |
| "gemini-2.0-flash", | |
| "gemini-3-flash-preview", | |
| "claude-sonnet-4-5-20250929", | |
| "claude-sonnet-4-20250514", | |
| "claude-3-7-sonnet-20250219" | |
| ], | |
| value="gemini-2.5-flash", | |
| label="Triage Response Evaluator", | |
| interactive=True | |
| ) | |
| gr.Markdown("### π₯ Medical Assistant") | |
| medical_model = gr.Dropdown( | |
| choices=[ | |
| "claude-sonnet-4-5-20250929", | |
| "claude-sonnet-4-20250514", | |
| "claude-3-7-sonnet-20250219", | |
| "gemini-2.5-flash", | |
| "gemini-2.0-flash", | |
| "gemini-3-flash-preview" | |
| ], | |
| value="claude-sonnet-4-5-20250929", | |
| label="Medical Assistant", | |
| interactive=True | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("### π©Ί Soft Medical Triage") | |
| soft_triage_model = gr.Dropdown( | |
| choices=[ | |
| "claude-sonnet-4-5-20250929", | |
| "claude-sonnet-4-20250514", | |
| "claude-3-7-sonnet-20250219", | |
| "gemini-2.5-flash", | |
| "gemini-2.0-flash", | |
| "gemini-3-flash-preview" | |
| ], | |
| value="claude-sonnet-4-5-20250929", | |
| label="Soft Medical Triage", | |
| interactive=True | |
| ) | |
| gr.Markdown("### π¬ Medical Brain Summary Generator") | |
| spiritual_care_message_model = gr.Dropdown( | |
| choices=[ | |
| "claude-sonnet-4-5-20250929", | |
| "claude-sonnet-4-20250514", | |
| "claude-3-7-sonnet-20250219", | |
| "gemini-2.5-flash", | |
| "gemini-2.0-flash", | |
| "gemini-3-flash-preview" | |
| ], | |
| value="claude-sonnet-4-5-20250929", | |
| label="Medical Brain Summary Generator (uses Spiritual Care Message prompt)", | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| apply_models_btn = gr.Button("β Apply Model Settings", variant="primary", scale=2) | |
| reset_models_btn = gr.Button("π Reset to Defaults", scale=1) | |
| model_status = gr.HTML(value="", visible=True) | |
| # Edit Prompts tab | |
| with gr.TabItem("π§ Edit Prompts", id="edit_prompts"): | |
| gr.Markdown("## π§ Customize AI Prompts") | |
| gr.Markdown("β οΈ **Note:** Changes apply only to your current session.") | |
| # Prompt selector | |
| with gr.Row(): | |
| prompt_selector = gr.Dropdown( | |
| choices=[ | |
| "π Spiritual Monitor (Classifier)", | |
| "π‘ Soft Spiritual Triage", | |
| "π Triage Response Evaluator", | |
| "π₯ Medical Assistant", | |
| "π©Ί Soft Medical Triage", | |
| "π¬ Spiritual Care Message" | |
| ], | |
| value="π Spiritual Monitor (Classifier)", | |
| label="Select Prompt to Edit", | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| # Prompt editor | |
| prompt_editor = gr.Code( | |
| label="System Prompt", | |
| value="", | |
| language="markdown", | |
| lines=25, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| load_prompt_btn = gr.Button("π₯ Load Prompt", scale=1) | |
| apply_prompt_btn = gr.Button("β Apply Changes", variant="primary", scale=2) | |
| reset_prompt_btn = gr.Button("π Reset to Default", variant="secondary", scale=1) | |
| with gr.Row(): | |
| promote_prompt_btn = gr.Button("π€ Promote to File", variant="stop", scale=1) | |
| validate_prompt_btn = gr.Button("π Validate", variant="secondary", scale=1) | |
| prompt_status = gr.HTML( | |
| value="", | |
| visible=True, | |
| elem_classes=["prompt-status-container"] | |
| ) | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Prompt Info") | |
| prompt_info_display = gr.HTML(value=""" | |
| <div style="font-family: system-ui; padding: 1em; background-color: #f9fafb; border-radius: 8px;"> | |
| <p><strong>Select a prompt to edit</strong></p> | |
| <p><strong>Available prompts:</strong></p> | |
| <ul style="margin-left: 1em;"> | |
| <li>π Spiritual Monitor</li> | |
| <li>π‘ Triage Questions</li> | |
| <li>π Triage Evaluation</li> | |
| <li>π₯ Medical Assistant</li> | |
| <li>π©Ί Soft Triage</li> | |
| <li>π¬ Spiritual Care Message (used for Medical Brain Summary)</li> | |
| </ul> | |
| <p><strong>Tips:</strong></p> | |
| <ul style="margin-left: 1em;"> | |
| <li>Load prompt first</li> | |
| <li>Edit carefully</li> | |
| <li>Test changes</li> | |
| <li>Reset if needed</li> | |
| </ul> | |
| </div> | |
| """) | |
| # Patient Profiles tab | |
| with gr.TabItem("π₯ Patient Profiles", id="profiles"): | |
| gr.Markdown("## π₯ Patient Profile Management") | |
| gr.Markdown("Select a predefined profile or customize the current patient settings.") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Predefined Profiles") | |
| profile_selector = gr.Dropdown( | |
| choices=[ | |
| "π€ Default Profile (Serhii)", | |
| "π’ GREEN - Healthy Coping", | |
| "π‘ YELLOW - Mild Distress", | |
| "π‘ YELLOW - Grief & Loss", | |
| "π‘ YELLOW - Existential Questions", | |
| "π‘ YELLOW - Spiritual Disconnection", | |
| "π΄ RED - Crisis (Suicidal Risk)", | |
| "π΄ RED - Severe Hopelessness", | |
| "π΄ RED - Spiritual Crisis", | |
| "π« Cardiac Patient (Rehabilitation)", | |
| "π©Έ Diabetic Patient (Management)", | |
| "π₯ Post-Surgery (Recovery)", | |
| "π§ Mental Health (Anxiety/Depression)", | |
| "π΄ Elderly Patient (Chronic Care)", | |
| "π Athletic Patient (Injury/Training)" | |
| ], | |
| value="π€ Default Profile (Serhii)", | |
| label="Select Profile", | |
| interactive=True | |
| ) | |
| load_profile_btn = gr.Button("π₯ Load Profile", variant="primary") | |
| profile_status = gr.HTML(value="", visible=True) | |
| with gr.Column(scale=2): | |
| gr.Markdown("### βοΈ Current Patient Settings") | |
| with gr.Row(): | |
| patient_name = gr.Textbox( | |
| label="Patient Name", | |
| value="Serhii", | |
| interactive=True | |
| ) | |
| patient_phone = gr.Textbox( | |
| label="Phone Number", | |
| value="", | |
| placeholder="(555) 123-4567", | |
| interactive=True | |
| ) | |
| patient_age = gr.Number( | |
| label="Age", | |
| value=52, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| conditions = gr.Textbox( | |
| label="Medical Conditions (comma-separated)", | |
| value="Atrial fibrillation, Deep vein thrombosis, Obesity, Hypertension", | |
| lines=3, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| primary_goal = gr.Textbox( | |
| label="Primary Goal", | |
| value="Weight reduction and cardiovascular fitness improvement", | |
| lines=2, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| exercise_prefs = gr.Textbox( | |
| label="Exercise Preferences (comma-separated)", | |
| value="Swimming, Walking, Light cardio", | |
| lines=2, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| exercise_limits = gr.Textbox( | |
| label="Exercise Limitations (comma-separated)", | |
| value="Anticoagulation therapy, Post-thrombotic recovery", | |
| lines=2, | |
| interactive=True | |
| ) | |
| with gr.Row(): | |
| save_profile_btn = gr.Button("πΎ Save Current Profile", variant="primary", scale=1) | |
| reset_profile_btn = gr.Button("π Reset to Default", scale=1) | |
| profile_save_status = gr.HTML(value="", visible=True) | |
| # Instructions tab | |
| with gr.TabItem("π Help", id="help"): | |
| gr.Markdown(HELP_CONTENT) | |
| # Event handlers | |
| # Handlers moved to modular modules | |
| # Bind events | |
| demo.load( | |
| initialize_session, | |
| outputs=[session_data, session_info] | |
| ) | |
| # Send message | |
| send_btn.click( | |
| chat_handlers.handle_message, | |
| inputs=[msg, chatbot, session_data], | |
| outputs=[chatbot, status_box, session_data, msg, conversation_stats, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| msg.submit( | |
| chat_handlers.handle_message, | |
| inputs=[msg, chatbot, session_data], | |
| outputs=[chatbot, status_box, session_data, msg, conversation_stats, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| # Clear chat | |
| clear_btn.click( | |
| chat_handlers.handle_clear, | |
| inputs=[session_data], | |
| outputs=[chatbot, status_box, session_data, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| # Refresh status | |
| refresh_btn.click( | |
| stats_handlers.get_status, | |
| inputs=[session_data], | |
| outputs=[status_box, conversation_stats, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| # Example buttons | |
| example_medical.click( | |
| lambda h, s: chat_handlers.send_example_with_stats("I am fine", h, s), | |
| inputs=[chatbot, session_data], | |
| outputs=[chatbot, status_box, session_data, msg, conversation_stats, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| example_wellness.click( | |
| lambda h, s: chat_handlers.send_example_with_stats("I'm feeling stressed and overwhelmed lately", h, s), | |
| inputs=[chatbot, session_data], | |
| outputs=[chatbot, status_box, session_data, msg, conversation_stats, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| example_help.click( | |
| lambda h, s: chat_handlers.send_example_with_stats("I am currently experiencing an emotional crisis", h, s), | |
| inputs=[chatbot, session_data], | |
| outputs=[chatbot, status_box, session_data, msg, conversation_stats, provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| # Conversation logging buttons | |
| download_json_btn.click( | |
| stats_handlers.download_conversation_json, | |
| inputs=[session_data], | |
| outputs=[download_json_btn] | |
| ) | |
| download_csv_btn.click( | |
| stats_handlers.download_conversation_csv, | |
| inputs=[session_data], | |
| outputs=[download_csv_btn] | |
| ) | |
| # Provider Summary panel handlers | |
| download_summary_btn.click( | |
| stats_handlers.download_provider_summary, | |
| inputs=[session_data], | |
| outputs=[download_summary_btn] | |
| ) | |
| clear_summary_btn.click( | |
| stats_handlers.clear_provider_summary, | |
| inputs=[], | |
| outputs=[provider_summary_content, provider_summary_status, provider_summary_display, coherent_summary_display] | |
| ) | |
| # Coherent summary handlers (Medical Brain Summary - now first tab by default) | |
| regenerate_coherent_btn.click( | |
| stats_handlers.regenerate_coherent_summary, | |
| inputs=[session_data], | |
| outputs=[coherent_summary_display] | |
| ) | |
| download_coherent_btn.click( | |
| stats_handlers.download_coherent_summary, | |
| inputs=[session_data], | |
| outputs=[download_coherent_btn] | |
| ) | |
| # Conversation Verification events | |
| generate_conv_verification_btn.click( | |
| verification_handlers._generate_conv_verification, | |
| inputs=[session_data], | |
| outputs=[conv_verify_state, conv_verify_records, conv_verify_index, conv_verify_status, conv_verify_exchange, conv_position, conv_stats] | |
| ) | |
| conv_verify_download_btn.click( | |
| verification_handlers._download_reviewed_json, | |
| inputs=[conv_verify_state, conv_verify_records], | |
| outputs=[conv_verify_download_btn] | |
| ) | |
| conv_verify_download_csv_btn.click( | |
| verification_handlers._download_reviewed_csv, | |
| inputs=[conv_verify_state, conv_verify_records], | |
| outputs=[conv_verify_download_csv_btn] | |
| ) | |
| conv_correct_btn.click( | |
| verification_handlers._mark_conv_correct, | |
| inputs=[conv_verify_records, conv_verify_index], | |
| outputs=[ | |
| conv_verify_records, | |
| conv_verify_index, | |
| conv_verify_status, | |
| conv_verify_exchange, | |
| conv_position, | |
| conv_stats, | |
| conv_incorrect_comment_row, | |
| conv_incorrect_comment, | |
| conv_correct_classification, | |
| ] | |
| ) | |
| conv_incorrect_btn.click( | |
| verification_handlers._show_incorrect_comment_ui, | |
| inputs=[conv_verify_records, conv_verify_index], | |
| outputs=[ | |
| conv_verify_records, | |
| conv_verify_index, | |
| conv_verify_status, | |
| conv_verify_exchange, | |
| conv_position, | |
| conv_stats, | |
| conv_incorrect_comment_row, | |
| conv_incorrect_comment, | |
| conv_correct_classification, | |
| ] | |
| ) | |
| conv_save_comment_btn.click( | |
| verification_handlers._save_incorrect_comment, | |
| inputs=[conv_verify_records, conv_verify_index, conv_incorrect_comment, conv_correct_classification], | |
| outputs=[ | |
| conv_verify_records, | |
| conv_verify_index, | |
| conv_verify_status, | |
| conv_verify_exchange, | |
| conv_position, | |
| conv_stats, | |
| conv_incorrect_comment_row, | |
| conv_incorrect_comment, | |
| conv_correct_classification, | |
| ] | |
| ) | |
| conv_prev_btn.click( | |
| lambda records, idx: verification_handlers._nav_conv(records, idx, -1), | |
| inputs=[conv_verify_records, conv_verify_index], | |
| outputs=[conv_verify_index, conv_verify_exchange, conv_position, conv_stats, conv_incorrect_comment_row, conv_incorrect_comment, conv_correct_classification] | |
| ) | |
| conv_next_btn.click( | |
| lambda records, idx: verification_handlers._nav_conv(records, idx, 1), | |
| inputs=[conv_verify_records, conv_verify_index], | |
| outputs=[conv_verify_index, conv_verify_exchange, conv_position, conv_stats, conv_incorrect_comment_row, conv_incorrect_comment, conv_correct_classification] | |
| ) | |
| # Prompt editing events | |
| load_prompt_btn.click( | |
| prompt_handlers.load_prompt, | |
| inputs=[prompt_selector, session_data], | |
| outputs=[prompt_editor, prompt_info_display, prompt_status] | |
| ) | |
| apply_prompt_btn.click( | |
| prompt_handlers.apply_prompt_changes, | |
| inputs=[prompt_selector, prompt_editor, session_data], | |
| outputs=[prompt_status, session_data] | |
| ) | |
| reset_prompt_btn.click( | |
| prompt_handlers.reset_prompt, | |
| inputs=[prompt_selector, session_data], | |
| outputs=[prompt_editor, prompt_info_display, prompt_status, session_data] | |
| ) | |
| promote_prompt_btn.click( | |
| prompt_handlers.promote_prompt_to_file, | |
| inputs=[prompt_selector, session_data], | |
| outputs=[prompt_status, session_data] | |
| ) | |
| validate_prompt_btn.click( | |
| prompt_handlers.validate_prompt_syntax, | |
| inputs=[prompt_editor], | |
| outputs=[prompt_status] | |
| ) | |
| # Auto-load prompt when selector changes | |
| prompt_selector.change( | |
| prompt_handlers.load_prompt, | |
| inputs=[prompt_selector, session_data], | |
| outputs=[prompt_editor, prompt_info_display, prompt_status] | |
| ) | |
| # Bind model selection events | |
| apply_models_btn.click( | |
| model_handlers.apply_model_settings, | |
| inputs=[spiritual_model, soft_spiritual_triage_model, triage_evaluate_model, medical_model, soft_triage_model, spiritual_care_message_model, session_data], | |
| outputs=[model_status, session_data] | |
| ) | |
| reset_models_btn.click( | |
| model_handlers.reset_model_settings, | |
| inputs=[session_data], | |
| outputs=[model_status, session_data] | |
| ) | |
| # Bind profile events | |
| load_profile_btn.click( | |
| profile_handlers.load_profile, | |
| inputs=[profile_selector, session_data], | |
| outputs=[patient_name, patient_phone, patient_age, conditions, primary_goal, exercise_prefs, exercise_limits, profile_status] | |
| ) | |
| save_profile_btn.click( | |
| profile_handlers.save_profile, | |
| inputs=[patient_name, patient_phone, patient_age, conditions, primary_goal, exercise_prefs, exercise_limits, session_data], | |
| outputs=[profile_save_status] | |
| ) | |
| reset_profile_btn.click( | |
| profile_handlers.reset_profile, | |
| inputs=[session_data], | |
| outputs=[patient_name, patient_phone, patient_age, conditions, primary_goal, exercise_prefs, exercise_limits, profile_save_status] | |
| ) | |
| # Add CSS for prompt status container | |
| demo.css = """ | |
| .prompt-status-container { | |
| max-height: 300px !important; | |
| overflow-y: auto !important; | |
| margin: 0.5em 0 !important; | |
| } | |
| .prompt-status-container > div { | |
| max-height: 280px !important; | |
| overflow-y: auto !important; | |
| } | |
| """ | |
| return demo | |
| def main(): | |
| """Launch the simplified Gradio interface.""" | |
| demo = create_simplified_interface() | |
| # Get configuration | |
| server_name = os.getenv("GRADIO_SERVER_NAME", "0.0.0.0") | |
| server_port = int(os.getenv("GRADIO_SERVER_PORT", "7860")) | |
| share = os.getenv("GRADIO_SHARE", "false").lower() == "true" | |
| print(f"π Starting Simplified Medical Assistant...") | |
| print(f"π Server: http://{server_name}:{server_port}") | |
| demo.launch( | |
| server_name=server_name, | |
| server_port=server_port, | |
| share=share | |
| ) | |
| if __name__ == "__main__": | |
| main() | |