Mandark-droid commited on
Commit
bb44e1f
·
1 Parent(s): 79f1857

Replace Trends plot with working MockTraceMind version

Browse files
Files changed (1) hide show
  1. components/analytics_charts.py +170 -130
components/analytics_charts.py CHANGED
@@ -630,146 +630,186 @@ def create_comparison_radar(runs: List[Dict[str, Any]]) -> go.Figure:
630
 
631
  def create_trends_plot(df: pd.DataFrame) -> go.Figure:
632
  """
633
- Create time series visualization of evaluation metrics over time
634
 
635
  Args:
636
- df: Leaderboard DataFrame with timestamp column
637
 
638
  Returns:
639
- Plotly figure with time series chart
640
  """
 
641
 
642
- if df.empty:
643
- return _create_empty_figure("No data available for trends")
644
-
645
- # Check if timestamp column exists
646
- if 'timestamp' not in df.columns:
647
- return _create_empty_figure("Missing timestamp column for trends analysis")
648
-
649
- # Convert timestamp to datetime
650
- df = df.copy()
651
  try:
652
- df['timestamp'] = pd.to_datetime(df['timestamp'])
653
- except Exception as e:
654
- return _create_empty_figure(f"Error parsing timestamp data: {str(e)}")
655
-
656
- # Remove rows with invalid timestamps
657
- df = df.dropna(subset=['timestamp'])
658
-
659
- if df.empty:
660
- return _create_empty_figure("No valid timestamp data available")
661
-
662
- # Sort by timestamp
663
- df = df.sort_values('timestamp')
664
-
665
- # Aggregate by date (in case multiple runs per day)
666
- df['date'] = df['timestamp'].dt.date
667
-
668
- # Check which metrics are available
669
- available_metrics = []
670
- agg_dict = {}
671
-
672
- if 'success_rate' in df.columns:
673
- agg_dict['success_rate'] = 'mean'
674
- available_metrics.append('success_rate')
675
- if 'avg_duration_ms' in df.columns:
676
- agg_dict['avg_duration_ms'] = 'mean'
677
- available_metrics.append('avg_duration_ms')
678
- if 'total_cost_usd' in df.columns:
679
- agg_dict['total_cost_usd'] = 'mean'
680
- available_metrics.append('total_cost_usd')
681
- if 'total_tokens' in df.columns:
682
- agg_dict['total_tokens'] = 'mean'
683
- available_metrics.append('total_tokens')
684
-
685
- if not agg_dict:
686
- return _create_empty_figure("No metrics available for trends analysis")
687
-
688
- daily_stats = df.groupby('date').agg(agg_dict).reset_index()
689
-
690
- if daily_stats.empty:
691
- return _create_empty_figure("No data after aggregation")
692
-
693
- # Create figure with secondary y-axis
694
- fig = go.Figure()
 
 
 
 
695
 
