'use strict'; // Static dashboard presenting locally stored and already executed Python metrics. // No user input leaves the browser. There is no neural inference on this page. const $ = selector => document.querySelector(selector); const $$ = selector => [...document.querySelectorAll(selector)]; const state = {db:null, split:'monolingual', view:'overview', metric:'accuracy_at_1', method:'char-tfidf', group:'by_language', caseMethod:'char-tfidf', selectedCase:null, search:'', language:'all', domain:'all'}; const METHOD_LABELS={'char-tfidf':'Character TF-IDF','word-tfidf':'Word TF-IDF','hybrid-tfidf':'Hybrid TF-IDF','bm25':'BM25'}; const LANG_LABELS={en:'English',es:'Español',pt:'Português'}; const DOMAIN_LABELS={ai:'Artificial intelligence',business:'Business',education:'Education','latin-america':'Latin America',research:'Research'}; const esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); const percent=x=>x==null?'Not evaluated':`${(x*100).toFixed(1)}%`; const fixed=(x,n=3)=>x==null?'—':Number(x).toFixed(n); const activeData=()=>state.db?.splits[state.split]; const executed=()=>activeData().results.models.filter(m=>m.status==='executed'&&m.kind==='lexical'); function updateTop(){ $('#splitMono').classList.toggle('active',state.split==='monolingual'); $('#splitCross').classList.toggle('active',state.split==='cross-language'); $('#splitMono').setAttribute('aria-pressed',state.split==='monolingual'); $('#splitCross').setAttribute('aria-pressed',state.split==='cross-language'); const desc=state.split==='monolingual'?'30 within-language questions across English, Spanish and Portuguese':'18 cross-language questions across six translation directions'; $('#splitDescription').textContent=desc; const group=$('#groupSelect'); if(state.split==='cross-language'&&group.value==='by_language') group.value='by_language_pair'; if(state.split==='monolingual'&&group.value==='by_language_pair') group.value='by_language'; [...group.options].find(x=>x.value==='by_language_pair').disabled=state.split==='monolingual'; state.group=group.value; } function renderStats(){ const d=activeData(), method=executed().slice().sort((a,b)=>b.accuracy_at_1-a.accuracy_at_1)[0]; const cells=[['Evaluation tasks',String(d.rows.length)],['Measured baselines',String(executed().length)],['Best Accuracy@1',percent(method.accuracy_at_1)],['Best MRR',fixed(Math.max(...executed().map(m=>m.mrr)))]]; $('#stats').innerHTML=cells.map(([title,value])=>`
Character TF-IDF: ${percent(char.accuracy_at_1)} versus Word TF-IDF: ${percent(word.accuracy_at_1)}. On this small cross-language test set, character patterns outperform exact token overlap by ${diff.toFixed(1)} percentage points.
Shared roots and technical vocabulary between the three languages can make these test cases easier for character matching.
`; }else{ $('#insight').innerHTML=`${percent(char.accuracy_at_1)} Accuracy@1 for character TF-IDF on 30 monolingual tests. Word TF-IDF achieves ${percent(word.accuracy_at_1)}.
All methods use three candidate passages per question. The high scores are diagnostic, not evidence of production reliability.
`; } } function renderMethodSelectors(){ for(const id of ['#modelSelect','#caseModelSelect']){ const el=$(id); const chosen=id==='#modelSelect'?state.method:state.caseMethod; el.innerHTML=executed().map(m=>``).join(''); el.value=chosen; } } function renderBreakdown(){ const m=executed().find(m=>m.name===state.method)||executed()[0]; const segments=m[state.group]||{}; const entries=Object.entries(segments).sort((a,b)=>a[0].localeCompare(b[0])); $('#breakdown').innerHTML=entries.length?entries.map(([key,r])=>{ const lbl=state.group==='by_language'?LANG_LABELS[key]||key:state.group==='by_domain'?DOMAIN_LABELS[key]||key:key.replace('->',' → ').toUpperCase(); return `n = ${Number(r.n)} · MRR ${fixed(r.mrr)}
No subgroup data available.
'; } function renderSemantic(){ const models=activeData().results.models.filter(m=>m.kind==='semantic'); $('#semanticRows').innerHTML=models.map(m=>`No cases match those filters. Clear the search or change filters.
'; $$('#caseList .case-btn').forEach(b=>b.addEventListener('click',()=>{state.selectedCase=b.dataset.id;renderCaseList();renderCaseDetail();})); renderCaseDetail(); } function renderCaseDetail(){ const d=activeData(), r=d.rows.find(x=>x.id===state.selectedCase); if(!r){$('#caseDetail').innerHTML='Select a case to see its original passages and scores.
';return;} const saved=(d.case_results[state.caseMethod]||[]).find(x=>x.id===r.id); if(!saved){$('#caseDetail').innerHTML='No stored result for this method.
';return;} const scores=saved.scores; const candidates=[{label:'Relevant passage',type:'positive',text:r.positive_passage,score:scores[0],original:0},{label:'Hard negative',type:'negative',text:r.hard_negative,score:scores[1],original:1},{label:'Easy negative',type:'negative',text:r.easy_negative,score:scores[2],original:2}]; candidates.sort((a,b)=>b.score-a.score||b.original-a.original); const winner=saved.positive_rank===1; const max=Math.max(...scores,0.000001),min=Math.min(...scores,0); $('#caseDetail').innerHTML=`${esc(c.text)}
Scores are retrieval scores, not confidence probabilities. Bars rescale to each case's minimum and maximum. The correct passage is defined in the curated dataset.
`; } function renderExplorer(){filtersUI();renderMethodSelectors();renderCaseList();} function render(){if(!state.db)return;renderOverview();renderExplorer();} function setSplit(split){if(!state.db||!state.db.splits[split])return;state.split=split;state.selectedCase=null;state.search='';state.language='all';state.domain='all';render();} function showView(which){state.view=which;$$('.tab').forEach(el=>{let selected=el.dataset.view===which;el.classList.toggle('active',selected);el.setAttribute('aria-selected',String(selected));});$$('.view').forEach(v=>v.classList.toggle('active',v.id===which));} function download(name, text, mime){const blob=new Blob([text],{type:mime});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),1000);} function exportCsv(){if(!state.db)return;const rows=[['split','method','status','n','accuracy_at_1','mrr','avg_latency_ms']];for(const [label,d] of Object.entries(state.db.splits)){for(const m of d.results.models){rows.push([label,m.name,m.status,m.n,m.accuracy_at_1??'',m.mrr??'',m.avg_latency_ms??'']);}}const csv=rows.map(x=>x.map(v=>'"'+String(v??'').replaceAll('"','""')+'"').join(',')).join('\r\n')+'\r\n';download('modelbench-verified-benchmarks.csv',csv,'text/csv;charset=utf-8');} async function load(){try{const res=await fetch('./benchmark-data.json',{cache:'no-store'});if(!res.ok)throw Error('Dataset could not be loaded (HTTP '+res.status+').');const obj=await res.json();if(obj?.splits?.monolingual?.rows?.length!==30||obj?.splits?.['cross-language']?.rows?.length!==18)throw Error('Dataset is incomplete or invalid.');state.db=obj;$('#lastStatus').textContent='● Stored results verified · no server needed';$('#errorBanner').hidden=true;render();}catch(err){$('#errorBanner').textContent='Could not display the evaluation data: '+err.message+' Please confirm benchmark-data.json was uploaded alongside index.html.';$('#errorBanner').hidden=false;$('#lastStatus').textContent='Data unavailable';$('#lastStatus').classList.add('bad');}} $('#splitMono').addEventListener('click',()=>setSplit('monolingual')); $('#splitCross').addEventListener('click',()=>setSplit('cross-language')); $$('.tab').forEach(b=>b.addEventListener('click',()=>showView(b.dataset.view))); $('#metricSelect').addEventListener('change',e=>{state.metric=e.target.value;renderLeaderboard();}); $('#modelSelect').addEventListener('change',e=>{state.method=e.target.value;renderBreakdown();}); $('#groupSelect').addEventListener('change',e=>{state.group=e.target.value;renderBreakdown();}); $('#caseModelSelect').addEventListener('change',e=>{state.caseMethod=e.target.value;renderCaseDetail();}); $('#querySearch').addEventListener('input',e=>{state.search=e.target.value;renderCaseList();}); $('#langFilter').addEventListener('change',e=>{state.language=e.target.value;renderCaseList();}); $('#domainFilter').addEventListener('change',e=>{state.domain=e.target.value;renderCaseList();}); $('#exportBtn').addEventListener('click',exportCsv); load();