Spaces:
Running
Running
Download app.js from MMOrgBench/orgbench-review: direct link, hf CLI and curl.
- Browser
- Download file 31.6 kB
-
https://huggingface.co/spaces/MMOrgBench/orgbench-review/resolve/main/app.js
- Command line
-
hf download hf://spaces/MMOrgBench/orgbench-review/app.js
-
curl -L -o app.js https://huggingface.co/spaces/MMOrgBench/orgbench-review/resolve/main/app.js
31.6 kB
| ; | |
| const $=s=>document.querySelector(s), esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); | |
| const fmt=n=>Number(n).toLocaleString('en-US'), pct=(a,b)=>b?`${(100*a/b).toFixed(1)}%`:'โ'; | |
| const kindNames={chat:'Slack',tracker:'Notion ยท Tracker',claim:'Notion ยท Claim',decision:'Notion ยท Decision',meeting:'ํ์ ๊ธฐ๋ก',email:'Email',doc:'๋ฌธ์',image:'๊ทธ๋ฆผ'}; | |
| const modNames={text:'Text',image:'Image',multi:'Multi-image'}; | |
| const taskOrder=['Fact','Attribution','Computation','Selection','Interpretation','Discrepancy','Resolution','State','Change','Abstention']; | |
| const taskNames={Fact:'Fact ยท ์ฌ์ค ์กฐํ',Attribution:'Attribution ยท ์ถ์ฒ ์ถ์ ',Computation:'Computation ยท ์๋ ๊ณ์ฐ',Selection:'Selection ยท ๋น๊ตยท์ ํ',Interpretation:'Interpretation ยท ํด์',Discrepancy:'Discrepancy ยท ๋ถ์ผ์น ์๋ณ',Resolution:'Resolution ยท ์ ํจ๊ฐ ๊ฒฐ์ ',State:'State ยท ์ํ',Change:'Change ยท ๋ณ๊ฒฝ'}; | |
| let INDEX,UNITS,unitMap,projectMap,recordUnits,questionMap,RANKS=null,rankError=false,renderGeneration=0; | |
| taskNames.Abstention='Abstention ยท ๋ต๋ณ ์ ๋ณด'; | |
| const qaCache=new Map(); | |
| let S={view:'qa',project:'',task:'',result:'',text:'',kind:'',id:'',page:1,tab:'retrieval',hitkind:'all',unit:''}; | |
| async function getJSON(path){const r=await fetch(path+'.gz');if(!r.ok)throw new Error(`${path} (${r.status})`);const b=new Uint8Array(await r.arrayBuffer());if(b[0]!==31||b[1]!==139)return JSON.parse(new TextDecoder().decode(b));if(typeof DecompressionStream==='undefined')throw new Error('์ต์ ๋ธ๋ผ์ฐ์ ์์ ์ด์ด ์ฃผ์ธ์. ๋ฌด์์ค ์์ถ ๋ฐ์ดํฐ ์ง์์ด ํ์ํฉ๋๋ค.');return new Response(new Blob([b]).stream().pipeThrough(new DecompressionStream('gzip'))).json();} | |
| function url(view,params={}){const q=new URLSearchParams();for(const[k,v]of Object.entries(params))if(v!==''&&v!==null&&v!==undefined&&v!==false)q.set(k,v);return '#'+view+(q.size?'?'+q:'');} | |
| function readState(){const raw=location.hash.slice(1),parts=raw.includes('?')?raw.split('?'):(raw.includes('=')?['clean',raw]:[raw,'']);const p=new URLSearchParams(parts[1]||''),aliases={capability:'group',family:'task',world:'project',evidence:'evidence_bucket'};let head=p.get('head')||'group';head=aliases[head]||head;let result=p.get('result')||p.get('verdict')||'';if(result==='wrong')result='incorrect';let project=p.get('project')||p.get('world')||p.get('f_world')||'';project=INDEX?.projects.find(x=>x.id===project||x.run===project)?.id||project;const requestedTask=p.get('task')||p.get('f_family')||'',requestedFacet=p.get('facet')||'';return {view:['clean','qa','world','results','stats'].includes(parts[0])?parts[0]:'clean',project,task:taskOrder.includes(requestedTask)?requestedTask:'',group:p.get('group')||p.get('f_capability')||'',result,model:p.get('model')||'luna',condition:p.get('condition')||'rag100',text:p.get('text')||'',kind:p.get('kind')||'',id:p.get('id')||'',page:Math.max(1,parseInt(p.get('page')||'1',10)||1),tab:p.get('tab')||'gold',hitkind:p.get('hitkind')||'all',unit:p.get('unit')||'',document:p.get('document')||'',head,facet:head==='task'&&!taskOrder.includes(requestedFacet)?'':requestedFacet,inclusion:p.get('inclusion')||'',interesting:p.get('interesting')||'',app:p.get('app')||'slack',room:p.get('room')||''};} | |
| function go(patch,replace=false){const next={...S,...patch};const h=url(next.view,Object.fromEntries(Object.entries(next).filter(([k])=>k!=='view')));if(replace){history.replaceState(null,'',h);S=next;render();}else if(location.hash===h){S=next;render();}else location.hash=h;} | |
| function projectLabel(id){return projectMap.get(id)?.label||id;} | |
| function shortSource(u){const lines=u.text.split('\n').filter(Boolean);return lines[1]||lines[0]||u.record_id;} | |
| function time(t){return (t||'').replace('T',' ');} | |
| function imageSrc(path){if(!/^media\/[a-f0-9]{64}\.(?:png|jpe?g|webp|gif)$/i.test(path||''))return '';return typeof LAYOUT_IMAGE_PATHS!=='undefined'&&LAYOUT_IMAGE_PATHS.has(path)?'https://huggingface.co/datasets/MMOrgBench/MMOrgBench/resolve/'+LAYOUT_REFRESH.hf_commit+'/'+path:path;} | |
| function badge(ok){return `<span class="chip ${ok?'good':'bad'}">${ok?'โ ์ ๋ต':'ร ์ค๋ต'}</span>`;} | |
| function overview(){const d=INDEX.summary;$('#overview').innerHTML=`<div class="stat"><span class="stat-label">Luna ยท ์ ์ญ RAG top100</span><strong>${pct(d.correct,d.questions)}</strong><small>${fmt(d.correct)} / ${fmt(d.questions)} ์ ๋ต ยท ์ฑ์ ์๋ฃ</small></div><div class="stat"><span class="stat-label">ํตํฉ ํ๋ก์ ํธ</span><strong>${d.projects}<small> ํ๋ก์ ํธ</small></strong><small>${fmt(d.records)}๊ฐ ์๋ฌธ ๊ธฐ๋ก</small></div><div class="stat"><span class="stat-label">๊ฒ์ ๋จ์</span><strong>${fmt(d.units)}</strong><small>ํ ์คํธ ${fmt(d.text_units)} ยท ์ด๋ฏธ์ง ${fmt(d.images)}</small></div><div class="stat"><span class="stat-label">์ง๋ฌธ ๊ด์ </span><strong>Omni</strong><small>ํ๋ก์ ํธ ์ฌ์ ํํฐ ์์</small></div>`;} | |
| function projectOptions(){return '<option value="">์ ์ฒด 32๊ฐ ํ๋ก์ ํธ</option>'+INDEX.projects.map(p=>`<option value="${p.id}" ${S.project===p.id?'selected':''}>${esc(p.id.toUpperCase())} ยท ${esc(p.label)}</option>`).join('');} | |
| function taskOptions(){return '<option value="">์ ์ฒด Task</option>'+taskOrder.map(t=>`<option value="${t}" ${S.task===t?'selected':''}>${esc(taskNames[t])}</option>`).join('');} | |
| function filterControls(world=false){return `<div class="filters"><label>${world?'์๋ฌธ ๊ฒ์':'์ง๋ฌธ ๊ฒ์'}<input type="search" id="search" placeholder="${world?'๋ณธ๋ฌธ, ์ธ๋ฌผ, ์ฑ๋, ํ์ผ๋ช โฆ':'์ง๋ฌธ ๋ด์ฉ ๋๋ Q / N / MU ๋ฌธํญ IDโฆ'}" value="${esc(S.text)}"></label><label>ํ๋ก์ ํธ<select id="project-filter">${projectOptions()}</select></label>${world?`<label>๊ธฐ๋ก ์ข ๋ฅ<select id="kind-filter"><option value="">์ ์ฒด ๊ธฐ๋ก</option>${Object.entries(kindNames).map(([k,v])=>`<option value="${k}" ${S.kind===k?'selected':''}>${v}</option>`).join('')}<option value="pixels" ${S.kind==='pixels'?'selected':''}>์ด๋ฏธ์ง ์๋ ๊ธฐ๋ก๋ง</option></select></label>`:`<label>Task<select id="task-filter">${taskOptions()}</select></label>`}<label>${world?'ํ์':'Luna ํ์ '}<select id="result-filter">${world?'<option value="">์๊ฐ์ ยท ์ค๋๋ ์</option>':`<option value="">์ ์ฒด ๋ฌธํญ</option><option value="correct" ${S.result==='correct'?'selected':''}>์ ๋ต๋ง</option><option value="incorrect" ${S.result==='incorrect'?'selected':''}>์ค๋ต๋ง</option><option value="no-image" ${S.result==='no-image'?'selected':''}>์ด๋ฏธ์ง ๋ฌธํญ ยท ๊ฒ์ ์ด๋ฏธ์ง 0</option>`}</select></label></div>`;} | |
| function bindFilters(world=false){let timer;$('#search')?.addEventListener('input',e=>{const pos=e.target.selectionStart,value=e.target.value;clearTimeout(timer);timer=setTimeout(()=>{go({text:value,page:1,id:'',unit:''},true);setTimeout(()=>{const el=$('#search');el?.focus();if(el&&pos!==null)el.setSelectionRange(pos,pos);},0);},250);});$('#project-filter')?.addEventListener('change',e=>go({project:e.target.value,page:1,id:'',unit:''}));$('#task-filter')?.addEventListener('change',e=>go({task:e.target.value,page:1,id:''}));$('#kind-filter')?.addEventListener('change',e=>go({kind:e.target.value,page:1,unit:''}));if(!world)$('#result-filter')?.addEventListener('change',e=>go({result:e.target.value,page:1,id:''}));} | |
| function pageControls(page,pages,extra=''){return `<div class="page-controls ${extra}"><button data-page="${page-1}" ${page<=1?'disabled':''}>โ ์ด์ </button><span>${page} / ${pages}</span><button data-page="${page+1}" ${page>=pages?'disabled':''}>๋ค์ โ</button></div>`;} | |
| function bindPages(){$$('[data-page]').forEach(b=>b.addEventListener('click',()=>go({page:Number(b.dataset.page),id:'',unit:''})));} | |
| function $$(s,base=document){return [...base.querySelectorAll(s)];} | |
| function filteredQuestions(){const needle=S.text.trim().toLowerCase();return INDEX.questions.filter(q=>(!S.project||q.project===S.project)&&(!S.task||q.task===S.task)&&(!needle||[q.q,q.id,projectLabel(q.project)].join(' ').toLowerCase().includes(needle))&&(!S.result||S.result==='correct'&&q.correct||S.result==='incorrect'&&!q.correct||S.result==='no-image'&&q.modality!=='text'&&q.images===0));} | |
| async function loadQuestion(id){const p=id.split('::')[0];if(!qaCache.has(p))qaCache.set(p,getJSON('data/qa/'+encodeURIComponent(p)+'.json').catch(e=>{qaCache.delete(p);throw e;}));const data=await qaCache.get(p);return data.items.find(q=>q.id===id);} | |
| async function renderQA(generation){const all=filteredQuestions(),pageSize=25,pages=Math.max(1,Math.ceil(all.length/pageSize));let page=Math.min(S.page,pages);let active=all.find(q=>q.id===S.id);if(active){page=Math.floor(all.indexOf(active)/pageSize)+1;}else active=all[(page-1)*pageSize];const start=(page-1)*pageSize;const shown=all.slice(start,start+pageSize);const good=all.filter(q=>q.correct).length; | |
| $('#workspace').innerHTML=filterControls()+`<div class="filter-foot"><span>ํ์ ${fmt(all.length)}๋ฌธํญ ยท ์ ๋ต ${fmt(good)} ยท ${pct(good,all.length)}</span><span>์ ์ฅ๋ Luna ํ์ ยท ์ง๋ฌธ ๋จ์</span><button id="reset-filters">ํํฐ ์ด๊ธฐํ</button></div><div class="qa-layout"><aside class="qa-list" aria-label="๋ฌธํญ ๋ชฉ๋ก"><div class="list-heading"><strong>๋ฌธํญ</strong><span>${all.length?start+1:0}โ${Math.min(start+pageSize,all.length)}</span></div><div class="list-items">${shown.length?shown.map(q=>`<a class="question-link ${q.id===active?.id?'selected':''}" href="${esc(url('qa',{...S,view:undefined,id:q.id,page,unit:''}))}" ${q.id===active?.id?'aria-current="true"':''}><span class="q-id">${esc(q.project.toUpperCase())} ยท ${esc(q.item)}<span class="${q.correct?'good':'bad'}">${q.correct?'โ':'ร'}</span></span><span class="q-title">${esc(q.q)}</span><span class="q-meta">${esc(projectLabel(q.project))} ยท ${esc(q.task)}</span></a>`).join(''):'<div class="empty">์กฐ๊ฑด์ ๋ง๋ ๋ฌธํญ์ด ์์ต๋๋ค.</div>'}</div>${pageControls(page,pages)}</aside><section id="question-detail" class="question-detail" aria-label="๋ฌธํญ ์์ธ">${active?'<div class="panel loading">๋ต๋ณ๊ณผ ๊ฒ์ ๊ธฐ๋ก์ ๋ถ๋ฌ์ค๋ ์ค์ ๋๋คโฆ</div>':'<div class="panel empty">ํํฐ๋ฅผ ๋ณ๊ฒฝํด ์ฃผ์ธ์.</div>'}</section></div>`; | |
| bindFilters();bindPages();const imageCounts=OrgBenchImageStats.summarize(all);$('.filter-foot').insertAdjacentHTML('beforeend',`<span>ํ์ฌ ๋ฌธํญ๋ค์ ๊ฒ์ ์ด๋ฏธ์ง: ํ๊ท ${imageCounts.mean===null?'โ':imageCounts.mean.toFixed(2)}์ฅ / 100๊ฐ ยท <a href="#results">์ ์ฒด ๋ถํฌ ๋ณด๊ธฐ</a></span>`);$$('.question-link .q-meta').forEach((el,i)=>el.insertAdjacentHTML('afterend',`<span class="q-image-count">๊ฒ์ ์ด๋ฏธ์ง ${shown[i].images} / 100</span>`));if(!active)return;try{const q=await loadQuestion(active.id);if(generation!==renderGeneration)return;if(!q)throw new Error('๋ฌธํญ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.');S.id=q.id;S.page=page;renderQuestion(q);}catch(e){if(generation===renderGeneration)$('#question-detail').innerHTML=`<div class="notice error">๋ฌธํญ์ ๋ถ๋ฌ์ค์ง ๋ชปํ์ต๋๋ค. ${esc(e.message)} <button onclick="location.reload()">๋ค์ ๋ถ๋ฌ์ค๊ธฐ</button></div>`;}} | |
| function renderQuestion(q){const projects=new Set(q.hits.map(h=>unitMap.get(h.id)?.project));$('#question-detail').innerHTML=`<article class="panel"><div class="question-top"><div class="eyebrow">${esc(q.project.toUpperCase())} ยท ${esc(projectLabel(q.project))} ยท ${esc(q.item)}</div><a class="subtle-link" href="${url('world',{project:q.project})}">์ด ํ๋ก์ ํธ ์๋ฌธ ๋ณด๊ธฐ โ</a></div><h1 class="question-text">${esc(q.q)}</h1><div class="chips"><span class="chip blue">${esc(q.group)} / ${esc(q.task)}</span><span class="chip">${esc(modNames[q.modality]||q.modality)} ๋ฌธํญ</span><span class="chip">๊ฒ์๋ ์ด๋ฏธ์ง ${q.images}์ฅ</span><span class="chip">${projects.size}๊ฐ ํ๋ก์ ํธ์ ๊ธฐ๋ก</span>${badge(q.grade.answer_ok)}</div><div class="answers"><section class="answer-card"><div class="answer-label">Gold ยท Omni<span class="muted">๊ฒ์์ฉ</span></div><div class="answer-body">${esc(q.gold)}</div></section><section class="answer-card"><div class="answer-label">Luna ๋ต๋ณ${badge(q.grade.answer_ok)}</div><div class="answer-body">${esc(q.answer)}</div></section></div><details class="judge"><summary>Luna ํ์ ์ด์ </summary><p>${esc(q.grade.grader_reason||'์ ์ฅ๋ ํ์ ์ด์ ๊ฐ ์์ต๋๋ค.')}</p></details><details class="plain-details"><summary>๋ชจ๋ธ ์๋ฌธ ์ถ๋ ฅ ยท ์ฌ์ฉ๋</summary><pre>${esc(q.raw)}</pre><p class="caption">์ ๋ ฅ ํ ํฐ ${fmt(q.usage?.reader?.prompt_tokens||0)} ยท ์ถ๋ ฅ ํ ํฐ ${fmt(q.usage?.reader?.completion_tokens||0)} ยท ๋ณ๋์ ๋น๊ณต๊ฐ ์ถ๋ก ๋ด์ฉ์ ์ ๊ณตํ์ง ์์ต๋๋ค.</p></details></article><section class="panel evidence-panel"><div class="tabs" role="tablist" aria-label="๊ทผ๊ฑฐ ๋ฐ ๋ชจ๋ธ ์ ๋ ฅ"><button role="tab" data-tab="retrieval" aria-selected="${S.tab==='retrieval'}" class="${S.tab==='retrieval'?'active':''}">๊ฒ์ top100</button><button role="tab" data-tab="input" aria-selected="${S.tab==='input'}" class="${S.tab==='input'?'active':''}">Luna ์ ๋ฌ ์์</button><button role="tab" data-tab="gold" aria-selected="${S.tab==='gold'}" class="${S.tab==='gold'?'active':''}">Gold ํ์ด ยท ๊ทผ๊ฑฐ</button></div><div id="tab-body" class="tab-body"></div></section>`;$$('[data-tab]').forEach(b=>b.addEventListener('click',()=>go({tab:b.dataset.tab})));renderEvidence(q);} | |
| function recordHTML(u,opts={}){const rank=opts.rank,selected=opts.selected,annotated=opts.annotated,originalRank=opts.originalRank,seq=opts.seq;const title=shortSource(u);const sourceTitle=title.length>165?title.slice(0,165)+'โฆ':title;let marks=`<span class="chip">${esc(kindNames[u.kind]||u.kind)}</span>${u.image?'<span class="chip blue">์ด๋ฏธ์ง</span>':''}`;if(annotated)marks+='<span class="chip warn">Gold ๊ทผ๊ฑฐ</span>';if(selected===false)marks+='<span class="chip warn">Luna์ ๋ฏธ์ ๋ฌ</span>';if(selected===true)marks+='<span class="chip good">top100 ํฌํจ</span>';const score=Number.isFinite(opts.score)?opts.score.toFixed(4):'';return `<details class="record" data-unit="${esc(u.id)}" ${opts.open?'open':''}><summary><span class="rank">${seq?'์์ '+seq:rank?'#'+rank:'์๋ฌธ'}</span><div><div class="record-topline">${marks}</div><div class="record-title">${esc(sourceTitle)}</div><div class="record-snippet">${esc(u.text.split('\n').slice(2).join('\n').slice(0,220))}</div><div class="record-meta">${esc(projectLabel(u.project))} ยท ${esc(time(u.timestamp))}<br>${esc(u.record_id)}${opts.imageRank?' ยท ์ด๋ฏธ์ง ์ค '+fmt(opts.imageRank)+'์':''}${seq&&originalRank?' ยท ๊ฒ์ #'+originalRank:''}</div></div><div class="score">${score?'์ ์ฌ๋<br>'+score:''}<span class="expand">ํผ์น๊ธฐ</span></div></summary><div class="record-body"><div class="native-text">${esc(u.text)}</div>${u.image?`<img class="record-image" src="${esc(imageSrc(u.image))}" alt="${esc(u.record_id)} ์๋ฌธ ์ด๋ฏธ์ง" loading="lazy" decoding="async">`:''}<div class="image-tools"><button type="button" data-open-unit="${esc(u.id)}">${u.image?'์ด๋ฏธ์ง ํฌ๊ฒ ๋ณด๊ธฐ':'์๋ฌธ ํฌ๊ฒ ๋ณด๊ธฐ'}</button><a href="${esc(url('world',{project:u.project,unit:u.id}))}">ํตํฉ ์๋์์ ์ด๊ธฐ โ</a></div></div></details>`;} | |
| function bindRecords(base=document){$$('[data-open-unit]',base).forEach(b=>b.addEventListener('click',()=>openUnit(b.dataset.openUnit)));$$('[data-record-ref]',base).forEach(b=>b.addEventListener('click',()=>{const units=recordUnits.get(b.dataset.recordRef)||[];if(units.length)openUnit(units[0].id);}));} | |
| function renderEvidence(q,body=$('#tab-body'),local=null){const tab=local?.tab||S.tab,hitkind=local?.hitkind||S.hitkind;if(tab==='gold'){const known=RANKS?.[q.id]||[];const rankMap=new Map(known.map(r=>[r.id,r]));const ids=[...new Set(q.evidence.flatMap(r=>(recordUnits.get(r)||[]).map(u=>u.id)))];const hits=new Map(q.hits.map(h=>[h.id,h]));body.innerHTML=`<div class="gold-warning">์๋ ํ์ดยท๊ทผ๊ฑฐ๋ ๊ฒ์์ฉ์ ๋๋ค. ๊ฒ์๋์ง ์์ ์๋ฌธ๋ ์ฌ๊ธฐ์๋ ์ด ์ ์์ง๋ง, ํด๋น ๋ฌธํญ์ Luna ์ ๋ ฅ์๋ ๋ค์ด๊ฐ์ง ์์์ต๋๋ค.</div>${q.solution?.length?`<details class="plain-details" open><summary>์ ์ฅ๋ Gold solution</summary><ol class="solution">${q.solution.map(s=>`<li>${esc(s.step)}<div>${(s.record_ids||[]).map(id=>`<button class="record-ref" data-record-ref="${esc(id)}">${esc(id)}</button>`).join('')}</div></li>`).join('')}</ol></details>`:''}<p class="caption">์ฃผ์์ ์ฐ๊ฒฐ๋ ${q.evidence.length}๊ฐ ๊ทผ๊ฑฐ ๊ธฐ๋ก์ ๋๋ค. ์ ์ผํ๊ฑฐ๋ ์ต์์ธ ๊ทผ๊ฑฐ ์งํฉ์ด๋ผ๋ ๋ป์ ์๋๋๋ค.${rankError?' ์ ์ฒด ์์ ์ง๋จ์ ๋ถ๋ฌ์ค์ง ๋ชปํ์ต๋๋ค.':''}</p><div class="hit-list">${ids.map(id=>{const u=unitMap.get(id),r=rankMap.get(id),h=hits.get(id);return recordHTML(u,{rank:r?.rank||h?.rank,score:r?.score??h?.score,imageRank:r?.image_rank,selected:hits.has(id),annotated:true});}).join('')||'<div class="empty">์ฐ๊ฒฐ๋ ๊ทผ๊ฑฐ ๊ธฐ๋ก์ด ์์ต๋๋ค.</div>'}</div>`;bindRecords(body);return;} | |
| const chronological=tab==='input';const hm=new Map(q.hits.map(h=>[h.id,h]));const ids=chronological?q.reader_order:q.hits.map(h=>h.id);const hitImages=ids.filter(id=>unitMap.get(id).image).length;const filtered=ids.filter(id=>hitkind==='image'?!!unitMap.get(id).image:hitkind==='text'?!unitMap.get(id).image:true);const projectCount=new Set(ids.map(id=>unitMap.get(id).project)).size; | |
| body.innerHTML=`<p class="context-note">${chronological?'์ ์ฌ๋ ์์ 100๊ฐ๋ฅผ ๋จผ์ ์ ํํ ๋ค ์๊ฐ์์ผ๋ก ๋ฐฐ์ดํ ์ค์ ๊ธฐ๋ก ์์์ ๋๋ค. ๋ง์ง๋ง์ ์ง๋ฌธ์ ๋ถ์ฌ Luna์ ์ ๋ฌํ์ต๋๋ค.':'32๊ฐ ํ๋ก์ ํธ ์ ์ฒด์์ ์ง๋ฌธ๊ณผ์ ์ ์ฌ๋๊ฐ ๋์ ์์๋ก ์ ํํ 100๊ฐ์ ๋๋ค. ํ ์คํธ์ ์ด๋ฏธ์ง๊ฐ ๊ฐ์ ์์์์ ๊ฒฝ์ํ๋ฉฐ, ์ฒจ๋ถ ํ์ผ์ ์๋์ผ๋ก ์ถ๊ฐํ์ง ์์ต๋๋ค.'}</p><div class="chips"><span class="chip">100๊ฐ ๊ฒ์ ๋จ์</span><span class="chip blue">์ด๋ฏธ์ง ${hitImages}์ฅ</span><span class="chip">ํ ์คํธ ์ ์ฉ ${100-hitImages}๊ฐ</span><span class="chip">${projectCount}๊ฐ ํ๋ก์ ํธ</span></div>${q.modality!=='text'&&!hitImages?'<p class="caption warn">์ด๋ฏธ์ง ๊ด๋ จ ๋ฌธํญ์ด์ง๋ง ์ด ์์ฒญ์๋ ์ด๋ฏธ์ง๊ฐ ํ ์ฅ๋ ์ ๋ฌ๋์ง ์์์ต๋๋ค. Gold ๊ทผ๊ฑฐ ํญ์์ ์ ์ธ๋ ์ด๋ฏธ์ง์ ์์๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.</p>':''}<div class="context-meter" aria-label="๊ฒ์ ๋จ์ 100๊ฐ ์ค ์ด๋ฏธ์ง ${hitImages}๊ฐ">${ids.map(id=>`<span class="${unitMap.get(id).image?'visual':''}" title="${esc(id)}"></span>`).join('')}</div><div class="hit-toolbar"><strong>${chronological?'Luna ์ ๋ ฅ์':'๊ฒ์ ์ ์ฌ๋์'}</strong><label>ํ์<select data-hit-kind><option value="all" ${hitkind==='all'?'selected':''}>์ ์ฒด 100๊ฐ</option><option value="image" ${hitkind==='image'?'selected':''}>์ด๋ฏธ์ง ์๋ ๊ธฐ๋ก๋ง</option><option value="text" ${hitkind==='text'?'selected':''}>ํ ์คํธ ๊ธฐ๋ก๋ง</option></select></label></div><div class="hit-list">${filtered.map(id=>{const h=hm.get(id);return recordHTML(unitMap.get(id),{rank:h.rank,score:h.score,seq:chronological?ids.indexOf(id)+1:null,originalRank:h.rank,annotated:q.evidence.includes(unitMap.get(id).record_id)});}).join('')||'<div class="evidence-empty">์ด ์์ฒญ์๋ ๊ฒ์๋ ์ด๋ฏธ์ง๊ฐ ์์ต๋๋ค. ํ์๋ฅผ ๋ฐ๊ฟ ํ ์คํธ ๊ธฐ๋ก์ ํ์ธํด ์ฃผ์ธ์.</div>'}</div><p class="caption">์ฝ์ฌ์ธ ์ ์ฌ๋๋ ๊ฒ์ ์์ ์ ์์ด๋ฉฐ ์ ๋ต ํ๋ฅ ์ด ์๋๋๋ค. ${chronological?'ํ๋ฉด์ Gold ํ์๋ ๊ฒ์์ฉ์ผ๋ก ๋ง๋ถ์ธ ๊ฒ์ด๋ฉฐ ์ค์ ์ ๋ ฅ์ ํฌํจ๋์ง ์์์ต๋๋ค.':''}</p>`;body.querySelector('[data-hit-kind]').addEventListener('change',e=>{if(local){local.hitkind=e.target.value;renderEvidence(q,body,local);}else go({hitkind:e.target.value});});bindRecords(body);} | |
| function openUnit(id){if(S.view==='world'||String(id).startsWith('layout23_')){const current=worldUnit(id);if(current)return openCleanRecord(current.record_id);return;}const u=unitMap.get(id);if(!u)return;const d=$('#record-dialog');$('#dialog-title').textContent=`${u.record_id} ยท ${kindNames[u.kind]||u.kind}`;$('#dialog-body').innerHTML=`<p class="eyebrow">${esc(projectLabel(u.project))} ยท ${esc(time(u.timestamp))}</p><div class="native-text">${esc(u.text)}</div>${u.image?`<img class="record-image" src="${esc(imageSrc(u.image))}" alt="${esc(u.record_id)} ์๋ฌธ ์ด๋ฏธ์ง"><a href="${esc(imageSrc(u.image))}" target="_blank" rel="noopener">์ด๋ฏธ์ง ์๋ณธ ํฌ๊ธฐ๋ก ์ด๊ธฐ โ</a>`:''}<p class="caption">์๋ฌธ์ ์ ํ ์๊ฐ์ ๊ทธ๋๋ก ํ์ํฉ๋๋ค. ์๊ฐ๋๋ ๋ณ๋๋ก ์ ์๋์ด ์์ง ์์ต๋๋ค.</p>`;if(!d.open)d.showModal();} | |
| function projectIntro(){if(!S.project)return `<details class="panel world-intro"><summary>32๊ฐ ํ๋ก์ ํธ ๊ตฌ์ฑ ยท ์ธ๋ฌผยท์ฑ๋ ๋ณด๊ธฐ</summary><div class="project-grid">${INDEX.projects.map(p=>`<a class="project-tile" href="${url('world',{project:p.id})}">${esc(p.id.toUpperCase())} ยท ${esc(p.label)}<small>${esc(p.run)}</small><small>${p.questions}๋ฌธํญ ยท ์ธ๋ฌผ ${p.people.length}๋ช </small></a>`).join('')}</div></details>`;const p=projectMap.get(S.project);if(!p)return '';return `<details class="panel world-intro"><summary>${esc(p.label)} ยท ์ธ๋ฌผ ${p.people.length}๋ช / ์ฑ๋ ${p.channels.length}๊ฐ</summary><p class="caption">${esc(p.run)} ยท Project CEO์ ๊ถํ์ ํด๋น ํ๋ก์ ํธ ์์์ ์ ์ง๋ฉ๋๋ค.</p><div class="people">${p.people.map(n=>`<div class="person">${esc(n.new_name)}<small>${esc(n.new_role)}</small></div>`).join('')}</div><div class="channels">${p.channels.map(c=>`<span class="chip">${esc(c.new_name)}</span>`).join('')}</div>${p.clients?.length?`<p class="caption">๊ณ ๊ฐ ๋ด๋น์: ${p.clients.map(c=>esc(c.new_name)+' ยท '+esc(c.company_name)).join(' / ')}</p>`:''}</details>`;} | |
| function renderWorld(){const needle=S.text.trim().toLowerCase();const all=UNITS.filter(u=>(!S.project||u.project===S.project)&&(!S.kind||(S.kind==='pixels'?!!u.image:u.kind===S.kind))&&(!needle||[u.text,u.record_id,projectLabel(u.project)].join(' ').toLowerCase().includes(needle)));const size=24,pages=Math.max(1,Math.ceil(all.length/size)),page=Math.min(S.page,pages),shown=all.slice((page-1)*size,page*size);$('#workspace').innerHTML=`<div class="section-head"><h1>ํตํฉ ์๋ ์๋ฌธ</h1><span class="muted">32๊ฐ ํ๋ก์ ํธ ยท ๊ฒ์์ ์ฌ์ฉํ ์๋ฌธ๊ณผ ํ์ด์ง ์ด๋ฏธ์ง</span></div>${filterControls(true)}<div class="filter-foot"><span>${fmt(all.length)}๊ฐ ๊ฒ์ ๋จ์ ยท ${fmt(new Set(all.map(u=>u.record_id)).size)}๊ฐ ๋ ผ๋ฆฌ ๊ธฐ๋ก</span><button id="reset-filters">ํํฐ ์ด๊ธฐํ</button></div>${projectIntro()}<div class="world-records">${shown.map(u=>recordHTML(u)).join('')||'<div class="panel empty">์กฐ๊ฑด์ ๋ง๋ ๊ธฐ๋ก์ด ์์ต๋๋ค.</div>'}</div>${pageControls(page,pages,'bottom-pages')}`;bindFilters(true);bindPages();bindRecords();if(S.unit&&unitMap.has(S.unit))openUnit(S.unit);} | |
| function groupStats(field,order){return order.map(k=>{const qs=INDEX.questions.filter(q=>q[field]===k);return {key:k,n:qs.length,ok:qs.filter(q=>q.correct).length};});} | |
| function statsTable(rows,label,href){return `<div class="table-wrap"><table><thead><tr><th>${label}</th><th>๋ฌธํญ</th><th>์ ๋ต</th><th>์ ํ๋</th></tr></thead><tbody>${rows.map(r=>`<tr><td>${href?`<a href="${esc(href(r.key))}">${esc(r.label||r.key)}</a>`:esc(r.label||r.key)}</td><td>${fmt(r.n)}</td><td>${fmt(r.ok)}</td><td>${pct(r.ok,r.n)}</td></tr>`).join('')}</tbody></table></div>`;} | |
| function renderResults(){const s=INDEX.summary;const mod=groupStats('modality',['text','image','multi']).map(r=>({...r,label:modNames[r.key]}));const groups=groupStats('group',['Retrieval','Synthesis','Alignment']);const tasks=groupStats('task',taskOrder).map(r=>({...r,label:taskNames[r.key]}));const im=INDEX.questions.filter(q=>q.modality!=='text');const buckets=[{key:'with',label:'์ด๋ฏธ์ง๊ฐ 1์ฅ ์ด์ ๊ฒ์๋จ',rows:im.filter(q=>q.images>0)},{key:'without',label:'๊ฒ์๋ ์ด๋ฏธ์ง 0์ฅ',rows:im.filter(q=>!q.images)}].map(r=>({...r,n:r.rows.length,ok:r.rows.filter(q=>q.correct).length}));$('#workspace').innerHTML=`<div class="section-head"><h1>์ต์ข ํ๊ฐ ๊ฒฐ๊ณผ</h1><span class="chip good">${fmt(s.questions)} / ${fmt(s.questions)} ์ฑ์ ์๋ฃ</span></div><div class="result-banner">GPT-5.6 Luna ยท Qwen3-VL-Embedding-2B ์ ์ญ top100 ยท <strong>${pct(s.correct,s.questions)}</strong> (${fmt(s.correct)} / ${fmt(s.questions)})</div><div class="results-grid"><section class="panel"><h2>Task ์์ ๊ทธ๋ฃน</h2>${statsTable(groups,'๊ทธ๋ฃน')}<p class="caption">๋ชจ๋ Luna ๋ต๋ณ ์ ํ๋์ ๋๋ค. ๊ฒ์๊ธฐ์ Recall@100 ์งํ๊ฐ ์๋๋๋ค.</p></section><section class="panel"><h2>๊ทผ๊ฑฐ ๋ชจ๋ฌ๋ฆฌํฐ</h2>${statsTable(mod,'๋ฌธํญ ๋ผ๋ฒจ')}<p class="caption">๋ฌธํญ์ ๋ถ์ฌ๋ ๋ผ๋ฒจ ๊ธฐ์ค์ ๋๋ค. ์ค์ ๊ฒ์๋ ์ด๋ฏธ์ง ์์๋ ๋ค๋ฆ ๋๋ค.</p></section><section class="panel"><h2>์ธ๋ถ Task</h2>${statsTable(tasks,'Task',k=>url('qa',{task:k}))}</section><section class="panel"><h2>์ด๋ฏธ์ง ๊ด๋ จ ๋ฌธํญ ยท ๊ฒ์ ๊ฒฐ๊ณผ</h2>${statsTable(buckets,'๊ฒ์๋ ์ด๋ฏธ์ง')}<p class="caption">์๋ก ๋ค๋ฅธ ๋ฌธํญ ์ง๋จ์ ๋น๊ต์ ๋๋ค. ์ด๋ฏธ์ง ์ ๊ณต ์ฌ๋ถ๋ง ๋ฐ๊พผ ๋์กฐ ์คํ์ด ์๋๋ฏ๋ก ์ธ๊ณผ์ ํจ๊ณผ๋ก ํด์ํ์ง ์์ต๋๋ค.</p><details class="plain-details" open><summary>๊ทธ๋ฆผ์ด ์์ด๋ Luna๊ฐ ๋ชป ๋ณธ ์ฌ๋ก</summary><p>โchild-in-redโ ๊ทธ๋ฆผ์ ์ด๋ฏธ์ง๋ผ๋ฆฌ ๋น๊ตํ๋ฉด 1์์ง๋ง, ํ ์คํธ๊น์ง ํฉ์น ์ ์ฒด ์์๋ 191์์ ๋๋ค. ๋ฐ๋ผ์ top100์ ํฌํจ๋์ง ์์์ต๋๋ค.</p><a href="${url('qa',{id:'p01::N260917_23',tab:'gold'})}">ํด๋น ๋ฌธํญ ยท ์ ์ฒด 191์ ๊ทธ๋ฆผ ํ์ธ โ</a></details></section></div><section class="panel"><h2>ํ๋ก์ ํธ๋ณ ์ฑ๋ฅ</h2>${statsTable(INDEX.projects.map(p=>({key:p.id,label:p.id.toUpperCase()+' ยท '+p.label,n:p.questions,ok:p.correct})),'ํ๋ก์ ํธ',k=>url('qa',{project:k}))}</section><section class="panel"><h2>์คํ ์ค์ ๊ณผ ํด์ ๋ฒ์</h2><div class="settings-grid"><div class="setting"><span>๊ฒ์ ๋์</span>32๊ฐ ํ๋ก์ ํธ ยท ${fmt(s.units)}๊ฐ ๋ ์ฝ๋ / ํ์ด์ง ๋จ์</div><div class="setting"><span>๊ฒ์ ๋ชจ๋ธ</span>Qwen3-VL-Embedding-2B ยท 2,048์ฐจ์ ยท ์ฝ์ฌ์ธ ์ ์ฌ๋</div><div class="setting"><span>์ง๋ฌธ ์ ๋ ฅ</span>์ง๋ฌธ ํ ์คํธ๋ง ยท ํ๊น ํ๋ก์ ํธ ์ฌ์ ํํฐ ์์</div><div class="setting"><span>์ด๋ฏธ์ง ์ ๋ ฅ</span>PDFยทPPT ํ์ด์ง์ ๋ณ๋ ๊ทธ๋ฆผ์ ์ค์ ํฝ์ ยท OCR / ์์ฑ ์ค๋ช ์ถ๊ฐ ์์</div><div class="setting"><span>Luna ์ปจํ ์คํธ</span>์ ์ญ top100 ์ ํ ํ ์๊ฐ์ ๋ฐฐ์ด ยท ์ฒจ๋ถ / ๋ฌธ์ ์ ์ฒด ์๋ ํ์ฅ ์์</div><div class="setting"><span>์ฑ์ </span>์งง์ Luna ์๋ฏธ ํ์ ยท ์ง๋ฌธ / ๊ด์ / Gold / ๋ชจ๋ธ ๋ต ๋น๊ต</div></div><p class="caption">์๋ต ๋ชจ๋ธ๊ณผ ์ฑ์ ๋ชจ๋ธ์ ๋ชจ๋ Luna์ ๋๋ค. ํ์ ์ ์ฌ๋์ ํ์ ๊ฒ์๊ฐ ์๋๋ฉฐ ์ด๊ฒฌ์ด ์๊ธธ ์ ์์ต๋๋ค. ์ด ์ฌ์ดํธ๋ ์ ์ฅ๋ ๊ฒฐ๊ณผ๋ฅผ ์ฝ๊ธฐ๋ง ํ๊ณ ๋ชจ๋ธ์ ์๋ก ์คํํ์ง ์์ต๋๋ค.</p></section>`;} | |
| function imageStatisticsHTML(){ | |
| const summarize=OrgBenchImageStats.summarize,s=summarize(INDEX.questions),visual=summarize(INDEX.questions.filter(q=>q.modality!=='text')); | |
| const rows=[{label:'์ ์ฒด ๋ฌธํญ',s},...['text','image','multi'].map(m=>({label:modNames[m],s:summarize(INDEX.questions.filter(q=>q.modality===m))}))]; | |
| return `<section class="panel" id="image-count-statistics"><h2>Top100์ ํฌํจ๋ ์ด๋ฏธ์ง ์</h2><p class="caption">๊ฐ ๋ฌธํญ์ ์ค์ ๊ฒ์ ๊ฒฐ๊ณผ 100๊ฐ ์ค ์ด๋ฏธ์ง๋ก ์ ๋ฌ๋ ํญ๋ชฉ ์์ ๋๋ค. ๋ฌธ์์ ํ์ด์ง ์ด๋ฏธ์ง์ ๋ณ๋ ๊ทธ๋ฆผ์ ๋ชจ๋ ์ ๋๋ค.</p><div class="image-count-summary"><div class="image-count-stat"><span>๋ฌธํญ๋น ํ๊ท </span><strong>${s.mean.toFixed(2)}์ฅ / 100๊ฐ</strong></div><div class="image-count-stat"><span>์ค์๊ฐ</span><strong>${s.median}์ฅ</strong></div><div class="image-count-stat"><span>์ต์โ์ต๋</span><strong>${s.min}โ${s.max}์ฅ</strong></div><div class="image-count-stat"><span>90๋ฐฑ๋ถ์์</span><strong>${s.p90.toFixed(1)}์ฅ</strong></div><div class="image-count-stat"><span>์ด๋ฏธ์ง 0์ฅ์ธ ๋ฌธํญ</span><strong>${fmt(s.zero)}๊ฐ ยท ${pct(s.zero,s.n)}</strong></div></div><div class="image-count-tables"><div><h3>์ด๋ฏธ์ง ์๋ณ ๋ฌธํญ ๋ถํฌ</h3><div class="table-wrap"><table><thead><tr><th>Top100์ ์ด๋ฏธ์ง ์</th><th>๋ฌธํญ</th><th>๋น์จ</th></tr></thead><tbody>${s.bins.map(b=>`<tr><td>${b.label}</td><td>${fmt(b.n)}</td><td>${pct(b.n,s.n)}</td></tr>`).join('')}</tbody></table></div></div><div><h3>๋ฌธํญ ๋ชจ๋ฌ๋ฆฌํฐ๋ณ</h3><div class="table-wrap"><table><thead><tr><th>๋ฌธํญ ๋ผ๋ฒจ</th><th>๋ฌธํญ</th><th>ํ๊ท ์ด๋ฏธ์ง ์</th><th>์ค์๊ฐ</th><th>์ด๋ฏธ์ง 0์ฅ ๋ฌธํญ</th></tr></thead><tbody>${rows.map(r=>`<tr><td>${r.label}</td><td>${fmt(r.s.n)}</td><td>${r.s.mean===null?'โ':r.s.mean.toFixed(2)}</td><td>${r.s.median??'โ'}</td><td>${fmt(r.s.zero)} ยท ${pct(r.s.zero,r.s.n)}</td></tr>`).join('')}</tbody></table></div></div></div><p class="caption">์ด๋ฏธ์ง ๊ด๋ จ ๋ฌธํญ(Image + Multi-image) ${fmt(visual.n)}๊ฐ: ํ๊ท ${visual.mean.toFixed(2)}์ฅ, ์ค์๊ฐ ${visual.median}์ฅ. ์ด ์ค ${fmt(visual.zero)}๊ฐ(${pct(visual.zero,visual.n)})์๋ ์ด๋ฏธ์ง๊ฐ ์ ๋ฌ๋์ง ์์์ต๋๋ค.</p><p class="caption">์ ์ฒด ${fmt(s.slots)}๊ฐ ๊ฒ์ ์ฌ๋กฏ ์ค ์ด๋ฏธ์ง ${fmt(s.total)}๊ฐ(${pct(s.total,s.slots)}). ๋์ผ ์ด๋ฏธ์ง๊ฐ ์ฌ๋ฌ ๋ฌธํญ์ ๊ฒ์๋๋ฉด ๊ฐ๊ฐ ์ง๊ณํ๋ฏ๋ก, ๊ณ ์ ์ด๋ฏธ์ง ์์ ๋ค๋ฆ ๋๋ค. ์ด๋ฏธ์ง๊ฐ ๊ฒ์๋๋ค๋ ๊ฒ๋ง์ผ๋ก ์ ๋ต์ ํ์ํ ๊ทธ๋ฆผ์ด ํฌํจ๋๋ค๋ ๋ป์ ์๋๋๋ค.</p></section>`; | |
| } | |
| function render(){ | |
| if(['qa','results'].includes(S.view))S.view='clean'; | |
| const generation=++renderGeneration;document.body.classList.toggle('corpus-view',S.view==='stats');$('#notice').textContent='';$('#overview').innerHTML=''; | |
| $$('[data-nav]').forEach(a=>{a.classList.toggle('active',a.dataset.nav===S.view);if(a.dataset.nav===S.view)a.setAttribute('aria-current','page');else a.removeAttribute('aria-current');}); | |
| if(S.view==='stats'){BenchmarkStats.show(generation);return;} | |
| if(S.view==='world'){renderWorldBrowser(generation);return;} | |
| renderClean(generation); | |
| } | |
| async function init(){try{[INDEX,UNITS]=await Promise.all([getJSON('data/index.json'),getJSON('data/units.json')]);unitMap=new Map(UNITS.map(u=>[u.id,u]));projectMap=new Map(INDEX.projects.map(p=>[p.id,p]));questionMap=new Map(INDEX.questions.map(q=>[q.id,q]));recordUnits=new Map();for(const u of UNITS){if(!recordUnits.has(u.record_id))recordUnits.set(u.record_id,[]);recordUnits.get(u.record_id).push(u);}S=readState();overview();render();getJSON('data/rank_checks.json').then(r=>{RANKS=r;refreshOpenReviewEvidence();if(S.view==='qa'&&S.tab==='gold'&&S.id){const id=S.id;loadQuestion(id).then(q=>{if(q&&S.id===id&&S.view==='qa'&&S.tab==='gold'&&$('#tab-body'))renderEvidence(q);});}}).catch(()=>{rankError=true;});}catch(e){$('#notice').className='notice error';$('#notice').innerHTML=`๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค์ง ๋ชปํ์ต๋๋ค. ${esc(e.message)} <button onclick="location.reload()">๋ค์ ๋ถ๋ฌ์ค๊ธฐ</button>`;}} | |
| window.addEventListener('hashchange',()=>{if(!INDEX)return;S=readState();if($('#record-dialog').open)$('#record-dialog').close();render();});$('.skip').addEventListener('click',e=>{e.preventDefault();$('#main').focus();$('#main').scrollIntoView({block:'start'});});$('#close-dialog').addEventListener('click',()=>$('#record-dialog').close());$('#record-dialog').addEventListener('click',e=>{if(e.target===$('#record-dialog'))$('#record-dialog').close();});init(); | |