696
- # Success Rate
697
- if 'success_rate' in daily_stats.columns:
698
- fig.add_trace(go.Scatter(
699
- x=daily_stats['date'],
700
- y=daily_stats['success_rate'],
701
- name='Success Rate (%)',
702
- mode='lines+markers',
703
- line=dict(color='#2ECC71', width=3),
704
- marker=dict(size=8),
705
- yaxis='y1',
706
- hovertemplate='<b>Success Rate</b><br>Date: %{x}<br>Rate: %{y:.1f}%<extra></extra>'
707
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
 
709
- # Duration
710
- if 'avg_duration_ms' in daily_stats.columns:
711
- fig.add_trace(go.Scatter(
712
- x=daily_stats['date'],
713
- y=daily_stats['avg_duration_ms'],
714
- name='Avg Duration (ms)',
715
- mode='lines+markers',
716
- line=dict(color='#3498DB', width=3),
717
- marker=dict(size=8),
718
- yaxis='y2',
719
- hovertemplate='<b>Duration</b><br>Date: %{x}<br>Time: %{y:.0f}ms<extra></extra>'
720
- ))
721
 
722
- # Cost
723
- if 'total_cost_usd' in daily_stats.columns:
724
- fig.add_trace(go.Scatter(
725
- x=daily_stats['date'],
726
- y=daily_stats['total_cost_usd'],
727
- name='Avg Cost (USD)',
728
- mode='lines+markers',
729
- line=dict(color='#E67E22', width=3),
730
- marker=dict(size=8),
731
- yaxis='y2',
732
- hovertemplate='<b>Cost</b><br>Date: %{x}<br>Cost: $%{y:.4f}<extra></extra>'
733
- ))
734
 
735
- fig.update_layout(
736
- title={
737
- 'text': '📈 Evaluation Metrics Trends Over Time',
738
- 'x': 0.5,
739
- 'xanchor': 'center',
740
- 'font': {'size': 20}
741
- },
742
- xaxis=dict(
743
- title='Date',
744
- showgrid=True,
745
- gridcolor='lightgray'
746
- ),
747
- yaxis=dict(
748
- title='Success Rate (%)',
749
- titlefont=dict(color='#2ECC71'),
750
- tickfont=dict(color='#2ECC71'),
751
- showgrid=True,
752
- gridcolor='lightgray'
753
- ),
754
- yaxis2=dict(
755
- title='Duration (ms) / Cost (USD)',
756
- titlefont=dict(color='#3498DB'),
757
- tickfont=dict(color='#3498DB'),
758
- overlaying='y',
759
- side='right'
760
- ),
761
- hovermode='x unified',
762
- height=500,
763
- plot_bgcolor='white',
764
- paper_bgcolor='#f8f9fa',
765
- showlegend=True,
766
- legend=dict(
767
- orientation="h",
768
- yanchor="bottom",
769
- y=1.02,
770
- xanchor="right",
771
- x=1
772
  )
773
- )
774
 
775
- return fig
 
 
 
 
 
 
 
 
630
 
631
  def create_trends_plot(df: pd.DataFrame) -> go.Figure:
632
  """
633
+ Create trends visualization over time with enhanced GPU metrics
634
 
635
  Args:
636
+ df: Leaderboard DataFrame with timestamp or evaluation_date column
637
 
638
  Returns:
639
+ Plotly figure showing trends
640
  """
641
+ from plotly.subplots import make_subplots
642
 
 
 
 
 
 
 
 
 
 
643
  try:
644
+ # Use evaluation_date or timestamp depending on what's available
645
+ date_col = 'evaluation_date' if 'evaluation_date' in df.columns else 'timestamp'
646
+
647
+ if df.empty or date_col not in df.columns:
648
+ fig = go.Figure()
649
+ fig.add_annotation(text="No trend data available", showarrow=False)
650
+ return fig
651
+
652
+ # Convert date column to datetime to avoid type errors
653
+ df[date_col] = pd.to_datetime(df[date_col], errors='coerce')
654
+
655
+ # Sort by date column
656
+ df_sorted = df.sort_values(date_col)
657
+
658
+ # Check which GPU metrics are available
659
+ has_gpu_util = 'gpu_utilization_avg' in df.columns and df_sorted['gpu_utilization_avg'].notna().any()
660
+ has_gpu_memory = 'gpu_memory_avg_mib' in df.columns and df_sorted['gpu_memory_avg_mib'].notna().any()
661
+ has_gpu_temp = 'gpu_temperature_avg' in df.columns and df_sorted['gpu_temperature_avg'].notna().any()
662
+ has_power_cost = 'power_cost_total_usd' in df.columns and df_sorted['power_cost_total_usd'].notna().any()
663
+
664
+ # Determine number of subplots based on available data
665
+ num_plots = 2 # Always show success rate and cost
666
+ if has_gpu_util:
667
+ num_plots += 1
668
+ if has_gpu_memory:
669
+ num_plots += 1
670
+ if has_gpu_temp:
671
+ num_plots += 1
672
+ if has_power_cost:
673
+ num_plots += 1
674
+
675
+ # Create subplots
676
+ subplot_titles = ["Success Rate Over Time", "Cost Over Time"]
677
+ if has_gpu_util:
678
+ subplot_titles.append("GPU Utilization Over Time")
679
+ if has_gpu_memory:
680
+ subplot_titles.append("GPU Memory Usage Over Time")
681
+ if has_gpu_temp:
682
+ subplot_titles.append("GPU Temperature Over Time")
683
+ if has_power_cost:
684
+ subplot_titles.append("Power Cost Over Time")
685
+
686
+ fig = make_subplots(
687
+ rows=num_plots, cols=1,
688
+ subplot_titles=subplot_titles,
689
+ vertical_spacing=0.08
690
+ )
691
 
692
+ current_row = 1
693
+
694
+ # Success rate trend
695
+ fig.add_trace(
696
+ go.Scatter(
697
+ x=df_sorted[date_col],
698
+ y=df_sorted['success_rate'],
699
+ mode='lines+markers',
700
+ name='Success Rate',
701
+ line=dict(color='#3498DB', width=2),
702
+ marker=dict(size=6),
703
+ hovertemplate='<b>%{x}</b><br>Success Rate: %{y:.1f}%<extra></extra>'
704
+ ),
705
+ row=current_row, col=1
706
+ )
707
+ fig.update_yaxes(title_text="Success Rate (%)", row=current_row, col=1)
708
+ current_row += 1
709
+
710
+ # Cost trend
711
+ fig.add_trace(
712
+ go.Scatter(
713
+ x=df_sorted[date_col],
714
+ y=df_sorted['total_cost_usd'],
715
+ mode='lines+markers',
716
+ name='Cost (USD)',
717
+ line=dict(color='#E67E22', width=2),
718
+ marker=dict(size=6),
719
+ hovertemplate='<b>%{x}</b><br>Cost: $%{y:.4f}<extra></extra>'
720
+ ),
721
+ row=current_row, col=1
722
+ )
723
+ fig.update_yaxes(title_text="Cost (USD)", row=current_row, col=1)
724
+ current_row += 1
725
+
726
+ # GPU Utilization trend (if available)
727
+ if has_gpu_util:
728
+ gpu_data = df_sorted[df_sorted['gpu_utilization_avg'].notna()]
729
+ fig.add_trace(
730
+ go.Scatter(
731
+ x=gpu_data[date_col],
732
+ y=gpu_data['gpu_utilization_avg'],
733
+ mode='lines+markers',
734
+ name='GPU Utilization',
735
+ line=dict(color='#9B59B6', width=2),
736
+ marker=dict(size=6),
737
+ hovertemplate='<b>%{x}</b><br>GPU Util: %{y:.1f}%<extra></extra>'
738
+ ),
739
+ row=current_row, col=1
740
+ )
741
+ fig.update_yaxes(title_text="GPU Utilization (%)", row=current_row, col=1)
742
+ current_row += 1
743
+
744
+ # GPU Memory trend (if available)
745
+ if has_gpu_memory:
746
+ gpu_memory_data = df_sorted[df_sorted['gpu_memory_avg_mib'].notna()]
747
+ fig.add_trace(
748
+ go.Scatter(
749
+ x=gpu_memory_data[date_col],
750
+ y=gpu_memory_data['gpu_memory_avg_mib'],
751
+ mode='lines+markers',
752
+ name='GPU Memory',
753
+ line=dict(color='#1ABC9C', width=2),
754
+ marker=dict(size=6),
755
+ hovertemplate='<b>%{x}</b><br>GPU Memory: %{y:.0f} MiB<extra></extra>'
756
+ ),
757
+ row=current_row, col=1
758
+ )
759
+ fig.update_yaxes(title_text="GPU Memory (MiB)", row=current_row, col=1)
760
+ current_row += 1
761
+
762
+ # GPU Temperature trend (if available)
763
+ if has_gpu_temp:
764
+ gpu_temp_data = df_sorted[df_sorted['gpu_temperature_avg'].notna()]
765
+ fig.add_trace(
766
+ go.Scatter(
767
+ x=gpu_temp_data[date_col],
768
+ y=gpu_temp_data['gpu_temperature_avg'],
769
+ mode='lines+markers',
770
+ name='GPU Temperature',
771
+ line=dict(color='#E74C3C', width=2),
772
+ marker=dict(size=6),
773
+ hovertemplate='<b>%{x}</b><br>GPU Temp: %{y:.1f}°C<extra></extra>'
774
+ ),
775
+ row=current_row, col=1
776
+ )
777
+ fig.update_yaxes(title_text="GPU Temperature (°C)", row=current_row, col=1)
778
+ current_row += 1
779
+
780
+ # Power Cost trend (if available)
781
+ if has_power_cost:
782
+ power_cost_data = df_sorted[df_sorted['power_cost_total_usd'].notna()]
783
+ fig.add_trace(
784
+ go.Scatter(
785
+ x=power_cost_data[date_col],
786
+ y=power_cost_data['power_cost_total_usd'],
787
+ mode='lines+markers',
788
+ name='Power Cost',
789
+ line=dict(color='#F39C12', width=2),
790
+ marker=dict(size=6),
791
+ hovertemplate='<b>%{x}</b><br>Power Cost: $%{y:.4f}<extra></extra>'
792
+ ),
793
+ row=current_row, col=1
794
+ )
795
+ fig.update_yaxes(title_text="Power Cost (USD)", row=current_row, col=1)
796
 
797
+ fig.update_xaxes(title_text="Date", row=num_plots, col=1)
 
 
 
 
 
 
 
 
 
 
 
798
 
799
+ # Calculate dynamic height based on number of plots
800
+ plot_height = max(400, num_plots * 200)
 
 
 
 
 
 
 
 
 
 
801
 
802
+ fig.update_layout(
803
+ height=plot_height,
804
+ showlegend=False,
805
+ margin=dict(l=50, r=50, t=50, b=50)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
  )
 
807
 
808
+ return fig
809
+ except Exception as e:
810
+ print(f"[ERROR] Creating trends plot: {e}")
811
+ import traceback
812
+ traceback.print_exc()
813
+ fig = go.Figure()
814
+ fig.add_annotation(text=f"Error creating trends: {str(e)}", showarrow=False)
815
+ return fig