Spaces:
Sleeping
Sleeping
| import React, { useState, useMemo } from 'react'; | |
| import { useResults } from './hooks/useResults'; | |
| import ModelSelector from './components/ModelSelector'; | |
| import MetricCard from './components/MetricCard'; | |
| import BarChartView from './components/BarChartView'; | |
| import RadarView from './components/RadarView'; | |
| import LineTrendView from './components/LineTrendView'; | |
| import ComparisonTable from './components/ComparisonTable'; | |
| import AddModelForm from './components/AddModelForm'; | |
| import LanguageLevelTable from './components/LanguageLevelTable'; | |
| import { ChartRow, ModelMetrics } from './types'; | |
| import axios from 'axios'; | |
| const colors = ['#4F46E5', '#059669', '#DC2626', '#7C3AED', '#EA580C', '#0891B2']; | |
| const metrics = ['bleu','chrf','cer','wer','rouge1','rouge2','rougeL','quality_score']; | |
| function App() { | |
| const { data, error } = useResults(); | |
| const [selectedMetric, setSelectedMetric] = useState(metrics[0]); | |
| const [selectedModel, setSelectedModel] = useState(''); | |
| const [selectedModels, setSelectedModels] = useState<string[]>([]); | |
| const [comparisonMode, setComparisonMode] = useState(false); | |
| const [viewMode, setViewMode] = useState<'overview' | 'detailed'>('overview'); | |
| const [activeTab, setActiveTab] = useState<'dashboard' | 'addModel' | 'comparison'>('dashboard'); | |
| const [newModelName, setNewModelName] = useState(''); | |
| const [isEvaluating, setIsEvaluating] = useState(false); | |
| const [evaluationError, setEvaluationError] = useState<string | null>(null); | |
| const handleEvaluate = async () => { | |
| if (!newModelName.trim()) { | |
| setEvaluationError('Model name cannot be empty.'); | |
| return; | |
| } | |
| setIsEvaluating(true); | |
| setEvaluationError(null); | |
| try { | |
| const response = await axios.post('http://localhost:8000/evaluate', { | |
| model_name: newModelName, | |
| }); | |
| // Handle success | |
| alert(`Evaluation successful! Metrics: ${JSON.stringify(response.data.metrics)}`); | |
| setNewModelName(''); // Clear the input field | |
| } catch (error: any) { | |
| // Handle error | |
| setEvaluationError(error.response?.data?.detail || 'An error occurred during evaluation.'); | |
| } finally { | |
| setIsEvaluating(false); | |
| } | |
| }; | |
| const modelNames = data ? Object.keys(data) : []; | |
| const languagePairs = data && selectedModel && data[selectedModel] | |
| ? Object.keys(data[selectedModel]).filter(k => k !== 'averages') | |
| : []; | |
| const barChartData: ChartRow[] = useMemo(() => { | |
| if (!data || !selectedModel || !data[selectedModel]) return []; | |
| return languagePairs.map(pair => { | |
| const row: any = { name: pair.toUpperCase() }; | |
| if (comparisonMode) { | |
| selectedModels.forEach((m, i) => { | |
| row[m] = data[m]?.[pair]?.[selectedMetric as keyof ModelMetrics] ?? 0; | |
| }); | |
| } else { | |
| row[selectedMetric] = data[selectedModel]?.[pair]?.[selectedMetric as keyof ModelMetrics] ?? 0; | |
| } | |
| return row; | |
| }); | |
| }, [data, languagePairs, selectedMetric, comparisonMode, selectedModels]); | |
| const radarData: ChartRow[] = useMemo(() => { | |
| if (!data || !selectedModel || !data[selectedModel]) return []; | |
| return metrics.map(metric => { | |
| const point: any = { metric: metric.toUpperCase() }; | |
| if (comparisonMode) { | |
| selectedModels.forEach((m, i) => { | |
| point[m] = data[m]?.averages?.[metric as keyof ModelMetrics] ?? 0; | |
| }); | |
| } else { | |
| point.value = data[selectedModel]?.averages?.[metric as keyof ModelMetrics] ?? 0; | |
| } | |
| return point; | |
| }); | |
| }, [data, selectedModel, selectedModels, comparisonMode]); | |
| if (error) return <div className="p-6 text-red-600">Error: {error}</div>; | |
| if (!data) return <div className="p-6">Loading...</div>; | |
| return ( | |
| <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100"> | |
| {/* Main Navigation Tabs */} | |
| <div className="bg-white shadow-sm border-b"> | |
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div className="flex justify-between items-center py-6"> | |
| <h1 className="text-3xl font-bold text-gray-900">Translation Leaderboard</h1> | |
| <div className="flex space-x-4"> | |
| <button | |
| onClick={() => setActiveTab('dashboard')} | |
| className={`px-4 py-2 rounded-lg font-medium ${ | |
| activeTab === 'dashboard' ? 'bg-indigo-600 text-white' : 'bg-gray-200 text-gray-700 hover:bg-gray-300' | |
| }`} | |
| > | |
| Dashboard | |
| </button> | |
| <button | |
| onClick={() => setActiveTab('comparison')} | |
| className={`px-4 py-2 rounded-lg font-medium ${ | |
| activeTab === 'comparison' ? 'bg-indigo-600 text-white' : 'bg-gray-200 text-gray-700 hover:bg-gray-300' | |
| }`} | |
| > | |
| Comparison | |
| </button> | |
| <button | |
| onClick={() => setActiveTab('addModel')} | |
| className={`px-4 py-2 rounded-lg font-medium ${ | |
| activeTab === 'addModel' ? 'bg-indigo-600 text-white' : 'bg-gray-200 text-gray-700 hover:bg-gray-300' | |
| }`} | |
| > | |
| Add Model | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Content Based on Active Tab */} | |
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| {activeTab === 'dashboard' && ( | |
| <div> | |
| <h2 className="text-2xl font-bold mb-4">Dashboard</h2> | |
| {/* Toggle Button for Comparison Mode */} | |
| <div className="mb-6"> | |
| <button | |
| onClick={() => setComparisonMode(!comparisonMode)} | |
| className={`px-4 py-2 rounded-lg font-medium ${ | |
| comparisonMode ? 'bg-red-600 text-white' : 'bg-indigo-600 text-white' | |
| }`} | |
| > | |
| {comparisonMode ? 'Disable Comparison Mode' : 'Enable Comparison Mode'} | |
| </button> | |
| </div> | |
| <ModelSelector | |
| modelNames={modelNames} | |
| selectedModel={selectedModel} | |
| selectedModels={selectedModels} | |
| comparisonMode={comparisonMode} | |
| onSelectModel={setSelectedModel} | |
| onToggleModel={m => | |
| setSelectedModels(prev => | |
| prev.includes(m) ? prev.filter(x => x !== m) : [...prev, m] | |
| ) | |
| } | |
| /> | |
| <div className="grid grid-cols-1 lg:grid-cols-4 gap-6 mb-8"> | |
| {/* Summary cards */} | |
| {!comparisonMode ? ( | |
| <> | |
| {data[selectedModel]?.averages && ( | |
| <MetricCard | |
| title="Average BLEU" | |
| value={data[selectedModel].averages.bleu} | |
| description="Translation quality" | |
| colorHex={colors[0]} | |
| /> | |
| )} | |
| {/* Other cards */} | |
| </> | |
| ) : ( | |
| selectedModels.map((m, i) => ( | |
| data[m]?.averages && ( | |
| <MetricCard | |
| key={m} | |
| title="Avg BLEU" | |
| value={data[m].averages.bleu} | |
| description={m} | |
| colorHex={colors[i]} | |
| /> | |
| ) | |
| )) | |
| )} | |
| </div> | |
| {viewMode === 'overview' ? ( | |
| <> | |
| <ComparisonTable data={data} metrics={metrics} /> | |
| <BarChartView | |
| data={barChartData} | |
| metrics={metrics} | |
| selectedMetric={selectedMetric} | |
| onMetricChange={setSelectedMetric} | |
| comparisonMode={comparisonMode} | |
| colors={colors} | |
| selectedModels={selectedModels} | |
| /> | |
| </> | |
| ) : ( | |
| <> | |
| <RadarView data={radarData} comparisonMode={comparisonMode} colors={colors} /> | |
| <LineTrendView data={barChartData} selectedModels={selectedModels} comparisonMode={comparisonMode} colors={colors} /> | |
| </> | |
| )} | |
| </div> | |
| )} | |
| {activeTab === 'addModel' && ( | |
| <div> | |
| <h2 className="text-2xl font-bold mb-4">Add a New Model</h2> | |
| <AddModelForm | |
| newModelName={newModelName} | |
| isEvaluating={isEvaluating} | |
| onNameChange={setNewModelName} | |
| onEvaluate={handleEvaluate} | |
| /> | |
| {evaluationError && <p className="text-red-600 mt-4">{evaluationError}</p>} | |
| </div> | |
| )} | |
| {activeTab === 'comparison' && ( | |
| <div> | |
| <h2 className="text-2xl font-bold mb-4">Comparison</h2> | |
| <ModelSelector | |
| modelNames={modelNames} | |
| selectedModel={selectedModel} | |
| selectedModels={selectedModels} | |
| comparisonMode={comparisonMode} | |
| onSelectModel={setSelectedModel} | |
| onToggleModel={m => | |
| setSelectedModels(prev => | |
| prev.includes(m) ? prev.filter(x => x !== m) : [...prev, m] | |
| ) | |
| } | |
| /> | |
| <RadarView data={radarData} comparisonMode={comparisonMode} colors={colors} /> | |
| <ComparisonTable data={data} metrics={metrics} /> | |
| <LineTrendView data={barChartData} selectedModels={selectedModels} comparisonMode={comparisonMode} colors={colors} /> | |
| </div> | |
| )} | |
| {activeTab === 'dashboard' && ( | |
| <div> | |
| <h2 className="text-2xl font-bold mb-4">Dashboard</h2> | |
| <LanguageLevelTable | |
| data={data} | |
| selectedModels={selectedModels} | |
| metrics={metrics} | |
| colors={colors} | |
| /> | |
| </div> | |
| )} | |
| {activeTab === 'comparison' && ( | |
| <div> | |
| <h2 className="text-2xl font-bold mb-4">Comparison</h2> | |
| <LanguageLevelTable | |
| data={data} | |
| selectedModels={selectedModels} | |
| metrics={metrics} | |
| colors={colors} | |
| /> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |
| export default App; | |