diff --git a/frontend/src/pages/leaderboard/Leaderboard.tsx b/frontend/src/pages/leaderboard/Leaderboard.tsx
index 7e55744..74e5f1c 100644
--- a/frontend/src/pages/leaderboard/Leaderboard.tsx
+++ b/frontend/src/pages/leaderboard/Leaderboard.tsx
@@ -261,7 +261,7 @@ export default function Leaderboard() {
AI Model Performance Trend
-
+
diff --git a/frontend/src/pages/leaderboard/components/AiTrendChart.tsx b/frontend/src/pages/leaderboard/components/AiTrendChart.tsx
index 40835e8..8406da1 100644
--- a/frontend/src/pages/leaderboard/components/AiTrendChart.tsx
+++ b/frontend/src/pages/leaderboard/components/AiTrendChart.tsx
@@ -1,6 +1,14 @@
import { useEffect, useState } from "react";
import ReactECharts from "echarts-for-react";
-import { Box, Typography, CircularProgress } from "@mui/material";
+import {
+ Box,
+ Typography,
+ CircularProgress,
+ FormControl,
+ InputLabel,
+ Select,
+ MenuItem,
+} from "@mui/material";
import { fetchAiTrend, type AiTrendResponse } from "../../../api/api";
import {
formatMicrosecondsNum,
@@ -10,6 +18,7 @@ import { useThemeStore } from "../../../lib/store/themeStore";
interface AiTrendChartProps {
leaderboardId: string;
+ rankings?: Record>;
}
// Generate a consistent color from a string using hash
@@ -27,14 +36,78 @@ function hashStringToColor(str: string): string {
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
}
-export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) {
+export default function AiTrendChart({ leaderboardId, rankings }: AiTrendChartProps) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
+ const [selectedGpuType, setSelectedGpuType] = useState("");
const resolvedMode = useThemeStore((state) => state.resolvedMode);
const isDark = resolvedMode === "dark";
const textColor = isDark ? "#e0e0e0" : "#333";
+ const gpuTypes = data?.time_series ? Object.keys(data.time_series) : [];
+
+ useEffect(() => {
+ if (gpuTypes.length > 0 && !selectedGpuType && data?.time_series) {
+ // Find the GPU type with the most unique users (from overall rankings)
+ // that also has actual AI data entries
+ let maxUniqueUsers = 0;
+ let defaultGpuType = "";
+
+ for (const gpuType of gpuTypes) {
+ const gpuData = data.time_series[gpuType];
+ // Check if this GPU type has actual AI data entries
+ if (!gpuData || Object.keys(gpuData).length === 0) {
+ continue;
+ }
+
+ let hasEntries = false;
+ for (const model of Object.keys(gpuData)) {
+ if (gpuData[model].length > 0) {
+ hasEntries = true;
+ break;
+ }
+ }
+
+ if (!hasEntries) {
+ continue;
+ }
+
+ // Count unique users from overall rankings (not just AI submissions)
+ const rankingsForGpu = rankings?.[gpuType];
+ const uniqueUserCount = rankingsForGpu?.length ?? 0;
+
+ if (uniqueUserCount > maxUniqueUsers) {
+ maxUniqueUsers = uniqueUserCount;
+ defaultGpuType = gpuType;
+ }
+ }
+
+ // Fallback to first GPU type with AI data if no rankings match
+ if (!defaultGpuType) {
+ for (const gpuType of gpuTypes) {
+ const gpuData = data.time_series[gpuType];
+ if (gpuData && Object.keys(gpuData).length > 0) {
+ for (const model of Object.keys(gpuData)) {
+ if (gpuData[model].length > 0) {
+ defaultGpuType = gpuType;
+ break;
+ }
+ }
+ if (defaultGpuType) break;
+ }
+ }
+ }
+
+ // Final fallback to first GPU type
+ if (!defaultGpuType && gpuTypes.length > 0) {
+ defaultGpuType = gpuTypes[0];
+ }
+
+ setSelectedGpuType(defaultGpuType);
+ }
+ }, [gpuTypes, selectedGpuType, data?.time_series, rankings]);
+
useEffect(() => {
const loadData = async () => {
setLoading(true);
@@ -94,17 +167,37 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) {
);
}
- // For now, only render H100 data
- const h100Data = data.time_series["H100"];
- if (!h100Data || Object.keys(h100Data).length === 0) {
+ const selectedData = selectedGpuType ? data.time_series[selectedGpuType] : null;
+ if (!selectedData || Object.keys(selectedData).length === 0) {
return (
-
- No H100 AI data available
+
+
+
+ GPU Type
+
+
+
+
+
+ No {selectedGpuType || "AI"} data available
+
+
);
}
@@ -112,7 +205,7 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) {
// Build series for ECharts
const series: any[] = [];
- Object.entries(h100Data).forEach(([model, dataPoints]) => {
+ Object.entries(selectedData).forEach(([model, dataPoints]) => {
const color = hashStringToColor(model);
const sortedData = [...dataPoints].sort(
@@ -146,7 +239,7 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) {
const option = {
title: {
- text: "AI Model Performance Trend (H100)",
+ text: `AI Model Performance Trend (${selectedGpuType})`,
left: "center",
textStyle: {
fontSize: 16,
@@ -169,7 +262,7 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) {
},
},
legend: {
- data: Object.keys(h100Data),
+ data: Object.keys(selectedData),
bottom: 0,
textStyle: {
color: textColor,
@@ -229,5 +322,26 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) {
series,
};
- return ;
+ return (
+
+
+
+ GPU Type
+
+
+
+
+
+ );
}