From ffe660f75a2f34012eacc3bee35db7a9060e9d03 Mon Sep 17 00:00:00 2001 From: Jack-Khuu Date: Tue, 10 Feb 2026 16:29:33 -0800 Subject: [PATCH 1/2] Add the ability to choose which GPU is shown in AITrends --- .../leaderboard/components/AiTrendChart.tsx | 113 +++++++++++++++--- 1 file changed, 98 insertions(+), 15 deletions(-) diff --git a/frontend/src/pages/leaderboard/components/AiTrendChart.tsx b/frontend/src/pages/leaderboard/components/AiTrendChart.tsx index 40835e8..c46f633 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, @@ -31,10 +39,44 @@ export default function AiTrendChart({ leaderboardId }: 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 with successful submissions + let maxUniqueUsers = 0; + let defaultGpuType = gpuTypes[0]; + + for (const gpuType of gpuTypes) { + const gpuData = data.time_series[gpuType]; + if (gpuData) { + // Collect unique user IDs across all models for this GPU type + const uniqueUserIds = new Set(); + for (const model of Object.keys(gpuData)) { + const dataPoints = gpuData[model]; + dataPoints.forEach((point) => { + if (point.user_id) { + uniqueUserIds.add(point.user_id); + } + }); + } + + if (uniqueUserIds.size > maxUniqueUsers) { + maxUniqueUsers = uniqueUserIds.size; + defaultGpuType = gpuType; + } + } + } + + setSelectedGpuType(defaultGpuType); + } + }, [gpuTypes, selectedGpuType, data?.time_series]); + useEffect(() => { const loadData = async () => { setLoading(true); @@ -94,17 +136,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 +174,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 +208,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 +231,7 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) { }, }, legend: { - data: Object.keys(h100Data), + data: Object.keys(selectedData), bottom: 0, textStyle: { color: textColor, @@ -229,5 +291,26 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) { series, }; - return ; + return ( + + + + GPU Type + + + + + + ); } From 96335ecd66ae0fbd6083bfa7a05de8857ba49022 Mon Sep 17 00:00:00 2001 From: Jack-Khuu Date: Wed, 11 Feb 2026 12:21:07 -0800 Subject: [PATCH 2/2] Update to skip GPUs with not AI insights --- .../src/pages/leaderboard/Leaderboard.tsx | 2 +- .../leaderboard/components/AiTrendChart.tsx | 65 ++++++++++++++----- 2 files changed, 49 insertions(+), 18 deletions(-) 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 c46f633..8406da1 100644 --- a/frontend/src/pages/leaderboard/components/AiTrendChart.tsx +++ b/frontend/src/pages/leaderboard/components/AiTrendChart.tsx @@ -18,6 +18,7 @@ import { useThemeStore } from "../../../lib/store/themeStore"; interface AiTrendChartProps { leaderboardId: string; + rankings?: Record>; } // Generate a consistent color from a string using hash @@ -35,7 +36,7 @@ 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); @@ -48,34 +49,64 @@ export default function AiTrendChart({ leaderboardId }: AiTrendChartProps) { useEffect(() => { if (gpuTypes.length > 0 && !selectedGpuType && data?.time_series) { - // Find the GPU type with the most unique users with successful submissions + // Find the GPU type with the most unique users (from overall rankings) + // that also has actual AI data entries let maxUniqueUsers = 0; - let defaultGpuType = gpuTypes[0]; + let defaultGpuType = ""; for (const gpuType of gpuTypes) { const gpuData = data.time_series[gpuType]; - if (gpuData) { - // Collect unique user IDs across all models for this GPU type - const uniqueUserIds = new Set(); - for (const model of Object.keys(gpuData)) { - const dataPoints = gpuData[model]; - dataPoints.forEach((point) => { - if (point.user_id) { - uniqueUserIds.add(point.user_id); - } - }); + // 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 (uniqueUserIds.size > maxUniqueUsers) { - maxUniqueUsers = uniqueUserIds.size; - defaultGpuType = gpuType; + 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]); + }, [gpuTypes, selectedGpuType, data?.time_series, rankings]); useEffect(() => { const loadData = async () => {