# enhanced_verification_ui.py """ Enhanced Verification UI Components for Multi-Mode Verification. Provides interface components for mode selection, session resumption, and enhanced verification workflows across different modes. Requirements: 1.1, 1.2, 1.3, 1.4, 1.5 """ import gradio as gr from typing import List, Dict, Tuple, Optional, Any from dataclasses import dataclass from datetime import datetime import uuid from src.core.verification_models import ( EnhancedVerificationSession, VerificationRecord, TestMessage, TestDataset, ) from src.core.verification_store import JSONVerificationStore from src.core.test_datasets import TestDatasetManager from src.interface.enhanced_dataset_interface import EnhancedDatasetInterfaceController @dataclass class ModeSelectionState: """State container for mode selection interface.""" current_mode: Optional[str] = None incomplete_sessions: List[EnhancedVerificationSession] = None selected_session: Optional[EnhancedVerificationSession] = None def __post_init__(self): if self.incomplete_sessions is None: self.incomplete_sessions = [] class EnhancedVerificationUIComponents: """Enhanced UI components for multi-mode verification.""" # Mode definitions with descriptions MODE_OPTIONS = { "enhanced_dataset": { "icon": "📊", "title": "Enhanced Datasets", "description": "Use existing test datasets with editing capabilities. Add, modify, or delete test cases to customize datasets for specific testing scenarios.", "features": [ "Edit existing datasets", "Add new test cases", "Modify message text and classifications", "Delete test cases with confirmation", "Dataset versioning and backup" ] }, "manual_input": { "icon": "✏️", "title": "Manual Input", "description": "Manually enter individual messages for immediate testing. Perfect for exploring edge cases or testing specific scenarios in real-time.", "features": [ "Real-time message classification", "Immediate feedback collection", "Session results accumulation", "Quick testing of specific cases", "Export manual input results" ] }, "file_upload": { "icon": "📁", "title": "File Upload", "description": "Upload CSV or XLSX files containing test messages for batch processing. Ideal for large-scale testing with pre-prepared datasets.", "features": [ "CSV and XLSX file support", "Batch processing with progress tracking", "Automated verification against expected results", "File format validation and error reporting", "Comprehensive export options" ] } } @staticmethod def create_mode_selection_interface() -> gr.Blocks: """ Create the main mode selection interface. Returns: Gradio Blocks component for mode selection """ with gr.Blocks() as mode_selection: # Header gr.Markdown("# 🔍 Enhanced Verification Modes") gr.Markdown("Choose your verification approach based on your testing needs and data source.") # Incomplete sessions section incomplete_sessions_section = gr.Row(visible=False) with incomplete_sessions_section: with gr.Column(): gr.Markdown("## 📋 Resume Previous Sessions") gr.Markdown("You have incomplete verification sessions. You can resume where you left off or start a new session.") incomplete_sessions_display = gr.HTML( value="", label="Incomplete Sessions" ) with gr.Row(): resume_session_btn = gr.Button( "▶️ Resume Selected Session", variant="primary", scale=2 ) clear_sessions_btn = gr.Button( "🗑️ Clear All Sessions", variant="secondary", scale=1 ) # Mode selection cards gr.Markdown("## 🎯 Select Verification Mode") with gr.Row(): # Enhanced Dataset Mode with gr.Column(scale=1): mode_info = EnhancedVerificationUIComponents.MODE_OPTIONS["enhanced_dataset"] gr.Markdown(f"### {mode_info['icon']} {mode_info['title']}") gr.Markdown(mode_info["description"]) gr.Markdown("**Features:**") for feature in mode_info["features"]: gr.Markdown(f"• {feature}") enhanced_dataset_btn = gr.Button( f"{mode_info['icon']} Start Enhanced Dataset Mode", variant="primary", size="lg" ) # Manual Input Mode with gr.Column(scale=1): mode_info = EnhancedVerificationUIComponents.MODE_OPTIONS["manual_input"] gr.Markdown(f"### {mode_info['icon']} {mode_info['title']}") gr.Markdown(mode_info["description"]) gr.Markdown("**Features:**") for feature in mode_info["features"]: gr.Markdown(f"• {feature}") manual_input_btn = gr.Button( f"{mode_info['icon']} Start Manual Input Mode", variant="primary", size="lg" ) # File Upload Mode with gr.Column(scale=1): mode_info = EnhancedVerificationUIComponents.MODE_OPTIONS["file_upload"] gr.Markdown(f"### {mode_info['icon']} {mode_info['title']}") gr.Markdown(mode_info["description"]) gr.Markdown("**Features:**") for feature in mode_info["features"]: gr.Markdown(f"• {feature}") file_upload_btn = gr.Button( f"{mode_info['icon']} Start File Upload Mode", variant="primary", size="lg" ) # Progress preservation warning progress_warning = gr.Markdown( "", visible=False, label="Progress Warning" ) # Confirmation dialog for mode switching mode_switch_dialog = gr.Row(visible=False) with mode_switch_dialog: with gr.Column(): gr.Markdown("### ⚠️ Switch Mode Confirmation") switch_warning_text = gr.Markdown( "You have unsaved progress in the current mode. What would you like to do?", label="Warning" ) with gr.Row(): save_and_switch_btn = gr.Button( "💾 Save Progress & Switch", variant="primary", scale=2 ) discard_and_switch_btn = gr.Button( "🗑️ Discard & Switch", variant="secondary", scale=1 ) cancel_switch_btn = gr.Button( "❌ Cancel", scale=1 ) # Status message status_message = gr.Markdown( "", visible=True, label="Status" ) # Hidden state for tracking current_mode_state = gr.State(value=None) incomplete_sessions_state = gr.State(value=[]) selected_session_state = gr.State(value=None) pending_mode_switch = gr.State(value=None) return mode_selection @staticmethod def render_incomplete_sessions_display(sessions: List[EnhancedVerificationSession]) -> str: """ Render HTML display for incomplete sessions. Args: sessions: List of incomplete verification sessions Returns: HTML string for displaying incomplete sessions """ if not sessions: return "" html = """
💡 Tip: Click on a session above to select it, then click "Resume Selected Session" to continue where you left off.
""" return html @staticmethod def _format_time_ago(timestamp: datetime) -> str: """ Format timestamp as time ago string. Args: timestamp: Datetime to format Returns: Human-readable time ago string """ now = datetime.now() diff = now - timestamp if diff.days > 0: return f"{diff.days} day{'s' if diff.days != 1 else ''} ago" elif diff.seconds > 3600: hours = diff.seconds // 3600 return f"{hours} hour{'s' if hours != 1 else ''} ago" elif diff.seconds > 60: minutes = diff.seconds // 60 return f"{minutes} minute{'s' if minutes != 1 else ''} ago" else: return "Just now" @staticmethod def check_for_incomplete_sessions(store: JSONVerificationStore) -> Tuple[bool, List[EnhancedVerificationSession], str]: """ Check for incomplete sessions and return display information. Args: store: Verification data store Returns: Tuple of (has_incomplete, sessions_list, display_html) """ try: incomplete_sessions = store.get_incomplete_sessions() # Filter to only enhanced sessions for this interface enhanced_sessions = [ s for s in incomplete_sessions if isinstance(s, EnhancedVerificationSession) ] if enhanced_sessions: display_html = EnhancedVerificationUIComponents.render_incomplete_sessions_display(enhanced_sessions) return True, enhanced_sessions, display_html else: return False, [], "" except Exception as e: error_html = f"""Could not load incomplete sessions: {str(e)}
No messages processed yet.
", label="Recent Results" ) # Export options gr.Markdown("## 💾 Export Results") with gr.Column(): export_csv_btn = gr.Button("📄 Export CSV", size="sm") export_json_btn = gr.Button("📋 Export JSON", size="sm") clear_session_btn = gr.Button("🗑️ Clear Session", size="sm") # Status messages status_message = gr.Markdown("", visible=True) return manual_input_interface @staticmethod def create_file_upload_interface() -> gr.Blocks: """ Create file upload mode interface. Returns: Gradio Blocks component for file upload mode """ with gr.Blocks() as file_upload_interface: gr.Markdown("# 📁 File Upload Mode") gr.Markdown("Upload CSV or XLSX files containing test messages for batch processing and verification.") # Back to mode selection back_to_modes_btn = gr.Button("← Back to Mode Selection", size="sm") with gr.Row(): with gr.Column(scale=2): # File upload area gr.Markdown("## 📤 Upload Test File") file_upload = gr.File( label="Select CSV or XLSX File", file_types=[".csv", ".xlsx"], file_count="single" ) # Format requirements gr.Markdown(""" **Required Columns:** - `message` or `text`: Patient message text - `expected_classification` or `classification`: Expected result (GREEN, YELLOW, RED) **Supported Formats:** - CSV files (comma, semicolon, or tab delimited) - XLSX files (first worksheet only) """) # Template download with gr.Row(): download_csv_template_btn = gr.Button("📄 Download CSV Template", size="sm") download_xlsx_template_btn = gr.Button("📊 Download XLSX Template", size="sm") # File validation results (initially hidden) validation_results = gr.Row(visible=False) with validation_results: with gr.Column(): gr.Markdown("### ✅ File Validation Results") validation_summary = gr.Markdown("", label="Summary") file_preview = gr.HTML("", label="Preview") start_processing_btn = gr.Button( "🚀 Start Batch Processing", variant="primary", size="lg" ) with gr.Column(scale=1): # Processing status gr.Markdown("## 📊 Processing Status") processing_stats = gr.Markdown( """ **File:** Not uploaded **Total Messages:** 0 **Processed:** 0 **Accuracy:** 0% """, label="Status" ) # Progress bar progress_bar = gr.HTML( value="", label="Progress" ) # Batch results gr.Markdown("## 📋 Batch Results") batch_results = gr.HTML( value="No file processed yet.
", label="Results" ) # Export options gr.Markdown("## 💾 Export Results") with gr.Column(): export_detailed_csv_btn = gr.Button("📄 Export Detailed CSV", size="sm") export_summary_btn = gr.Button("📊 Export Summary", size="sm") export_errors_btn = gr.Button("⚠️ Export Errors", size="sm") # Status messages status_message = gr.Markdown("", visible=True) return file_upload_interface @staticmethod def create_enhanced_dataset_interface_with_handlers() -> gr.Blocks: """ Create enhanced dataset mode interface with complete event handlers. Returns: Gradio Blocks component for enhanced dataset mode with functionality """ # Initialize controller controller = EnhancedDatasetInterfaceController() with gr.Blocks() as enhanced_dataset_interface: gr.Markdown("# 📊 Enhanced Dataset Mode") gr.Markdown("Select and customize test datasets for verification. You can edit existing datasets or create new test cases.") # Status and error messages status_message = gr.Markdown("", visible=True) return enhanced_dataset_interface def create_enhanced_verification_app() -> gr.Blocks: """ Create the complete enhanced verification application. Returns: Gradio Blocks application with mode selection and all verification modes """ # Initialize store store = JSONVerificationStore() with gr.Blocks(title="Enhanced Verification Modes") as app: # Application state current_mode = gr.State(value=None) current_session = gr.State(value=None) # Mode selection interface mode_selection = EnhancedVerificationUIComponents.create_mode_selection_interface() # Individual mode interfaces (initially hidden) enhanced_dataset_interface = gr.Row(visible=False) with enhanced_dataset_interface: enhanced_dataset_ui = EnhancedVerificationUIComponents.create_enhanced_dataset_interface() manual_input_interface = gr.Row(visible=False) with manual_input_interface: manual_input_ui = EnhancedVerificationUIComponents.create_manual_input_interface() file_upload_interface = gr.Row(visible=False) with file_upload_interface: file_upload_ui = EnhancedVerificationUIComponents.create_file_upload_interface() # Event handlers for mode selection def initialize_app(): """Initialize the application and check for incomplete sessions.""" has_incomplete, sessions, display_html = EnhancedVerificationUIComponents.check_for_incomplete_sessions(store) if has_incomplete: return ( gr.Row(visible=True), # Show incomplete sessions section display_html, # Display sessions sessions, # Store sessions in state "✨ Welcome back! You have incomplete sessions." ) else: return ( gr.Row(visible=False), # Hide incomplete sessions section "", # Empty display [], # Empty sessions list "✨ Welcome to Enhanced Verification Modes! Choose a mode to get started." ) def switch_to_mode(mode_type: str, current_mode_val: str, current_session_val: EnhancedVerificationSession): """Switch to a specific verification mode.""" # Check if we need to show progress preservation warning has_progress = (current_session_val is not None and not current_session_val.is_complete and current_session_val.verified_count > 0) if has_progress and current_mode_val != mode_type: warning_msg, show_dialog = EnhancedVerificationUIComponents.create_mode_switch_confirmation( current_mode_val, mode_type, has_progress ) return ( gr.Row(visible=True), # Show confirmation dialog warning_msg, # Warning message mode_type, # Store pending mode switch current_mode_val, # Keep current mode current_session_val, # Keep current session f"⚠️ Confirm mode switch to {EnhancedVerificationUIComponents.MODE_OPTIONS[mode_type]['title']}" ) else: # Direct switch return perform_mode_switch(mode_type, current_session_val) def perform_mode_switch(mode_type: str, session_to_save: EnhancedVerificationSession = None): """Perform the actual mode switch.""" # Save current session if exists if session_to_save and not session_to_save.is_complete: store.save_session(session_to_save) # Hide all interfaces interfaces_visibility = [gr.Row(visible=False)] * 4 # mode_selection, enhanced_dataset, manual_input, file_upload # Show selected interface if mode_type == "enhanced_dataset": interfaces_visibility[1] = gr.Row(visible=True) elif mode_type == "manual_input": interfaces_visibility[2] = gr.Row(visible=True) elif mode_type == "file_upload": interfaces_visibility[3] = gr.Row(visible=True) else: interfaces_visibility[0] = gr.Row(visible=True) # Default to mode selection return ( *interfaces_visibility, gr.Row(visible=False), # Hide confirmation dialog "", # Clear warning message None, # Clear pending mode switch mode_type, # Set current mode None, # Clear current session (will be set by mode interface) f"✅ Switched to {EnhancedVerificationUIComponents.MODE_OPTIONS.get(mode_type, {}).get('title', 'Unknown')} mode" ) # Initialize app on load app.load( initialize_app, outputs=[ # These would be bound to actual components in the full implementation # For now, returning placeholder values ] ) return app with gr.Blocks() as enhanced_dataset_interface: gr.Markdown("# 📊 Enhanced Dataset Mode") gr.Markdown("Select and customize test datasets for verification. You can edit existing datasets or create new test cases.") # Back to mode selection back_to_modes_btn = gr.Button("← Back to Mode Selection", size="sm") # Application state current_dataset_state = gr.State(value=None) editing_mode_state = gr.State(value=False) selected_test_case_state = gr.State(value=None) verification_session_state = gr.State(value=None) # Dataset selection and editing interface with gr.Row(): with gr.Column(scale=2): gr.Markdown("## 📋 Select Dataset") # Dataset selector dataset_selector = gr.Dropdown( choices=[], label="Available Datasets", info="Choose a dataset to verify or edit", interactive=True ) with gr.Row(): load_dataset_btn = gr.Button("📥 Load Dataset", variant="primary", scale=2) edit_dataset_btn = gr.Button("✏️ Edit Dataset", variant="secondary", scale=1) create_new_btn = gr.Button("➕ Create New", variant="secondary", scale=1) with gr.Column(scale=1): gr.Markdown("## 📊 Dataset Information") dataset_info_display = gr.Markdown( "Select a dataset to view details", label="Dataset Details" ) # Dataset creation section (initially hidden) dataset_creation_section = gr.Row(visible=False) with dataset_creation_section: with gr.Column(): gr.Markdown("## ➕ Create New Dataset") with gr.Row(): with gr.Column(scale=2): new_dataset_name = gr.Textbox( label="Dataset Name", placeholder="e.g., Custom Test Messages", interactive=True ) with gr.Column(scale=1): template_selector = gr.Dropdown( choices=[], label="Template (Optional)", info="Start with a template", interactive=True ) new_dataset_description = gr.Textbox( label="Dataset Description", placeholder="Describe the purpose and content of this dataset...", lines=2, interactive=True ) with gr.Row(): create_dataset_btn = gr.Button("✨ Create Dataset", variant="primary", scale=2) cancel_create_btn = gr.Button("❌ Cancel", scale=1) # Dataset editing section (initially hidden) dataset_editing_section = gr.Row(visible=False) with dataset_editing_section: with gr.Column(): gr.Markdown("## ✏️ Edit Dataset") # Dataset metadata editing with gr.Row(): edit_dataset_name = gr.Textbox( label="Dataset Name", interactive=True ) edit_dataset_description = gr.Textbox( label="Dataset Description", lines=2, interactive=True ) # Test case list test_cases_display = gr.HTML( value="", label="Test Cases" ) # Add new test case gr.Markdown("### ➕ Add New Test Case") with gr.Row(): with gr.Column(scale=3): new_message_text = gr.Textbox( label="Message Text", placeholder="Enter patient message...", lines=3, interactive=True ) with gr.Column(scale=1): new_classification = gr.Radio( choices=[ ("🟢 GREEN - No Distress", "green"), ("🟡 YELLOW - Potential Distress", "yellow"), ("🔴 RED - Severe Distress", "red") ], label="Expected Classification", value="green", interactive=True ) with gr.Row(): add_test_case_btn = gr.Button("➕ Add Test Case", variant="primary", scale=2) save_dataset_btn = gr.Button("💾 Save Dataset", variant="secondary", scale=1) cancel_edit_btn = gr.Button("❌ Cancel", scale=1) # Verification interface (initially hidden) verification_section = gr.Row(visible=False) with verification_section: with gr.Column(): gr.Markdown("## 🔍 Dataset Verification") # Verification controls with gr.Row(): with gr.Column(scale=2): verifier_name_input = gr.Textbox( label="Verifier Name", placeholder="Enter your name...", interactive=True ) with gr.Column(scale=1): start_verification_btn = gr.Button( "🚀 Start Verification", variant="primary", size="lg" ) # Progress display verification_progress = gr.Markdown( "Ready to start verification", label="Progress" ) # Message review area (initially hidden) message_review_area = gr.Row(visible=False) with message_review_area: with gr.Column(scale=2): # Current message display current_message_display = gr.Textbox( label="📝 Patient Message", interactive=False, lines=4 ) # Classification results classifier_decision_display = gr.Markdown( "🔄 Loading...", label="🎯 Classifier Decision" ) classifier_confidence_display = gr.Markdown( "Loading...", label="📊 Confidence Level" ) classifier_indicators_display = gr.Markdown( "Loading...", label="🔍 Detected Indicators" ) # Verification buttons with gr.Row(): correct_classification_btn = gr.Button( "✓ Correct", variant="primary", scale=1 ) incorrect_classification_btn = gr.Button( "✗ Incorrect", variant="stop", scale=1 ) # Correction section (initially hidden) correction_section = gr.Row(visible=False) with correction_section: correction_selector = gr.Radio( choices=[ ("🟢 Should be GREEN - No Distress", "green"), ("🟡 Should be YELLOW - Potential Distress", "yellow"), ("🔴 Should be RED - Severe Distress", "red") ], label="Correct Classification", interactive=True ) correction_notes = gr.Textbox( label="Notes (Optional)", placeholder="Why is this incorrect?", lines=2, interactive=True ) submit_correction_btn = gr.Button("✓ Submit", variant="primary") with gr.Column(scale=1): # Session statistics gr.Markdown("### 📊 Session Statistics") session_stats_display = gr.Markdown( """ **Messages Processed:** 0 **Correct Classifications:** 0 **Incorrect Classifications:** 0 **Accuracy:** 0% """, label="Statistics" ) # Export options gr.Markdown("### 💾 Export Options") with gr.Column(): export_csv_btn = gr.Button("📄 Export CSV", size="sm") export_json_btn = gr.Button("📋 Export JSON", size="sm") export_xlsx_btn = gr.Button("📊 Export XLSX", size="sm") # Status and error messages status_message = gr.Markdown("", visible=True) # Event handlers def initialize_interface(): """Initialize the interface with datasets and templates.""" dataset_choices, dataset_info, status_msg, templates = controller.initialize_interface() template_choices = [ f"{t['name']} - {t['description']}" for t in templates ] return ( dataset_choices, # dataset_selector choices dataset_info, # dataset_info_display status_msg, # status_message template_choices # template_selector choices ) def on_dataset_selection_change(dataset_selection): """Handle dataset selection change.""" dataset_info, dataset_obj = controller.get_dataset_info(dataset_selection) return ( dataset_info, # dataset_info_display dataset_obj # current_dataset_state ) def on_load_dataset(current_dataset): """Handle load dataset for verification.""" if not current_dataset: return ( gr.Row(visible=False), # verification_section "❌ No dataset selected" # status_message ) return ( gr.Row(visible=True), # verification_section f"✅ Dataset '{current_dataset.name}' loaded for verification" # status_message ) def on_edit_dataset(current_dataset): """Handle edit dataset.""" if not current_dataset: return ( gr.Row(visible=False), # dataset_editing_section "", # edit_dataset_name "", # edit_dataset_description "", # test_cases_display "❌ No dataset selected" # status_message ) test_cases_html = controller.render_test_cases_display(current_dataset) return ( gr.Row(visible=True), # dataset_editing_section current_dataset.name, # edit_dataset_name current_dataset.description, # edit_dataset_description test_cases_html, # test_cases_display f"✅ Editing dataset '{current_dataset.name}'" # status_message ) def on_create_new(): """Handle create new dataset.""" return ( gr.Row(visible=True), # dataset_creation_section "✨ Create a new dataset" # status_message ) def on_create_dataset(name, description, template_selection): """Handle dataset creation.""" # Parse template type from selection template_type = None if template_selection: # Extract template type from selection string template_mapping = { "📝 Empty Dataset": "empty", "🎯 Sample Mixed Dataset": "sample_mixed", "🟢 Custom Green Messages": "custom_green", "🟡 Custom Yellow Messages": "custom_yellow", "🔴 Custom Red Messages": "custom_red" } for key, value in template_mapping.items(): if template_selection.startswith(key): template_type = value break success, message, dataset = controller.create_new_dataset(name, description, template_type) if success: # Refresh dataset list dataset_choices, _, _, _ = controller.initialize_interface() return ( gr.Row(visible=False), # dataset_creation_section dataset_choices, # dataset_selector choices dataset, # current_dataset_state message # status_message ) else: return ( gr.Row(visible=True), # dataset_creation_section (keep visible) gr.Dropdown(choices=[]), # dataset_selector (no change) None, # current_dataset_state message # status_message ) def on_add_test_case(current_dataset, message_text, classification): """Handle adding new test case.""" if not current_dataset: return ( None, # current_dataset_state "", # test_cases_display "", # new_message_text (clear) "❌ No dataset selected" # status_message ) success, message, updated_dataset = controller.add_test_case( current_dataset, message_text, classification ) if success: test_cases_html = controller.render_test_cases_display(updated_dataset) return ( updated_dataset, # current_dataset_state test_cases_html, # test_cases_display "", # new_message_text (clear) message # status_message ) else: return ( current_dataset, # current_dataset_state (no change) gr.HTML(value=""), # test_cases_display (no change) message_text, # new_message_text (keep) message # status_message ) def on_save_dataset(current_dataset): """Handle saving dataset.""" if not current_dataset: return "❌ No dataset to save" success, message = controller.save_dataset(current_dataset) return message def on_start_verification(current_dataset, verifier_name): """Handle starting verification session.""" if not current_dataset: return ( None, # verification_session_state gr.Row(visible=False), # message_review_area "❌ No dataset selected" # status_message ) success, message, session = controller.start_verification_session( current_dataset, verifier_name ) if success: # Load first message current_message, classification_result = controller.get_current_message_for_verification() if current_message: # Format classification results decision_badge = f"🎯 {classification_result.get('decision', 'Unknown').upper()}" confidence_text = f"📊 {classification_result.get('confidence', 0) * 100:.1f}% confident" indicators_text = "🔍 " + ", ".join(classification_result.get('indicators', ['No indicators'])) return ( session, # verification_session_state gr.Row(visible=True), # message_review_area current_message.text, # current_message_display decision_badge, # classifier_decision_display confidence_text, # classifier_confidence_display indicators_text, # classifier_indicators_display f"Progress: 1 of {len(current_dataset.messages)} messages", # verification_progress message # status_message ) else: return ( session, # verification_session_state gr.Row(visible=False), # message_review_area "", # current_message_display "", # classifier_decision_display "", # classifier_confidence_display "", # classifier_indicators_display "No messages to verify", # verification_progress "❌ No messages in dataset" # status_message ) else: return ( None, # verification_session_state gr.Row(visible=False), # message_review_area "", # current_message_display "", # classifier_decision_display "", # classifier_confidence_display "", # classifier_indicators_display "", # verification_progress message # status_message ) def on_correct_classification(): """Handle correct classification feedback.""" success, message, stats = controller.submit_verification_feedback(True) if success and not stats.get('is_complete', False): # Load next message current_message, classification_result = controller.get_current_message_for_verification() if current_message: decision_badge = f"🎯 {classification_result.get('decision', 'Unknown').upper()}" confidence_text = f"📊 {classification_result.get('confidence', 0) * 100:.1f}% confident" indicators_text = "🔍 " + ", ".join(classification_result.get('indicators', ['No indicators'])) stats_text = f""" **Messages Processed:** {stats['processed']} **Correct Classifications:** {stats['correct']} **Incorrect Classifications:** {stats['incorrect']} **Accuracy:** {stats['accuracy']:.1f}% """ return ( current_message.text, # current_message_display decision_badge, # classifier_decision_display confidence_text, # classifier_confidence_display indicators_text, # classifier_indicators_display f"Progress: {stats['processed'] + 1} of {stats['total']} messages", # verification_progress stats_text, # session_stats_display gr.Row(visible=False), # correction_section message # status_message ) else: # Session complete stats_text = f""" **Session Complete!** **Messages Processed:** {stats['processed']} **Correct Classifications:** {stats['correct']} **Incorrect Classifications:** {stats['incorrect']} **Final Accuracy:** {stats['accuracy']:.1f}% """ return ( "Session completed!", # current_message_display "✅ All messages verified", # classifier_decision_display "", # classifier_confidence_display "", # classifier_indicators_display "✅ Verification complete", # verification_progress stats_text, # session_stats_display gr.Row(visible=False), # correction_section message # status_message ) else: return ( gr.Textbox(value=""), # current_message_display (no change) gr.Markdown(value=""), # classifier_decision_display (no change) gr.Markdown(value=""), # classifier_confidence_display (no change) gr.Markdown(value=""), # classifier_indicators_display (no change) gr.Markdown(value=""), # verification_progress (no change) gr.Markdown(value=""), # session_stats_display (no change) gr.Row(visible=False), # correction_section message # status_message ) def on_incorrect_classification(): """Handle incorrect classification - show correction options.""" return ( gr.Row(visible=True), # correction_section "Please select the correct classification" # status_message ) def on_submit_correction(correction, notes): """Handle correction submission.""" success, message, stats = controller.submit_verification_feedback( False, correction, notes ) if success and not stats.get('is_complete', False): # Load next message current_message, classification_result = controller.get_current_message_for_verification() if current_message: decision_badge = f"🎯 {classification_result.get('decision', 'Unknown').upper()}" confidence_text = f"📊 {classification_result.get('confidence', 0) * 100:.1f}% confident" indicators_text = "🔍 " + ", ".join(classification_result.get('indicators', ['No indicators'])) stats_text = f""" **Messages Processed:** {stats['processed']} **Correct Classifications:** {stats['correct']} **Incorrect Classifications:** {stats['incorrect']} **Accuracy:** {stats['accuracy']:.1f}% """ return ( current_message.text, # current_message_display decision_badge, # classifier_decision_display confidence_text, # classifier_confidence_display indicators_text, # classifier_indicators_display f"Progress: {stats['processed'] + 1} of {stats['total']} messages", # verification_progress stats_text, # session_stats_display gr.Row(visible=False), # correction_section "", # correction_notes (clear) message # status_message ) else: # Session complete stats_text = f""" **Session Complete!** **Messages Processed:** {stats['processed']} **Correct Classifications:** {stats['correct']} **Incorrect Classifications:** {stats['incorrect']} **Final Accuracy:** {stats['accuracy']:.1f}% """ return ( "Session completed!", # current_message_display "✅ All messages verified", # classifier_decision_display "", # classifier_confidence_display "", # classifier_indicators_display "✅ Verification complete", # verification_progress stats_text, # session_stats_display gr.Row(visible=False), # correction_section "", # correction_notes (clear) message # status_message ) else: return ( gr.Textbox(value=""), # current_message_display (no change) gr.Markdown(value=""), # classifier_decision_display (no change) gr.Markdown(value=""), # classifier_confidence_display (no change) gr.Markdown(value=""), # classifier_indicators_display (no change) gr.Markdown(value=""), # verification_progress (no change) gr.Markdown(value=""), # session_stats_display (no change) gr.Row(visible=True), # correction_section (keep visible) notes, # correction_notes (keep) message # status_message ) def on_export_results(format_type): """Handle results export.""" success, message, file_path = controller.export_session_results(format_type) return message # Bind event handlers enhanced_dataset_interface.load( initialize_interface, outputs=[ dataset_selector, dataset_info_display, status_message, template_selector ] ) dataset_selector.change( on_dataset_selection_change, inputs=[dataset_selector], outputs=[dataset_info_display, current_dataset_state] ) load_dataset_btn.click( on_load_dataset, inputs=[current_dataset_state], outputs=[verification_section, status_message] ) edit_dataset_btn.click( on_edit_dataset, inputs=[current_dataset_state], outputs=[ dataset_editing_section, edit_dataset_name, edit_dataset_description, test_cases_display, status_message ] ) create_new_btn.click( on_create_new, outputs=[dataset_creation_section, status_message] ) create_dataset_btn.click( on_create_dataset, inputs=[new_dataset_name, new_dataset_description, template_selector], outputs=[ dataset_creation_section, dataset_selector, current_dataset_state, status_message ] ) cancel_create_btn.click( lambda: (gr.Row(visible=False), "❌ Dataset creation cancelled"), outputs=[dataset_creation_section, status_message] ) add_test_case_btn.click( on_add_test_case, inputs=[current_dataset_state, new_message_text, new_classification], outputs=[ current_dataset_state, test_cases_display, new_message_text, status_message ] ) save_dataset_btn.click( on_save_dataset, inputs=[current_dataset_state], outputs=[status_message] ) cancel_edit_btn.click( lambda: (gr.Row(visible=False), "❌ Dataset editing cancelled"), outputs=[dataset_editing_section, status_message] ) start_verification_btn.click( on_start_verification, inputs=[current_dataset_state, verifier_name_input], outputs=[ verification_session_state, message_review_area, current_message_display, classifier_decision_display, classifier_confidence_display, classifier_indicators_display, verification_progress, status_message ] ) correct_classification_btn.click( on_correct_classification, outputs=[ current_message_display, classifier_decision_display, classifier_confidence_display, classifier_indicators_display, verification_progress, session_stats_display, correction_section, status_message ] ) incorrect_classification_btn.click( on_incorrect_classification, outputs=[correction_section, status_message] ) submit_correction_btn.click( on_submit_correction, inputs=[correction_selector, correction_notes], outputs=[ current_message_display, classifier_decision_display, classifier_confidence_display, classifier_indicators_display, verification_progress, session_stats_display, correction_section, correction_notes, status_message ] ) export_csv_btn.click( lambda: on_export_results("csv"), outputs=[status_message] ) export_json_btn.click( lambda: on_export_results("json"), outputs=[status_message] ) export_xlsx_btn.click( lambda: on_export_results("xlsx"), outputs=[status_message] ) return enhanced_dataset_interface