Spaces:
Sleeping
Sleeping
| # enhanced_progress_components.py | |
| """ | |
| Enhanced Progress UI Components for Verification Modes. | |
| Provides Gradio components for real-time progress tracking, statistics display, | |
| and session management across all verification modes. | |
| Requirements: 9.1, 9.2, 9.3, 9.4, 9.5 | |
| """ | |
| from __future__ import annotations | |
| import gradio as gr | |
| from typing import Tuple, Dict, Any, Optional | |
| from datetime import datetime, timedelta | |
| from src.core.enhanced_progress_tracker import ( | |
| EnhancedProgressTracker, | |
| VerificationMode, | |
| ProgressDisplayFormatter | |
| ) | |
| class EnhancedProgressComponents: | |
| """Enhanced progress tracking UI components.""" | |
| def create_progress_panel() -> Tuple[gr.Component, gr.Component, gr.Component, gr.Component, gr.Component]: | |
| """ | |
| Create comprehensive progress tracking panel. | |
| Returns: | |
| Tuple of (progress_display, accuracy_display, speed_display, error_display, time_display) | |
| """ | |
| # Main progress display with bar and position | |
| progress_display = gr.HTML( | |
| value=EnhancedProgressComponents._get_initial_progress_html(), | |
| label="Progress Tracking" | |
| ) | |
| # Running accuracy display | |
| accuracy_display = gr.Markdown( | |
| value="🎯 Current Accuracy: No verifications yet", | |
| label="Accuracy" | |
| ) | |
| # Processing speed display (for batch mode) | |
| speed_display = gr.Markdown( | |
| value="", | |
| label="Processing Speed", | |
| visible=False | |
| ) | |
| # Error count and status display | |
| error_display = gr.Markdown( | |
| value="", | |
| label="Error Status", | |
| visible=False | |
| ) | |
| # Time tracking display | |
| time_display = gr.Markdown( | |
| value="⏱️ Time: Ready to start", | |
| label="Session Time" | |
| ) | |
| return progress_display, accuracy_display, speed_display, error_display, time_display | |
| def create_compact_progress_panel() -> gr.Component: | |
| """ | |
| Create compact progress panel for smaller interfaces. | |
| Returns: | |
| Single HTML component with comprehensive progress info | |
| """ | |
| return gr.HTML( | |
| value=EnhancedProgressComponents._get_initial_progress_html(), | |
| label="Session Progress" | |
| ) | |
| def create_session_controls() -> Tuple[gr.Component, gr.Component, gr.Component]: | |
| """ | |
| Create session control buttons. | |
| Returns: | |
| Tuple of (pause_btn, resume_btn, reset_btn) | |
| """ | |
| pause_btn = gr.Button( | |
| "⏸️ Pause Session", | |
| variant="secondary", | |
| size="sm", | |
| visible=False | |
| ) | |
| resume_btn = gr.Button( | |
| "▶️ Resume Session", | |
| variant="primary", | |
| size="sm", | |
| visible=False | |
| ) | |
| reset_btn = gr.Button( | |
| "🔄 Reset Progress", | |
| variant="stop", | |
| size="sm" | |
| ) | |
| return pause_btn, resume_btn, reset_btn | |
| def update_progress_displays( | |
| tracker: EnhancedProgressTracker, | |
| use_compact: bool = False | |
| ) -> Tuple[str, str, str, str, str, bool, bool]: | |
| """ | |
| Update all progress displays based on tracker state. | |
| Args: | |
| tracker: Progress tracker instance | |
| use_compact: Whether to use compact display format | |
| Returns: | |
| Tuple of display values and visibility states | |
| """ | |
| if use_compact: | |
| # Return single HTML component | |
| progress_html = ProgressDisplayFormatter.create_progress_panel_html(tracker) | |
| return ( | |
| progress_html, # progress_display | |
| "", # accuracy_display (unused in compact) | |
| "", # speed_display (unused in compact) | |
| "", # error_display (unused in compact) | |
| "", # time_display (unused in compact) | |
| False, # speed_visible | |
| False # error_visible | |
| ) | |
| else: | |
| # Return individual components | |
| progress_html = ProgressDisplayFormatter.create_progress_panel_html(tracker) | |
| accuracy_display = tracker.get_accuracy_display() | |
| speed_display = tracker.get_processing_speed_display() | |
| error_display = tracker.get_error_display() | |
| time_display = tracker.get_time_tracking_display() | |
| # Determine visibility | |
| speed_visible = tracker.mode == VerificationMode.FILE_UPLOAD and tracker.stats.processing_speed > 0 | |
| error_visible = tracker.error_tracker.error_count > 0 | |
| return ( | |
| progress_html, | |
| accuracy_display, | |
| speed_display, | |
| error_display, | |
| time_display, | |
| speed_visible, | |
| error_visible | |
| ) | |
| def update_session_controls( | |
| tracker: EnhancedProgressTracker | |
| ) -> Tuple[bool, bool, bool]: | |
| """ | |
| Update session control button visibility. | |
| Args: | |
| tracker: Progress tracker instance | |
| Returns: | |
| Tuple of (pause_visible, resume_visible, reset_visible) | |
| """ | |
| session_active = tracker.stats.start_time is not None | |
| is_paused = tracker.is_paused | |
| pause_visible = session_active and not is_paused | |
| resume_visible = session_active and is_paused | |
| reset_visible = session_active | |
| return pause_visible, resume_visible, reset_visible | |
| def create_statistics_summary() -> gr.Component: | |
| """ | |
| Create detailed statistics summary component. | |
| Returns: | |
| Gradio component for statistics display | |
| """ | |
| return gr.Markdown( | |
| value=EnhancedProgressComponents._get_initial_stats_summary(), | |
| label="Session Statistics" | |
| ) | |
| def update_statistics_summary(tracker: EnhancedProgressTracker) -> str: | |
| """ | |
| Update statistics summary display. | |
| Args: | |
| tracker: Progress tracker instance | |
| Returns: | |
| Formatted statistics summary | |
| """ | |
| stats = tracker.get_comprehensive_stats() | |
| # Calculate additional metrics | |
| total_verified = stats["correct_count"] + stats["incorrect_count"] | |
| summary = f""" | |
| ### 📊 Session Statistics | |
| **Progress Overview:** | |
| - Messages Processed: {stats['processed_messages']}/{stats['total_messages']} ({stats['completion_percentage']:.1f}%) | |
| - Verifications Complete: {total_verified} | |
| - Current Accuracy: {stats['accuracy']:.1f}% | |
| **Performance Metrics:** | |
| - Correct Classifications: {stats['correct_count']} | |
| - Incorrect Classifications: {stats['incorrect_count']} | |
| """ | |
| if tracker.mode == VerificationMode.FILE_UPLOAD: | |
| summary += f"- Processing Speed: {stats['processing_speed']:.1f} messages/min\n" | |
| if stats["average_processing_time"] > 0: | |
| summary += f"- Average Time per Message: {stats['average_processing_time']:.1f}s\n" | |
| summary += f""" | |
| **Session Timing:** | |
| - Elapsed Time: {EnhancedProgressComponents._format_duration(stats['elapsed_time'])} | |
| """ | |
| if stats["estimated_remaining"]: | |
| remaining_str = EnhancedProgressComponents._format_duration(stats["estimated_remaining"]) | |
| summary += f"- Estimated Remaining: {remaining_str}\n" | |
| if stats["is_paused"]: | |
| summary += "- Status: ⏸️ **Paused**\n" | |
| if stats["error_count"] > 0: | |
| summary += f""" | |
| **Error Information:** | |
| - Total Errors: {stats['error_count']} | |
| - Can Continue: {'✅ Yes' if stats['can_continue'] else '❌ No'} | |
| """ | |
| return summary | |
| def create_error_details_panel() -> gr.Component: | |
| """ | |
| Create detailed error information panel. | |
| Returns: | |
| Gradio component for error details | |
| """ | |
| return gr.Markdown( | |
| value="", | |
| label="Error Details", | |
| visible=False | |
| ) | |
| def update_error_details(tracker: EnhancedProgressTracker) -> Tuple[str, bool]: | |
| """ | |
| Update error details panel. | |
| Args: | |
| tracker: Progress tracker instance | |
| Returns: | |
| Tuple of (error_details, visible) | |
| """ | |
| if tracker.error_tracker.error_count == 0: | |
| return "", False | |
| recent_errors = tracker.error_tracker.get_recent_errors(5) | |
| details = f""" | |
| ### ⚠️ Error Details | |
| **Total Errors:** {tracker.error_tracker.error_count} | |
| **Can Continue Processing:** {'✅ Yes' if tracker.error_tracker.can_continue else '❌ No'} | |
| **Recent Errors:** | |
| """ | |
| for i, (error_msg, timestamp) in enumerate(recent_errors, 1): | |
| time_str = timestamp.strftime("%H:%M:%S") | |
| details += f"{i}. `{time_str}` - {error_msg}\n" | |
| if tracker.error_tracker.error_count > len(recent_errors): | |
| details += f"\n*... and {tracker.error_tracker.error_count - len(recent_errors)} more errors*" | |
| return details, True | |
| def _get_initial_progress_html() -> str: | |
| """Get initial progress HTML.""" | |
| return """ | |
| <div style="font-family: system-ui; padding: 1rem; background: #f9fafb; border-radius: 8px; border: 1px solid #e5e7eb;"> | |
| <div style="text-align: center; color: #6b7280;"> | |
| <div style="font-size: 1.125rem; margin-bottom: 0.5rem;">📊 Ready to Start</div> | |
| <div style="width: 100%; background-color: #e5e7eb; border-radius: 4px; height: 8px;"> | |
| <div style="width: 0%; background-color: #3b82f6; border-radius: 4px; height: 8px;"></div> | |
| </div> | |
| <div style="margin-top: 0.5rem; font-size: 0.875rem;">Select a dataset or enter messages to begin</div> | |
| </div> | |
| </div> | |
| """ | |
| def _get_initial_stats_summary() -> str: | |
| """Get initial statistics summary.""" | |
| return """ | |
| ### 📊 Session Statistics | |
| **Progress Overview:** | |
| - Messages Processed: 0/0 (0%) | |
| - Verifications Complete: 0 | |
| - Current Accuracy: 0% | |
| **Performance Metrics:** | |
| - Correct Classifications: 0 | |
| - Incorrect Classifications: 0 | |
| **Session Timing:** | |
| - Elapsed Time: 0s | |
| - Status: Ready to start | |
| """ | |
| def _format_duration(seconds: float) -> str: | |
| """Format duration in seconds to human-readable string.""" | |
| if seconds is None or seconds <= 0: | |
| return "0s" | |
| total_seconds = int(seconds) | |
| if total_seconds < 60: | |
| return f"{total_seconds}s" | |
| elif total_seconds < 3600: | |
| minutes = total_seconds // 60 | |
| seconds = total_seconds % 60 | |
| return f"{minutes}m {seconds}s" | |
| else: | |
| hours = total_seconds // 3600 | |
| minutes = (total_seconds % 3600) // 60 | |
| return f"{hours}h {minutes}m" | |
| class ProgressTrackingMixin: | |
| """Mixin class for adding progress tracking to verification interfaces.""" | |
| def __init__(self, mode: VerificationMode): | |
| """Initialize progress tracking.""" | |
| self.progress_tracker = EnhancedProgressTracker(mode) | |
| self.progress_components = None | |
| def setup_progress_tracking(self, total_messages: int = 0) -> None: | |
| """ | |
| Setup progress tracking for a session. | |
| Args: | |
| total_messages: Total number of messages to process | |
| """ | |
| self.progress_tracker = EnhancedProgressTracker(self.progress_tracker.mode, total_messages) | |
| self.progress_tracker.start_session() | |
| def record_verification_with_timing(self, is_correct: bool, start_time: datetime = None) -> None: | |
| """ | |
| Record verification with automatic timing. | |
| Args: | |
| is_correct: Whether verification was correct | |
| start_time: When processing started (for timing calculation) | |
| """ | |
| processing_time = None | |
| if start_time: | |
| processing_time = (datetime.now() - start_time).total_seconds() | |
| self.progress_tracker.record_verification(is_correct, processing_time) | |
| def get_progress_updates(self, use_compact: bool = False) -> Tuple: | |
| """ | |
| Get all progress display updates. | |
| Args: | |
| use_compact: Whether to use compact display | |
| Returns: | |
| Tuple of display updates | |
| """ | |
| return EnhancedProgressComponents.update_progress_displays( | |
| self.progress_tracker, use_compact | |
| ) | |
| def handle_session_pause(self) -> Tuple[bool, bool, bool]: | |
| """ | |
| Handle session pause and return control states. | |
| Returns: | |
| Tuple of control button visibility states | |
| """ | |
| self.progress_tracker.pause_session() | |
| return EnhancedProgressComponents.update_session_controls(self.progress_tracker) | |
| def handle_session_resume(self) -> Tuple[bool, bool, bool]: | |
| """ | |
| Handle session resume and return control states. | |
| Returns: | |
| Tuple of control button visibility states | |
| """ | |
| self.progress_tracker.resume_session() | |
| return EnhancedProgressComponents.update_session_controls(self.progress_tracker) |