PeterPinetree commited on
Commit
76f2906
·
1 Parent(s): 84b80eb

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +76 -3
index.html CHANGED
@@ -215,13 +215,86 @@
215
  }catch(e){ console.error(e); showError(e); setStatus('Error'); } finally{ busy=false; }
216
  }
217
 
218
- // Embedding Viewer
219
  function getEmbState(){ if(!EmbCache[currentModel]) EmbCache[currentModel]={coords:null,neigh:null,ids:null,baseDrawn:false}; return EmbCache[currentModel]; }
220
- async function ensureEmbeddings(){ const emb=getEmbState(); if(emb.coords&&emb.neigh&&emb.ids) return emb; const files=MODELS[currentModel].emb; emb.coords=await fetch(files.coords).then(r=>r.json()); emb.neigh=await fetch(files.neigh).then(r=>r.json()); emb.ids=new Set(Object.keys(emb.coords).map(Number)); emb.baseDrawn=false; return emb; }
 
 
 
 
 
 
 
 
 
 
221
  function getBounds(coords){ const pts=Object.values(coords); let minX=Infinity,minY=Infinity,maxX=-Infinity,maxY=-Infinity; for(const [x,y] of pts){ if(x<minX)minX=x; if(y<minY)minY=y; if(x>maxX)maxX=x; if(y>maxY)maxY=y; } return {minX,minY,maxX,maxY}; }
222
  function makeToXY(coords){ const {minX,minY,maxX,maxY}=getBounds(coords); const pad=18,w=canvas.width-pad*2,h=canvas.height-pad*2; return([x,y])=>{const nx=(x-minX)/(maxX-minX); const ny=(y-minY)/(maxY-minY); return [pad+nx*w,pad+(1-ny)*h];}; }
223
  function drawBase(emb,toXY){ ctx.clearRect(0,0,canvas.width,canvas.height); ctx.fillStyle='#1a2a3a'; for(const id in emb.coords){ const [x,y]=toXY(emb.coords[id]); ctx.beginPath(); ctx.arc(x,y,2,0,Math.PI*2); ctx.fill(); } emb.baseDrawn=true; }
224
- async function drawNeighborhood(tokenId){ const emb=await ensureEmbeddings(); if(!emb.ids.has(tokenId)){ embInfo.innerHTML='<span class="warn">Neighborhood unavailable for this token (not in the top-5k set).</span>'; nbrsEl.innerHTML=''; if(!emb.baseDrawn){const toXY=makeToXY(emb.coords); drawBase(emb,toXY);} return; } const toXY=makeToXY(emb.coords); drawBase(emb,toXY); const targetXY=toXY(emb.coords[tokenId]); const list=emb.neigh.neighbors?.[tokenId]||[]; ctx.fillStyle='#93c5fd'; for(const [nid] of list){ const pt=emb.coords[nid]; if(!pt) continue; const [x,y]=toXY(pt); ctx.beginPath(); ctx.arc(x,y,3.4,0,Math.PI*2); ctx.fill(); } ctx.fillStyle='#22d3ee'; ctx.beginPath(); ctx.arc(targetXY[0],targetXY[1],4.8,0,Math.PI*2); ctx.fill(); nbrsEl.innerHTML=''; embInfo.textContent='Nearest neighbors:'; for(const [nid,sim] of list.slice(0,18)){ const tok=decodeId(nid); const b=document.createElement('div'); b.className='chip'; b.textContent=`${tok} ${(sim*100).toFixed(1)}%`; nbrsEl.appendChild(b); } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
 
226
  // Events
227
  let debounceId;
 
215
  }catch(e){ console.error(e); showError(e); setStatus('Error'); } finally{ busy=false; }
216
  }
217
 
218
+ // Embedding Viewer (with cache)
219
  function getEmbState(){ if(!EmbCache[currentModel]) EmbCache[currentModel]={coords:null,neigh:null,ids:null,baseDrawn:false}; return EmbCache[currentModel]; }
