Spaces:
Running
Running
File size: 10,747 Bytes
61fe966 6bf37b5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <!doctype html>
<html lang="tr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#070a12">
<meta name="description" content="DUSUNEN Pusula ile 384'ten 32 boyuta canlı Matryoshka Türkçe arama laboratuvarı.">
<title>DUSUNEN Vector Lab</title>
<style>
:root{color-scheme:dark;--bg:#070a12;--panel:#101626;--line:#273047;--text:#f6f7ff;--muted:#99a6bd;--violet:#a78bfa;--cyan:#54d9e8;--lime:#b8f28d}
*{box-sizing:border-box}body{margin:0;min-height:100vh;background:radial-gradient(circle at 12% 0,rgba(118,80,230,.24),transparent 36rem),radial-gradient(circle at 100% 35%,rgba(38,211,232,.12),transparent 32rem),var(--bg);color:var(--text);font-family:Inter,ui-sans-serif,system-ui,sans-serif}body:before{content:"";position:fixed;inset:0;pointer-events:none;opacity:.15;background-image:linear-gradient(rgba(255,255,255,.07) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.07) 1px,transparent 1px);background-size:50px 50px;mask-image:linear-gradient(#000,transparent 76%)}
.shell{position:relative;width:min(1080px,calc(100% - 30px));margin:auto;padding:28px 0 66px}nav{display:flex;justify-content:space-between;align-items:center;padding-bottom:24px;border-bottom:1px solid var(--line)}.brand{font-weight:850}.brand b{display:inline-grid;place-items:center;width:34px;height:34px;margin-right:10px;border:1px solid rgba(167,139,250,.55);border-radius:11px;color:var(--violet);font:750 10px ui-monospace,monospace}nav a,footer a{color:var(--muted);font-size:12px;text-decoration:none}
header{padding:72px 0 34px}.kicker{color:var(--cyan);font:700 11px ui-monospace,monospace;letter-spacing:.14em;text-transform:uppercase}h1{max-width:880px;margin:17px 0;font-size:clamp(45px,8vw,78px);line-height:.98;letter-spacing:-.06em}.gradient{color:transparent;background:linear-gradient(100deg,#fff,var(--violet),var(--cyan));background-clip:text}.lead{max-width:790px;margin:0;color:var(--muted);font-size:18px;line-height:1.7}.lead strong{color:var(--text)}
.lab{padding:22px;border:1px solid var(--line);border-radius:21px;background:rgba(16,22,38,.94);box-shadow:0 28px 80px rgba(0,0,0,.28)}label{display:block;margin-bottom:9px;color:var(--muted);font:650 10px ui-monospace,monospace;letter-spacing:.1em;text-transform:uppercase}.controls{display:grid;grid-template-columns:1fr auto;gap:10px}input{height:54px;padding:0 17px;border:1px solid var(--line);border-radius:12px;outline:0;background:#090d17;color:var(--text);font:500 15px inherit}input:focus{border-color:var(--cyan);box-shadow:0 0 0 3px rgba(84,217,232,.1)}button{height:54px;padding:0 20px;border:0;border-radius:12px;background:var(--text);color:#080c15;font:800 13px inherit;cursor:pointer}button:disabled{opacity:.55;cursor:wait}.dims{display:flex;flex-wrap:wrap;gap:7px;margin-top:15px}.dim{height:36px;padding:0 13px;border:1px solid var(--line);background:transparent;color:var(--muted);font:700 11px ui-monospace,monospace}.dim.active{border-color:var(--cyan);background:rgba(84,217,232,.1);color:var(--cyan)}.status{display:flex;justify-content:space-between;gap:14px;margin-top:15px;color:var(--muted);font:600 10px ui-monospace,monospace}.bar{height:3px;margin-top:9px;background:#20283a;border-radius:3px;overflow:hidden}.bar span{display:block;width:0;height:100%;background:linear-gradient(90deg,var(--violet),var(--cyan));transition:width .25s}
.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:26px 0}.metric{padding:18px;border:1px solid var(--line);border-radius:15px;background:rgba(255,255,255,.025)}.metric strong{display:block;font-size:23px;letter-spacing:-.04em}.metric span{color:var(--muted);font:650 9px ui-monospace,monospace;text-transform:uppercase}.metric strong.accent{color:var(--lime)}
.result{display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:start;margin:10px 0;padding:18px;border:1px solid var(--line);border-radius:16px;background:linear-gradient(145deg,rgba(17,23,39,.97),rgba(9,13,22,.97))}.rank{display:grid;place-items:center;width:34px;height:34px;border:1px solid rgba(167,139,250,.45);border-radius:10px;color:var(--violet);font:700 11px ui-monospace,monospace}.result h2{margin:1px 0 6px;font-size:17px}.result p{margin:0;color:#b9c3d4;font-size:13px;line-height:1.6}.score{color:var(--cyan);font:700 10px ui-monospace,monospace}.empty{padding:28px;border:1px dashed var(--line);border-radius:16px;color:var(--muted);text-align:center}footer{display:flex;justify-content:space-between;gap:20px;margin-top:44px;padding-top:23px;border-top:1px solid var(--line);color:#68758b;font-size:11px}
@media(max-width:700px){header{padding-top:52px}.controls{grid-template-columns:1fr}.controls button{width:100%}.metrics{grid-template-columns:repeat(2,1fr)}.status{flex-direction:column}.result{grid-template-columns:auto 1fr}.score{grid-column:2}footer{flex-direction:column}}
</style>
</head>
<body><div class="shell">
<nav><div class="brand"><b>VEC</b>DUSUNEN Vector Lab</div><a href="https://huggingface.co/GoktugD/DUSUNEN-Pusula-118M-v1" target="_blank" rel="noreferrer">Model card ↗</a></nav>
<header><div class="kicker">Matryoshka retrieval / 384 → 32 dimensions</div><h1>Aynı model.<br><span class="gradient">Altı vektör bütçesi.</span></h1><p class="lead">DUSUNEN Pusula sorguyu bir kez kodlar. Boyutu değiştirerek sıralamanın ve indeks maliyetinin nasıl hareket ettiğini canlı gör. <strong>Sorgu cihazından çıkmaz.</strong></p></header>
<main>
<section class="lab">
<label for="query">Türkçe sorgu</label><div class="controls"><input id="query" value="Hard negative örnekleri arama kalitesini nasıl geliştirir?" maxlength="300" autocomplete="off"><button id="search">Modeli yükle ve karşılaştır</button></div>
<div class="dims" aria-label="Embedding dimension"><button class="dim active" data-dim="384">384-D</button><button class="dim" data-dim="256">256-D</button><button class="dim" data-dim="192">192-D</button><button class="dim" data-dim="128">128-D</button><button class="dim" data-dim="64">64-D</button><button class="dim" data-dim="32">32-D</button></div>
<div class="status"><span id="status">Hazır · ilk sorgu q8 ONNX modelini önbelleğe alır</span><span id="latency">—</span></div><div class="bar"><span id="progress"></span></div>
</section>
<section class="metrics"><div class="metric"><strong id="dimension">384</strong><span>dimensions</span></div><div class="metric"><strong id="bytes">1,536 B</strong><span>float32 / vector</span></div><div class="metric"><strong class="accent" id="reduction">0.0%</strong><span>index reduction</span></div><div class="metric"><strong id="accuracy">91.95%</strong><span>held-out triplet accuracy</span></div></section>
<section id="results"><div class="empty">Bir sorgu çalıştır; sonra boyut düğmeleriyle aynı adayların sıralamasını karşılaştır.</div></section>
</main>
<footer><span>Scores are cosine similarities, not calibrated probabilities.</span><span><a href="https://huggingface.co/datasets/GoktugD/DUSUNEN-Turkish-Retrieval-Benchmark-v1">Benchmark</a> · <a href="https://huggingface.co/GoktugD">Göktuğ Düşünen</a></span></footer>
</div><script type="module">
const ACC={384:91.95,256:91.70,192:90.75,128:89.85,64:88.90,32:86.40};
const query=document.querySelector("#query"),search=document.querySelector("#search"),status=document.querySelector("#status"),latency=document.querySelector("#latency"),progress=document.querySelector("#progress"),results=document.querySelector("#results"),worker=new Worker("./worker.js",{type:"module"});
let documents=[],embeddings=[],queryVector=null,currentDim=384,requestId=0,ready=false;
const assets=Promise.all([fetch("./corpus.json").then(r=>r.json()),fetch("./embeddings.json").then(r=>r.json())]).then(([d,e])=>{documents=d;embeddings=e});
function truncate(vector,dim){const out=vector.slice(0,dim);let norm=Math.sqrt(out.reduce((s,x)=>s+x*x,0));return out.map(x=>x/norm)}
function dot(a,b){let sum=0;for(let i=0;i<a.length;i++)sum+=a[i]*b[i];return sum}
function updateMetrics(){document.querySelector("#dimension").textContent=currentDim;document.querySelector("#bytes").textContent=`${(currentDim*4).toLocaleString("en-US")} B`;document.querySelector("#reduction").textContent=`${((1-currentDim/384)*100).toFixed(1)}%`;document.querySelector("#accuracy").textContent=`${ACC[currentDim].toFixed(2)}%`}
function render(){if(!queryVector)return;const q=truncate(queryVector,currentDim),ranked=embeddings.map((v,index)=>({index,score:dot(q,truncate(v,currentDim))})).sort((a,b)=>b.score-a.score).slice(0,5);results.replaceChildren(...ranked.map(({index,score},rank)=>{const item=documents[index],card=document.createElement("article");card.className="result";const r=document.createElement("span");r.className="rank";r.textContent=`#${rank+1}`;const body=document.createElement("div"),h=document.createElement("h2"),p=document.createElement("p"),s=document.createElement("span");h.textContent=item.title;p.textContent=item.text;body.append(h,p);s.className="score";s.textContent=`cosine ${score.toFixed(4)}`;card.append(r,body,s);return card}));status.textContent=`${currentDim}-D sıralama hazır · boyutlar arasında anında geçiş yapabilirsin`;updateMetrics()}
async function run(){if(query.value.trim().length<3)return;await assets;search.disabled=true;search.textContent=ready?"Kodlanıyor…":"Model yükleniyor…";progress.style.width=ready?"65%":"4%";worker.postMessage({type:"encode",query:query.value,requestId:++requestId})}
document.querySelectorAll(".dim").forEach(button=>button.addEventListener("click",()=>{document.querySelector(".dim.active").classList.remove("active");button.classList.add("active");currentDim=Number(button.dataset.dim);updateMetrics();render()}));search.addEventListener("click",run);query.addEventListener("keydown",e=>{if(e.key==="Enter")run()});
worker.onmessage=({data})=>{if(data.type==="progress"){if(data.event?.progress!=null)progress.style.width=`${Math.max(4,Math.round(data.event.progress))}%`;if(data.event?.file)status.textContent=`Model yükleniyor · ${data.event.file.split("/").pop()}`}else if(data.type==="result"&&data.requestId===requestId){queryVector=data.embedding;latency.textContent=`${data.inferenceMs.toFixed(0)} ms · ${documents.length} belge`;progress.style.width="100%";search.disabled=false;search.textContent="Yeniden karşılaştır";ready=true;render()}else if(data.type==="error"){status.textContent=`Yükleme hatası: ${data.message}`;progress.style.width="0";search.disabled=false;search.textContent="Yeniden dene"}};
</script></body></html>
|