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; | |