Spaces:
Running
Running
Mandark-droid
commited on
Commit
·
bb44e1f
1
Parent(s):
79f1857
Replace Trends plot with working MockTraceMind version
Browse files- 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
|
| 634 |
|
| 635 |
Args:
|
| 636 |
-
df: Leaderboard DataFrame with timestamp column
|
| 637 |
|
| 638 |
Returns:
|
| 639 |
-
Plotly figure
|
| 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 |
-
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
-
|
| 694 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 695 |
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
| 705 |
-
|
| 706 |
-
|
| 707 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 708 |
|
| 709 |
-
|
| 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 |
-
|
| 723 |
-
|
| 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 |
-
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|