| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Ghanaian MMLU Leaderboard</title> |
| <style> |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } |
| :root { |
| --bg: #f8fafc; --surface: #ffffff; --surface-2: #f1f5f9; --border: #e2e8f0; |
| --text: #1e293b; --text-muted: #64748b; --accent: #4f46e5; --accent-hover: #4338ca; |
| --success: #059669; --danger: #dc2626; --warning: #d97706; |
| --table-stripe: rgba(15,23,42,0.025); --radius: 12px; |
| } |
| html { font-size: 14px; } |
| body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; |
| background: var(--bg); color: var(--text); line-height: 1.5; min-height: 100vh; } |
| a { color: var(--accent-hover); text-decoration: none; } |
| a:hover { text-decoration: underline; } |
| .container { max-width: 1200px; margin: 0 auto; padding: 24px 20px 60px; } |
| .header { text-align: center; margin-bottom: 28px; } |
| .header h1 { font-size: 1.8rem; font-weight: 700; margin-bottom: 8px; } |
| .header p { color: var(--text-muted); font-size: 0.95rem; } |
| .header .links { margin-top: 10px; } |
| .repo-link { display: inline-flex; align-items: center; gap: 4px; font-size: 0.85rem; } |
| .repo-link svg { width: 16px; height: 16px; } |
| .tabs { display: flex; gap: 4px; margin-bottom: 24px; flex-wrap: wrap; } |
| .tab { padding: 10px 20px; border-radius: 8px 8px 0 0; cursor: pointer; |
| border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); |
| font-weight: 500; font-size: 0.95rem; transition: all 0.15s; border-bottom: none; } |
| .tab:hover { color: var(--text); } |
| .tab.active { background: var(--surface-2); color: var(--text); border-bottom: 2px solid var(--accent); } |
| .tab-pane { display: none; } |
| .tab-pane.active { display: block; } |
| .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); |
| gap: 12px; margin-bottom: 24px; } |
| .stat-card { background: var(--surface); border: 1px solid var(--border); |
| border-radius: var(--radius); padding: 18px; } |
| .stat-card .label { color: var(--text-muted); font-size: 0.8rem; margin-bottom: 6px; } |
| .stat-card .value { font-size: 1.4rem; font-weight: 700; } |
| .table-wrap { background: var(--surface); border: 1px solid var(--border); |
| border-radius: var(--radius); overflow-x: auto; } |
| table { width: 100%; border-collapse: collapse; font-size: 0.88rem; } |
| th, td { text-align: left; padding: 10px 16px; white-space: nowrap; } |
| th { background: var(--surface-2); color: var(--text-muted); font-weight: 600; font-size: 0.8rem; |
| text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid var(--border); |
| position: sticky; top: 0; } |
| tbody tr { border-bottom: 1px solid var(--border); } |
| tbody tr:nth-child(even) { background: var(--table-stripe); } |
| tbody tr:hover { background: rgba(79, 70, 229, 0.1); } |
| .empty-row { text-align: center; color: var(--text-muted); } |
| .mtype { display: inline-block; padding: 1px 8px; border-radius: 4px; font-size: 0.75rem; |
| background: var(--surface-2); color: var(--text-muted); } |
| .rank-medal { font-size: 1rem; } |
| ::-webkit-scrollbar { width: 8px; height: 8px; } |
| ::-webkit-scrollbar-track { background: var(--surface); } |
| ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } |
| .loading { text-align: center; padding: 80px 0; color: var(--text-muted); } |
| .loading .spinner { width: 40px; height: 40px; border: 3px solid var(--border); |
| border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; margin: 0 auto 16px; } |
| @keyframes spin { to { transform: rotate(360deg); } } |
| .footer { margin-top: 40px; text-align: center; color: var(--text-muted); font-size: 0.8rem; |
| padding-top: 20px; border-top: 1px solid var(--border); } |
| .note { color: var(--text-muted); margin-bottom: 14px; font-size: 0.9rem; } |
| @media (max-width: 600px) { |
| .header h1 { font-size: 1.4rem; } |
| th, td { padding: 8px 10px; font-size: 0.82rem; } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <div class="header"> |
| <h1>🇬🇭 Ghanaian MMLU Leaderboard</h1> |
| <p>Benchmarking LLMs on <strong>2,194</strong> multiple-choice questions across |
| <strong>12 Ghanaian languages</strong> from the |
| <a href="https://ntc.gov.gh/practice_test/ghanaian_languages/" target="_blank">NTC licensing practice tests</a>. |
| All models evaluated with <strong>thinking disabled</strong> for fair comparison.</p> |
| <div class="links"> |
| <a href="https://github.com/GhanaNLP/nsanku-MMLU" target="_blank" class="repo-link"> |
| <svg viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg> |
| GhanaNLP/nsanku-MMLU |
| </a> |
| </div> |
| </div> |
|
|
| <div id="loading" class="loading"> |
| <div class="spinner"></div> |
| <p>Loading benchmark data from GitHub…</p> |
| </div> |
|
|
| <div id="main" style="display:none;"> |
| <div class="stats-grid" id="stats-grid"></div> |
|
|
| <div class="tabs"> |
| <div class="tab active" data-tab="overall">🏆 Overall</div> |
| <div class="tab" data-tab="per-lang">🌐 Per-Language</div> |
| </div> |
|
|
| <div class="tab-pane active" id="pane-overall"> |
| <p class="note">Overall accuracy across all 2,194 questions — higher is better.</p> |
| <div class="table-wrap"> |
| <table> |
| <thead><tr><th>#</th><th>Model</th><th>Accuracy (%)</th><th>Correct</th><th>Total</th><th>Unparsed</th></tr></thead> |
| <tbody id="overall-body"></tbody> |
| </table> |
| </div> |
| </div> |
|
|
| <div class="tab-pane" id="pane-per-lang"> |
| <p class="note">Per-language accuracy (%) — models sorted by overall accuracy.</p> |
| <div class="table-wrap"> |
| <table> |
| <thead><tr id="per-lang-head"></tr></thead> |
| <tbody id="per-lang-body"></tbody> |
| </table> |
| </div> |
| </div> |
|
|
| <div class="footer"> |
| <p>Higher accuracy is better · Chance baseline ≈ 25% (4 options)</p> |
| <p>Add a model by opening a PR to <a href="https://github.com/GhanaNLP/nsanku-MMLU" target="_blank">the GitHub repo</a> — see CONTRIBUTING.md. Then reload this page.</p> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| const REPO = 'GhanaNLP/nsanku-MMLU'; |
| const BRANCH = 'master'; |
| const RAW = `https://raw.githubusercontent.com/${REPO}/${BRANCH}`; |
| const API = `https://api.github.com/repos/${REPO}/contents`; |
| |
| const DISPLAY_NAMES = { |
| 'openai/gpt-4o': 'GPT-4o', |
| 'gemini/gemini-3-flash-preview': 'Gemini 3 Flash', |
| 'gemini/gemini-3.1-pro-preview': 'Gemini 3.1 Pro', |
| 'nvidia/deepseek-ai/deepseek-v4-flash': 'DeepSeek v4 Flash', |
| 'nvidia/minimaxai/minimax-m3': 'MiniMax M3', |
| 'nvidia/z-ai/glm-5.2': 'GLM-5.2', |
| 'nvidia/nvidia/nemotron-3-ultra-550b-a55b': 'Nemotron 3 Ultra 550B', |
| 'nvidia/abacusai/dracarys-llama-3.1-70b-instruct': 'Dracarys Llama 3.1 70B', |
| 'mistral/mistral-large-latest': 'Mistral Large', |
| }; |
| const LANG_ORDER = ['akuapem_twi','asante_twi','dagaare','dagbani','dangme','ewe','fanti','ga','gonja','gurene','kasem','nzema']; |
| const LANG_DISPLAY = {akuapem_twi:'Akuapem Twi',asante_twi:'Asante Twi',dagaare:'Dagaare',dagbani:'Dagbani', |
| dangme:'Dangme',ewe:'Ewe',fanti:'Fante',ga:'Ga',gonja:'Gonja',gurene:'Gurene',kasem:'Kasem',nzema:'Nzema'}; |
| |
| function displayName(spec){ return DISPLAY_NAMES[spec] || (spec||'unknown').split('/').pop(); } |
| function escapeHtml(s){ return (s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } |
| function accColor(a){ return a >= 50 ? 'var(--success)' : a >= 35 ? 'var(--accent-hover)' : 'var(--warning)'; } |
| const MEDALS = ['🥇','🥈','🥉']; |
| |
| async function getJSON(url){ const r = await fetch(url); if(!r.ok) throw new Error('HTTP '+r.status+' for '+url); return r.json(); } |
| |
| async function loadResults(){ |
| const entries = await getJSON(`${API}/results?ref=${BRANCH}`); |
| const dirs = entries.filter(e => e.type === 'dir'); |
| const out = []; |
| for (const d of dirs){ |
| try { |
| const data = await getJSON(`${RAW}/results/${d.name}/results.json`); |
| if (data && data.overall) out.push(data); |
| } catch(e){ } |
| } |
| return out; |
| } |
| |
| function renderStats(results){ |
| const n = results.length; |
| const best = results.reduce((a,b)=> b.overall.accuracy > (a?a.overall.accuracy:-1) ? b : a, null); |
| const stats = [ |
| {label:'Models', value:n}, |
| {label:'Questions', value:'2,194'}, |
| {label:'Languages', value:'12'}, |
| {label:'Best model', value: best ? `${displayName(best.model)} · ${best.overall.accuracy.toFixed(2)}%` : '—'}, |
| ]; |
| document.getElementById('stats-grid').innerHTML = stats.map(s => |
| `<div class="stat-card"><div class="label">${s.label}</div><div class="value">${s.value}</div></div>`).join(''); |
| } |
| |
| function renderOverall(results){ |
| const rows = [...results].sort((a,b)=> b.overall.accuracy - a.overall.accuracy); |
| const body = document.getElementById('overall-body'); |
| if(!rows.length){ body.innerHTML = '<tr class="empty-row"><td colspan="6">No results found</td></tr>'; return; } |
| body.innerHTML = rows.map((r,i)=>{ |
| const o = r.overall; |
| return `<tr> |
| <td>${MEDALS[i] ? `<span class="rank-medal">${MEDALS[i]}</span>` : (i+1)}</td> |
| <td>${escapeHtml(displayName(r.model))}</td> |
| <td style="font-weight:700;color:${accColor(o.accuracy)}">${o.accuracy.toFixed(2)}</td> |
| <td>${o.correct}</td> |
| <td>${o.total}</td> |
| <td>${o.unparsed||0}</td> |
| </tr>`; |
| }).join(''); |
| } |
| |
| function renderPerLang(results){ |
| const rows = [...results].sort((a,b)=> b.overall.accuracy - a.overall.accuracy); |
| document.getElementById('per-lang-head').innerHTML = |
| '<th>Model</th>' + LANG_ORDER.map(l=>`<th>${LANG_DISPLAY[l]}</th>`).join(''); |
| const body = document.getElementById('per-lang-body'); |
| if(!rows.length){ body.innerHTML = '<tr class="empty-row"><td colspan="13">No results found</td></tr>'; return; } |
| body.innerHTML = rows.map(r=>{ |
| const cells = LANG_ORDER.map(l=>{ |
| const s = (r.per_language||{})[l]; |
| if(s && s.total>0) return `<td style="color:${accColor(s.accuracy)}">${s.accuracy.toFixed(1)}</td>`; |
| return '<td>—</td>'; |
| }).join(''); |
| return `<tr><td>${escapeHtml(displayName(r.model))}</td>${cells}</tr>`; |
| }).join(''); |
| } |
| |
| function setupTabs(){ |
| document.querySelectorAll('.tab').forEach(tab=>{ |
| tab.addEventListener('click', ()=>{ |
| document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active')); |
| document.querySelectorAll('.tab-pane').forEach(p=>p.classList.remove('active')); |
| tab.classList.add('active'); |
| document.getElementById('pane-'+tab.dataset.tab).classList.add('active'); |
| }); |
| }); |
| } |
| |
| async function main(){ |
| try { |
| const results = await loadResults(); |
| document.getElementById('loading').style.display = 'none'; |
| document.getElementById('main').style.display = 'block'; |
| renderStats(results); |
| renderOverall(results); |
| renderPerLang(results); |
| setupTabs(); |
| } catch(e){ |
| document.getElementById('loading').innerHTML = |
| `<div style="color:var(--danger)"><p>Failed to load benchmark data.</p> |
| <p style="font-size:0.85rem;margin-top:8px">${escapeHtml(e.message)}</p> |
| <p style="margin-top:12px;font-size:0.85rem">Visit the <a href="https://github.com/GhanaNLP/nsanku-MMLU" target="_blank">GitHub repo</a> directly.</p></div>`; |
| } |
| } |
| main(); |
| </script> |
| </body> |
| </html> |
|
|