Spaces:
Runtime error
Runtime error
import { useState, useEffect } from 'react' | |
import { PrimeReactProvider } from 'primereact/api' | |
import 'primereact/resources/themes/lara-light-cyan/theme.css' | |
import ModelTable from './components/ModelTable' | |
import LanguageTable from './components/LanguageTable' | |
import DatasetTable from './components/DatasetTable' | |
import WorldMap from './components/WorldMap' | |
import AutoComplete from './components/AutoComplete' | |
import LanguagePlot from './components/LanguagePlot' | |
import SpeakerPlot from './components/SpeakerPlot' | |
import HistoryPlot from './components/HistoryPlot' | |
import { Carousel } from 'primereact/carousel' | |
import { Dialog } from 'primereact/dialog' | |
import { Button } from 'primereact/button' | |
function App () { | |
const [data, setData] = useState(null) | |
const [loading, setLoading] = useState(true) | |
const [error, setError] = useState(null) | |
const [selectedLanguages, setSelectedLanguages] = useState([]) | |
const [dialogVisible, setDialogVisible] = useState(false) | |
const [aboutVisible, setAboutVisible] = useState(false) | |
const [contributeVisible, setContributeVisible] = useState(false) | |
useEffect(() => { | |
fetch('/api/data', { | |
method: 'POST', | |
body: JSON.stringify({ selectedLanguages }) | |
}) | |
.then(response => { | |
if (!response.ok) { | |
throw new Error('Network response was not ok') | |
} | |
return response.json() | |
}) | |
.then(jsonData => { | |
setData(jsonData) | |
setLoading(false) | |
}) | |
.catch(err => { | |
setError(err.message) | |
setLoading(false) | |
}) | |
}, [selectedLanguages]) | |
const [windowWidth, setWindowWidth] = useState(window.innerWidth) | |
const [windowHeight, setWindowHeight] = useState(window.innerHeight) | |
useEffect(() => { | |
const handleResize = () => { | |
setWindowWidth(window.innerWidth) | |
setWindowHeight(window.innerHeight) | |
} | |
window.addEventListener('resize', handleResize) | |
return () => window.removeEventListener('resize', handleResize) | |
}, []) | |
return ( | |
<PrimeReactProvider> | |
<div style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column', width: '100vw' }}> | |
<div style={{backgroundColor: '#fff3cd', color: '#856404', padding: '0.75rem 1.25rem', marginBottom: '1rem', border: '1px solid #ffeeba', borderRadius: '0.25rem', textAlign: 'center'}}> | |
<strong>Work in Progress:</strong> This dashboard is currently under active development. Evaluation results are not yet final. | |
<a href="https://github.com/datenlabor-bmz/ai-language-monitor" target="_blank" rel="noopener noreferrer" style={{ | |
textDecoration: 'none', | |
color: '#856404', | |
float: 'right', | |
fontSize: '1.2rem', | |
fontWeight: 'bold', | |
padding: '0 0.5rem', | |
borderRadius: '3px', | |
backgroundColor: 'rgba(255,255,255,0.3)' | |
}}> | |
<i className="pi pi-github" title="View on GitHub" style={{ marginRight: '0.3rem' }} /> | |
GitHub | |
</a> | |
</div> | |
<header | |
style={{ | |
display: 'flex', | |
flexDirection: 'column', | |
alignItems: 'center', | |
justifyContent: 'center', | |
padding: '5vh 5vw', | |
width: '100%', | |
maxWidth: '1400px', | |
margin: '0 auto' | |
}} | |
> | |
<div> | |
<span | |
role='img' | |
aria-label='Globe Emoji' | |
style={{ fontSize: '40px' }} | |
> | |
π | |
</span> | |
</div> | |
<h1 style={{ fontSize: '2.5rem', fontWeight: '700' }}> | |
AI Language Proficiency Monitor | |
</h1> | |
<p style={{ fontSize: '1.10rem', color: '#555', marginTop: '0', marginBottom: '2rem' }}> | |
Comprehensive multilingual evaluation results for AI language models | |
</p> | |
<div style={{ display: 'flex', gap: '1rem', marginBottom: '1.5rem', flexWrap: 'wrap', justifyContent: 'center' }}> | |
<Button | |
label="π About this tool" | |
className="p-button-text" | |
onClick={() => setAboutVisible(true)} | |
style={{ | |
color: '#666', | |
border: '1px solid #ddd', | |
padding: '0.5rem 1rem', | |
borderRadius: '4px', | |
fontSize: '0.9rem' | |
}} | |
/> | |
<Button | |
label="π Add your model" | |
className="p-button-text" | |
onClick={() => setContributeVisible(true)} | |
style={{ | |
color: '#666', | |
border: '1px solid #ddd', | |
padding: '0.5rem 1rem', | |
borderRadius: '4px', | |
fontSize: '0.9rem' | |
}} | |
/> | |
</div> | |
{data && ( | |
<AutoComplete | |
languages={data?.language_table} | |
onComplete={items => setSelectedLanguages(items)} | |
/> | |
)} | |
</header> | |
<main | |
style={{ | |
display: 'flex', | |
flexDirection: 'column', | |
gap: '3rem', | |
width: '100%', | |
paddingBottom: '5vh', | |
padding: '1rem 15vw 5vh 15vw' | |
}} | |
> | |
{loading && ( | |
<div style={{ width: '100%', textAlign: 'center' }}> | |
<i className='pi pi-spinner pi-spin' style={{ fontSize: '4rem' }} /> | |
</div> | |
)} | |
{error && <div style={{ width: '100%', textAlign: 'center' }}><p>Error: {error}</p></div>} | |
{data && ( | |
<> | |
<div style={{ width: '100%' }}> | |
<ModelTable data={data.model_table} /> | |
</div> | |
<div style={{ width: '100%' }}> | |
<LanguageTable | |
data={data.language_table} | |
selectedLanguages={selectedLanguages} | |
setSelectedLanguages={setSelectedLanguages} | |
/> | |
</div> | |
<div style={{ width: '100%' }}> | |
<DatasetTable data={data} /> | |
</div> | |
<div | |
id='figure' | |
style={{ | |
width: '100%', | |
position: 'relative' | |
}} | |
> | |
<Button | |
icon="pi pi-external-link" | |
className="p-button-text p-button-plain" | |
onClick={() => setDialogVisible(true)} | |
tooltip="Open in larger view" | |
style={{ | |
position: 'absolute', | |
top: '10px', | |
right: '10px', | |
zIndex: 1, | |
color: '#666' | |
}} | |
/> | |
<Carousel | |
value={[ | |
<WorldMap data={data.countries} />, | |
<LanguagePlot data={data} />, | |
<SpeakerPlot data={data} />, | |
<HistoryPlot data={data} />, | |
]} | |
numScroll={1} | |
numVisible={1} | |
itemTemplate={item => item} | |
circular | |
style={{ width: '100%', minHeight: '650px' }} | |
/> | |
</div> | |
</> | |
)} | |
</main> | |
{/* About Dialog */} | |
<Dialog | |
visible={aboutVisible} | |
onHide={() => setAboutVisible(false)} | |
style={{ width: '600px' }} | |
modal | |
header="About this tool" | |
> | |
<div> | |
<p>The <i>AI Language Proficiency Monitor</i> presents comprehensive multilingual evaluation results of AI language models.</p> | |
<h4>Who is this for?</h4> | |
<ul> | |
<li><b>Practitioners</b> can pick the best model for a given language.</li> | |
<li><b>Policymakers and funders</b> can identify and prioritize neglected languages.</li> | |
<li><b>Model developers</b> can compete on our <i>AI Language Proficiency</i> metric.</li> | |
</ul> | |
<h4>β‘ Live Updates</h4> | |
<p>Benchmark results automatically refresh every night and include the most popular models from <a href="https://openrouter.ai" target="_blank" rel="noopener noreferrer">OpenRouter</a>, plus community-submitted models.</p> | |
<h4>Authors</h4> | |
<p>The AI Language Proficiency Monitor is a collaboration between BMZ's <a href="https://www.bmz-digital.global/en/overview-of-initiatives/the-bmz-data-lab/" target="_blank" rel="noopener noreferrer">Data Lab</a>, the BMZ-Initiative <a href="https://www.bmz-digital.global/en/overview-of-initiatives/fair-forward/" target="_blank" rel="noopener noreferrer">Fair Forward</a> (implemented by GIZ), and the <a href="https://www.dfki.de/en/web/research/research-departments/multilinguality-and-language-technology/ee-team" target="_blank" rel="noopener noreferrer">E&E group</a> of DFKI's Multilinguality and Language Technology Lab.</p> | |
<h4>π Links</h4> | |
<p> | |
<a | |
href="https://github.com/datenlabor-bmz/ai-language-monitor" | |
target="_blank" | |
rel="noopener noreferrer" | |
style={{ | |
color: '#666', | |
textDecoration: 'none', | |
display: 'inline-flex', | |
alignItems: 'center', | |
gap: '0.5rem' | |
}} | |
> | |
<i className="pi pi-github" style={{ fontSize: '1.2rem' }} /> | |
View source code on GitHub | |
</a> | |
</p> | |
</div> | |
</Dialog> | |
{/* Contribute Dialog */} | |
<Dialog | |
visible={contributeVisible} | |
onHide={() => setContributeVisible(false)} | |
style={{ width: '600px' }} | |
modal | |
header="Add your model & Contribute" | |
> | |
<div> | |
<h4>π Submit Your Model</h4> | |
<p>Have a custom fine-tuned model you'd like to see on the leaderboard?</p> | |
<p><a href="https://forms.gle/ckvY9pS7XLcHYnaV8" target="_blank" rel="noopener noreferrer" style={{ color: '#28a745', fontWeight: 'bold' }}>β Submit your model here</a></p> | |
<h4>π§ Contribute to Development</h4> | |
<p>Help us expand language coverage and add new evaluation tasks:</p> | |
<p><a href="https://github.com/datenlabor-bmz/ai-language-monitor/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" style={{ color: '#007bff', fontWeight: 'bold' }}>β Contribution guidelines</a></p> | |
</div> | |
</Dialog> | |
{/* Full-screen Dialog for Charts */} | |
<Dialog | |
visible={dialogVisible} | |
onHide={() => setDialogVisible(false)} | |
style={{ width: '90vw', height: '90vh' }} | |
maximizable | |
modal | |
header="Interactive Visualizations" | |
> | |
{data && ( | |
<div style={{ width: '100%', height: '100%' }}> | |
<Carousel | |
value={[ | |
<WorldMap data={data.countries} width={windowWidth * 0.7} height={windowHeight * 0.6} />, | |
<LanguagePlot data={data} width={windowWidth * 0.7} height={windowHeight * 0.6} />, | |
<SpeakerPlot data={data} width={windowWidth * 0.7} height={windowHeight * 0.6} />, | |
<HistoryPlot data={data} width={windowWidth * 0.7} height={windowHeight * 0.6} />, | |
]} | |
numScroll={1} | |
numVisible={1} | |
itemTemplate={item => item} | |
circular | |
style={{ width: '100%', height: 'calc(90vh - 120px)' }} | |
/> | |
</div> | |
)} | |
</Dialog> | |
</div> | |
</PrimeReactProvider> | |
) | |
} | |
export default App | |