"use client"; import q3Results from "../../results/qwen3.json" import q3_30B_A3B_Results from "../../results/qwen3-30B-A3-results.json" // import mockResults from "../../qwen3-final-results.json" import { useMemo, useState, useEffect, useRef } from "react"; import { Card } from "@/components/ui/card"; import ForceDirectedGraph from "@/components/force-directed-graph"; import RunsList from "@/components/runs-list"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Run as ForceGraphRun } from "@/components/reasoning-trace"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { UploadIcon } from "lucide-react"; const defaultModels = { "Qwen3-14B": q3Results, "Qwen3-30B-A3B": q3_30B_A3B_Results, } // Use the type expected by RunsList interface Run { start_article: string; destination_article: string; steps: string[]; result: string; } // Interface for model statistics interface ModelStats { winPercentage: number; avgSteps: number; stdDevSteps: number; totalRuns: number; wins: number; medianSteps: number; minSteps: number; maxSteps: number; } export default function ViewerTab({ handleTryRun, }: { handleTryRun: (startArticle: string, destinationArticle: string) => void; }) { const [selectedRun, setSelectedRun] = useState(null); const [runs, setRuns] = useState([]); const [selectedModel, setSelectedModel] = useState("Qwen3-14B"); const [modelStats, setModelStats] = useState(null); const [models, setModels] = useState(defaultModels); const fileInputRef = useRef(null); useEffect(() => { // Convert the model data to the format expected by RunsList const convertedRuns = models[selectedModel]?.runs?.map((run: { start_article: string; destination_article: string; steps: { type: string; article: string }[]; result: string; }) => ({ start_article: run.start_article, destination_article: run.destination_article, steps: run.steps.map((step: { article: string }) => step.article), result: run.result })) || []; setRuns(convertedRuns); // Calculate model statistics const winRuns = convertedRuns.filter(run => run.result === "win"); const totalRuns = convertedRuns.length; const wins = winRuns.length; const winPercentage = totalRuns > 0 ? (wins / totalRuns) * 100 : 0; // Calculate steps statistics for winning runs const stepCounts = winRuns.map(run => run.steps.length); const avgSteps = stepCounts.length > 0 ? stepCounts.reduce((sum, count) => sum + count, 0) / stepCounts.length : 0; // Calculate standard deviation const variance = stepCounts.length > 0 ? stepCounts.reduce((sum, count) => sum + Math.pow(count - avgSteps, 2), 0) / stepCounts.length : 0; const stdDevSteps = Math.sqrt(variance); // Calculate median, min, max steps const sortedSteps = [...stepCounts].sort((a, b) => a - b); const medianSteps = stepCounts.length > 0 ? stepCounts.length % 2 === 0 ? (sortedSteps[stepCounts.length / 2 - 1] + sortedSteps[stepCounts.length / 2]) / 2 : sortedSteps[Math.floor(stepCounts.length / 2)] : 0; const minSteps = stepCounts.length > 0 ? Math.min(...stepCounts) : 0; const maxSteps = stepCounts.length > 0 ? Math.max(...stepCounts) : 0; setModelStats({ winPercentage, avgSteps, stdDevSteps, totalRuns, wins, medianSteps, minSteps, maxSteps }); }, [selectedModel, models]); const handleRunSelect = (runId: number) => { setSelectedRun(runId); }; const filterRuns = useMemo(() => { return runs.filter(run => run.result === "win"); }, [runs]); // Convert the runs to the format expected by ForceDirectedGraph const forceGraphRuns = useMemo(() => { return filterRuns.map((run): ForceGraphRun => ({ start_article: run.start_article, destination_article: run.destination_article, steps: run.steps.map(article => ({ type: "move", article })) })); }, [filterRuns]); const handleFileUpload = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { try { const jsonData = JSON.parse(e.target?.result as string); // Validate the JSON structure has the required fields if (!jsonData.runs || !Array.isArray(jsonData.runs)) { alert("Invalid JSON format. File must contain a 'runs' array."); return; } // Create a filename-based model name, removing extension and path const fileName = file.name.replace(/\.[^/.]+$/, ""); const modelName = `Custom: ${fileName}`; // Add the new model to the models object setModels(prev => ({ ...prev, [modelName]: jsonData })); // Select the newly added model setSelectedModel(modelName); } catch (error) { alert(`Error parsing JSON file: ${error.message}`); } }; reader.readAsText(file); // Reset the file input if (fileInputRef.current) { fileInputRef.current.value = ''; } }; const handleUploadClick = () => { fileInputRef.current?.click(); }; return (
{modelStats && (
Success: {modelStats.winPercentage.toFixed(1)}% ({modelStats.wins}/{modelStats.totalRuns}) Mean: {modelStats.avgSteps.toFixed(1)} ±{modelStats.stdDevSteps.toFixed(1)} Median: {modelStats.medianSteps.toFixed(1)} Min: {modelStats.minSteps} Max: {modelStats.maxSteps}
)}

Runs

); }