220
+ async function ensureEmbeddings(){
221
+ const emb=getEmbState();
222
+ if(emb.coords&&emb.neigh&&emb.ids) return emb;
223
+ const files=MODELS[currentModel].emb;
224
+ emb.coords=await fetch(files.coords).then(r=>r.json());
225
+ emb.neigh =await fetch(files.neigh ).then(r=>r.json());
226
+ emb.ids =new Set(Object.keys(emb.coords).map(Number));
227
+ emb.baseDrawn=false;
228
+ return emb;
229
+ }
230
+
231
  function getBounds(coords){ const pts=Object.values(coords); let minX=Infinity,minY=Infinity,maxX=-Infinity,maxY=-Infinity; for(const [x,y] of pts){ if(x<minX)minX=x; if(y<minY)minY=y; if(x>maxX)maxX=x; if(y>maxY)maxY=y; } return {minX,minY,maxX,maxY}; }
232
  function makeToXY(coords){ const {minX,minY,maxX,maxY}=getBounds(coords); const pad=18,w=canvas.width-pad*2,h=canvas.height-pad*2; return([x,y])=>{const nx=(x-minX)/(maxX-minX); const ny=(y-minY)/(maxY-minY); return [pad+nx*w,pad+(1-ny)*h];}; }
233
  function drawBase(emb,toXY){ ctx.clearRect(0,0,canvas.width,canvas.height); ctx.fillStyle='#1a2a3a'; for(const id in emb.coords){ const [x,y]=toXY(emb.coords[id]); ctx.beginPath(); ctx.arc(x,y,2,0,Math.PI*2); ctx.fill(); } emb.baseDrawn=true; }
234
+
235
+ // ---- Fallback-aware neighborhood lookup ----
236
+ async function drawNeighborhood(tokenId){
237
+ const emb = await ensureEmbeddings();
238
+
239
+ // If direct match is missing, try space-prefixed and lowercase variants.
240
+ let id = tokenId;
241
+ if (!emb.ids.has(id)) {
242
+ try {
243
+ const decoded = decodeId(tokenId);
244
+ // try " space + token"
245
+ const sp = await tokenizer(' ' + decoded, { add_special_tokens:false });
246
+ const cand1 = Array.isArray(sp.input_ids) ? sp.input_ids.at(-1) : null;
247
+ if (cand1 != null && emb.ids.has(cand1)) id = cand1;
248
+ } catch {}
249
+ }
250
+ if (!emb.ids.has(id)) {
251
+ try {
252
+ const low = await tokenizer(decodeId(tokenId).toLowerCase(), { add_special_tokens:false });
253
+ const cand2 = Array.isArray(low.input_ids) ? low.input_ids.at(-1) : null;
254
+ if (cand2 != null && emb.ids.has(cand2)) id = cand2;
255
+ } catch {}
256
+ }
257
+
258
+ // Still not found: show message and (re)draw base if needed
259
+ if (!emb.ids.has(id)) {
260
+ embInfo.innerHTML = '<span class="warn">Neighborhood unavailable for this token (not in the current map).</span>';
261
+ nbrsEl.innerHTML = '';
262
+ if (!emb.baseDrawn) {
263
+ const toXY = makeToXY(emb.coords);
264
+ drawBase(emb, toXY);
265
+ }
266
+ return;
267
+ }
268
+
269
+ const toXY = makeToXY(emb.coords);
270
+ drawBase(emb, toXY); // refresh for clarity
271
+
272
+ const targetXY = toXY(emb.coords[id]);
273
+ const list = (emb.neigh.neighbors?.[id]) || [];
274
+
275
+ // neighbors
276
+ ctx.fillStyle = '#93c5fd';
277
+ for (const [nid] of list){
278
+ const pt = emb.coords[nid];
279
+ if (!pt) continue;
280
+ const [x,y] = toXY(pt);
281
+ ctx.beginPath(); ctx.arc(x, y, 3.4, 0, Math.PI*2); ctx.fill();
282
+ }
283
+ // target
284
+ ctx.fillStyle = '#22d3ee';
285
+ ctx.beginPath(); ctx.arc(targetXY[0], targetXY[1], 4.8, 0, Math.PI*2); ctx.fill();
286
+
287
+ // chips
288
+ nbrsEl.innerHTML = '';
289
+ embInfo.textContent = 'Nearest neighbors:';
290
+ for (const [nid, sim] of list.slice(0,18)){
291
+ const tok = decodeId(nid);
292
+ const b = document.createElement('div');
293
+ b.className = 'chip';
294
+ b.textContent = `${tok} ${(sim*100).toFixed(1)}%`;
295
+ nbrsEl.appendChild(b);
296
+ }
297
+ }
298
 
299
  // Events
300
  let debounceId;