File size: 26,019 Bytes
1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 68d82b8 1a054f7 | 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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 'use strict';
(()=>{
const $=id=>document.getElementById(id), canvas=$('scene'), gl=canvas.getContext('webgl',{alpha:true,antialias:true,preserveDrawingBuffer:true});
if(!gl){$('message').textContent='WebGL is unavailable. Enable hardware acceleration in your browser.';return;}
let expanded=true,projectionCount=0;
let trace,token=0,mode='network',selected=0,head=0,edges=[],nodes=[],labels=[],total=0,kept=0,clock=0,last=0,play=false,signals=true,orbit=false,nextToken=0,frames=0,fpsStart=0,frameTimes=[];
const F=Filaments;let geometryTier=0;let moving=true,selectionId=-1,selectionFade=0,selectionGoal=0,transition=1,transitionStart=0,visualTime=0,cameraGoal=null;
let nodeIndex=new Map(),nodeByPosition=new Map(),adjacency=new Map(),normCache=new Map(),previousNodeColors=new Map(),previousEdgeColors=new Map(),lastNodeColors=new Map(),lastEdgeColors=new Map(),screenNodes=[],pickDirty=true,hoverX=-1,hoverY=-1,pickStamp=0;
let camera={yaw:-.14,pitch:.13,distance:62,target:[0,0,0]},matrix,drag=null,hover=null,focused=null;
const vs=`
attribute vec3 a;attribute vec3 b;attribute vec4 c;attribute vec4 d;
attribute vec4 meta;attribute vec4 prior;attribute vec4 lut;
uniform mat4 vp;uniform float time,particle,scale,selectedId,focusMix,transition,sway,blockLight;uniform mediump float point;
varying vec4 color;
float parameter(float q){
if(q<lut.x)return .25*q/max(lut.x,.00001);
if(q<lut.y)return .25+.25*(q-lut.x)/max(lut.y-lut.x,.00001);
if(q<lut.z)return .5+.25*(q-lut.y)/max(lut.z-lut.y,.00001);
return .75+.25*(q-lut.z)/max(1.-lut.z,.00001);
}
void main(){
float q=fract(time*d.y+d.x);float t=particle>.5?parameter(q):d.x;
float envelope=sin(t*3.14159265),wave=sin(time*.63+meta.z+t*4.2)*meta.w*sway;
vec3 p=mix(a,b,t);p.z+=envelope*(d.z+wave);p.y+=envelope*(d.w+wave*.7);
gl_Position=vp*vec4(p,1.);
color=mix(prior,c,transition);
// A solid, magnitude-shaded neuron body remains readable without bloom.
if(point>1.5){color.rgb*=.58+.42*sqrt(color.a);color.a=.62+.38*color.a;}
float hit=selectedId>=0.&&(abs(meta.x-selectedId)<.25||abs(meta.y-selectedId)<.25)?1.:0.;
float amount=focusMix*hit;
color.rgb=mix(color.rgb,vec3(1.,.98,.92),amount);
color.a*=mix(1.,.055,focusMix*(1.-hit));
color.a=mix(color.a,max(color.a,.66),amount);
if(lut.w>.5)color.a*=mix(blockLight,1.,amount);
if(particle>.5)color.a*=smoothstep(0.,.06,q)*(1.-smoothstep(.9,1.,q));
gl_PointSize=scale*(particle>.5?2.1:mix(1.9,3.4,sqrt(c.a)))*clamp(100./gl_Position.w,.65,4.5)*(1.+amount*.45);
if(point>1.5)gl_PointSize=clamp(gl_PointSize,2.2,6.5)*(1.+amount*.25);
}`;
const fs=`precision mediump float;varying vec4 color;uniform float point,exposure;
void main(){
float alpha=1.;vec3 rgb=color.rgb;
if(point>.5){
vec2 uv=(gl_PointCoord-.5)*2.;float r=length(uv);if(r>1.)discard;
if(point>1.5){
alpha=1.-smoothstep(.78,1.,r);
float dome=sqrt(max(0.,1.-r*r));
float highlight=pow(max(0.,1.-length(uv-vec2(-.25,-.28))),5.);
rgb=rgb*(.48+.52*dome)+vec3(.2)*highlight;
}else alpha=exp(-r*r*5.5);
}
gl_FragColor=vec4(rgb,color.a*alpha*exposure);
}`;
function shader(type,s){const sh=gl.createShader(type);gl.shaderSource(sh,s);gl.compileShader(sh);if(!gl.getShaderParameter(sh,gl.COMPILE_STATUS))throw Error(gl.getShaderInfoLog(sh));return sh;}
const program=gl.createProgram();gl.attachShader(program,shader(gl.VERTEX_SHADER,vs));gl.attachShader(program,shader(gl.FRAGMENT_SHADER,fs));gl.linkProgram(program);if(!gl.getProgramParameter(program,gl.LINK_STATUS))throw Error(gl.getProgramInfoLog(program));gl.useProgram(program);
const loc={};for(const k of ['a','b','c','d','meta','prior','lut'])loc[k]=gl.getAttribLocation(program,k);for(const k of ['vp','time','particle','scale','point','exposure','selectedId','focusMix','transition','sway','blockLight'])loc[k]=gl.getUniformLocation(program,k);
const buffers={line:gl.createBuffer(),node:gl.createBuffer(),pulse:gl.createBuffer()};let counts={};
function multiply(a,b){let o=new Float32Array(16);for(let c=0;c<4;c++)for(let r=0;r<4;r++)for(let k=0;k<4;k++)o[c*4+r]+=a[k*4+r]*b[c*4+k];return o;}
const sub=(a,b)=>a.map((v,i)=>v-b[i]),dot=(a,b)=>a.reduce((s,v,i)=>s+v*b[i],0),cross=(a,b)=>[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]],norm=a=>a.map(v=>v/Math.hypot(...a));
function view(){const t=camera.target,eye=[t[0]+Math.sin(camera.yaw)*Math.cos(camera.pitch)*camera.distance,t[1]+Math.sin(camera.pitch)*camera.distance,t[2]+Math.cos(camera.yaw)*Math.cos(camera.pitch)*camera.distance],z=norm(sub(eye,t)),x=[Math.cos(camera.yaw),0,-Math.sin(camera.yaw)],y=cross(z,x);const v=new Float32Array([x[0],y[0],z[0],0,x[1],y[1],z[1],0,x[2],y[2],z[2],0,-dot(x,eye),-dot(y,eye),-dot(z,eye),1]),f=1/Math.tan(.58/2),asp=canvas.width/canvas.height,n=.05,far=5000;return multiply(new Float32Array([f/asp,0,0,0,0,f,0,0,0,0,(far+n)/(n-far),-1,0,0,2*far*n/(n-far),0]),v);}
function project(p){const q=[...p,1],o=[0,0,0,0];for(let r=0;r<4;r++)for(let c=0;c<4;c++)o[r]+=matrix[c*4+r]*q[c];return [(o[0]/o[3]*.5+.5)*innerWidth,(-o[1]/o[3]*.5+.5)*innerHeight,o[3]];}
const color=(v,a=1)=>v>=0?[1,.055,.035,a]:[.025,1,.12,a];
function bank(values,x,height,z,title){let out=[];const max=Math.max(.000001,...values.map(Math.abs));for(let i=0;i<values.length;i++){const p=[x,(.5-i/Math.max(1,values.length-1))*height,z];const n={p,v:values[i],title:title+' ['+i+']',c:color(values[i],.3+.7*Math.sqrt(Math.abs(values[i])/max))};nodes.push(n);out.push(n);}return out;}
function label(p,title,sub=''){labels.push({p,title,sub});}
function edge(a,b,value,info,arc=0,kind='dense'){edges.push({a:a.p||a,b:b.p||b,v:value,info,arc,kind});}
function denseGraph(d,x,z=0,spacing=2.2,h=8){const input=d.input[token],out=d.output[token],a=bank(input,x,h,z,d.id+' input'),b=bank(out,x+spacing,h*Math.sqrt(out.length/input.length),z,d.id+' output');let all=[];for(let i=0;i<input.length;i++)for(let j=0;j<out.length;j++)all.push({i,j,v:input[i]*d.weight[i][j]});total+=all.length;all.sort((a,b)=>Math.abs(b.v)-Math.abs(a.v));let count=Math.max(1,Math.round(all.length*Number($('density').value)/100));for(const e of all.slice(0,count)){edge(a[e.i],b[e.j],e.v,`${d.id}\nx[${e.i}] × W[${e.i},${e.j}] = ${e.v.toPrecision(5)}\nx=${input[e.i].toPrecision(4)} · W=${d.weight[e.i][e.j].toPrecision(4)}`,0,'dense');}label([x+spacing/2,h/2+1.2,z],d.id.split('/').pop(),`${input.length} → ${out.length}`);return {a,b};}
function frame(x,y,z,w,h){const p=[[x-w/2,y-h/2,z],[x+w/2,y-h/2,z],[x+w/2,y+h/2,z],[x-w/2,y+h/2,z]];for(let i=0;i<4;i++)edge(p[i],p[(i+1)%4],0,'Module boundary',0,'frame');}
function moduleDenses(m){return trace.dense.filter(d=>d.id.startsWith(m.id+'/'));}
function network(){const g=AtomicGraph(trace,token,Number($('density').value));nodes=g.nodes;edges=g.edges;labels=g.labels;total=g.total;camera.distance=g.width/(2*Math.tan(.29)*(innerWidth/innerHeight))*1.12;camera.target=[3,-3,0];$('explain').textContent='One residual stream. Violet links show preceding layer deltas in the current block; gold links show deltas from earlier blocks. All '+g.routes.length+' H-DAR routes × '+trace.channels+' channels are retained. Blue junctions represent tensor operations; their links are structural dependencies. Hover a neuron to trace its links; click to pin.';}
function productionScene(){
if(mode==='dar'){dar();return;}
if(mode==='memory'){const m=trace.modules[selected],g=trace.memories.find(g=>g.id===m.id);if(!g){$('explain').textContent='Select a GDN-2 module.';return;}const h=Math.min(head,g.heads-1),a=g.states[h],mx=Math.max(1e-8,...a.flat().map(Math.abs));for(let i=0;i<a.length;i++)for(let j=0;j<a[i].length;j++)nodes.push({p:[(j/(a[i].length-1)-.5)*20,(.5-i/(a.length-1))*20,0],v:a[i][j],title:`H head ${h} [${i},${j}] · token ${g.token} · pooled region mean`,c:color(a[i][j],.2+.8*Math.sqrt(Math.abs(a[i][j])/mx))});heatmap(a,`FP32 serial reference · head ${h+1} · token ${g.token}`);label([0,12,0],'GDN STATE · '+m.label,'published checkpoint · '+g.dim+' × '+g.dim+(g.original_dim?' pooled from '+g.original_dim+' × '+g.original_dim:'' ));camera.distance=65;camera.target=[0,0,0];$('explain').textContent='FP32 reference memory from the published weights. Each compact cell is the mean of an 8×8 region in the original matrix. Only the final captured token is stored. TPU bf16/fused parity has not been established.';return;}
if(mode==='attention'){const m=trace.modules[selected],a=trace.attention.find(g=>g.id===m.id);if(!a){$('explain').textContent='Select an MLA module.';return;}const h=Math.min(head,a.heads-1),row=a.attention[h][token],src=bank(row,-10,16,0,'Attention probability'),out=bank([row.reduce((a,b)=>a+b,0)],10,0,0,'Σ attention');src.forEach((n,i)=>{if(i<=token)edge(n,out[0],n.v,`A[${token},${i}]=${n.v}`,0,'local');});heatmap(a.attention[h],'Captured FP32 MLA causal attention · head '+(h+1));label([0,10,0],'MLA · '+m.label,'query token '+token);camera.distance=60;camera.target=[0,0,0];$('explain').textContent='Causal attention across the captured GPT-2 tokens. Probabilities are computed using the published checkpoint weights.';return;}
const g=ProductionGraph(trace,token,mode==='projection',selected,Number($('groups').value),expanded);projectionCount=g.projectionCount||0;nodes=g.nodes;edges=g.edges;labels=g.labels;total=g.total;camera.distance=Math.max(mode==='projection'?95:0,g.width/(2*Math.tan(.29)*(innerWidth/innerHeight))*1.12);camera.target=[0,-3,0];
$('explain').textContent=mode==='projection'?`Individual channels of the selected module. Exact xᵢWᵢⱼ products: the 24 largest-magnitude outputs and 8 largest-magnitude inputs for each are saved. Detail is captured for token ${trace.detail_token+1}; other links are not exported.`:`All ${trace.metadata.config.num_blocks} blocks, ${trace.channels} channels. Overview nodes are means across ${Number($('groups').value)} groups. All ${trace.routes.reduce((n,r)=>n+r.sources.length,0)} H-DAR sources are retained. ${expanded?'40k+ mode includes measured contributions from '+projectionCount+' input Dense projections; 40,000+ links at full density.':'Standard view.'} Individual Dense contributions remain fixed to token ${trace.detail_token+1}. Select Module projections to inspect individual neurons.`;
}
function projection(){const m=trace.modules[selected],ds=moduleDenses(m),width=ds.length*5;ds.forEach((d,i)=>denseGraph(d,-width/2+i*5,(i%2?1:-1)*1.8,3.5,12));label([0,11,0],m.label,'Measured xᵢWᵢⱼ · bias is included in output, not edges');camera.distance=Math.max(85,width*1.9);camera.target=[-1,0,0];$('explain').textContent='Each link is xᵢ × Wᵢⱼ at the selected token. Color encodes sign; brightness encodes magnitude. Output nodes contain the sum of contributions plus bias. Q/K normalization, RoPE and SwiGLU are not drawn as Dense links.';}
function dar(){const m=trace.modules[selected];const r=trace.routes.find(r=>r.target===m.stage);if(!r){$('explain').textContent='The first layer has no preceding DAR sources.';camera.distance=40;return;}const target=bank(r.retrieved[token],9,15,0,'DAR retrieved'),res=bank(r.residual[token],14,15,0,'Residual'),sum=bank(r.residual[token].map((v,i)=>v+r.retrieved[token][i]),20,15,0,'Residual + retrieved');r.sources.forEach((id,s)=>{let vals=trace.stages.find(v=>v.id===id).values[token],z=(s-(r.sources.length-1)/2)*4.5;const b=bank(vals,-12,15,z,id);for(let c=0;c<b.length;c++){edge(b[c],target[c],vals[c]*r.weights[token][s],`DAR ${id}\n${trace.publication?'group mean':'channel'} ${c} · α=${r.weights[token][s].toPrecision(6)}\ncontribution=${(vals[c]*r.weights[token][s]).toPrecision(6)}`,0,'dar');}label([-12,9,z],id,'α = '+r.weights[token][s].toFixed(4));});for(let c=0;c<sum.length;c++){edge(target[c],sum[c],r.retrieved[token][c],'retrieved contribution',0,'retrieved');edge(res[c],sum[c],r.residual[token][c],'residual contribution',0,'residual');}label([9,9,0],'Retrieved Δ');label([14,9,0],'Residual');label([20,9,0],'Routed input');camera.distance=70;camera.target=[3,0,0];$('explain').textContent='Paper-DAR: learned query · RMSNorm keys → depth softmax. Links connect matching channels only: αₛΔₛ. The retrieved vector is added to the residual stream before sublayer normalization.';}
function memory(){const m=trace.modules[selected],g=trace.gdn.find(g=>g.id===m.id);if(!g){$('explain').textContent='Select a GDN-2 module to inspect its memory.';return;}const h=Math.min(head,g.heads-1),state=g.states[token][h],dim=state.length;const q=bank(g.q[token][h],-13,14,0,'q'),k=bank(g.k[token][h],-9,14,-3,'k'),v=bank(g.write_value[token][h],-9,14,3,'w·v − erase'),read=bank(g.measured[token][h],13,14,0,'Measured kernel output');let max=Math.max(1e-6,...state.flat().map(Math.abs));for(let i=0;i<dim;i++)for(let j=0;j<state[i].length;j++){const p=[(j/(state[i].length-1)-.5)*8,(.5-i/(dim-1))*14,0],n={p,v:state[i][j],title:`H[${i},${j}] reference`,c:color(state[i][j],.3+.7*Math.abs(state[i][j])/max)};nodes.push(n);const contribution=g.q[token][h][i]/Math.sqrt(dim)*state[i][j];edge(q[i],n,contribution,`Read q[${i}]H[${i},${j}]/√d = ${contribution}`,0,'dense');edge(n,read[j],contribution,'Reference read contribution',0,'dense');total+=2;}
label([0,9,0],'RECURRENT STATE','Hₜ = decay(Hₜ₋₁) + k ⊗ (w·v − erase)');label([-13,9,0],'Query');label([-9,9,-3],'Key');label([-9,9,3],'Write value');label([13,9,0],'Kernel output');camera.distance=65;camera.target=[0,0,0];heatmap(state,'GDN Hₜ · serial reference · max output error '+g.max_error.toExponential(2));$('explain').textContent='Memory is reconstructed using the serial recurrence, not captured from fused-kernel internals. The measured kernel output is on the right. Comparison error is retained. Key and write value have separate banks.';}
function attention(){const m=trace.modules[selected],a=trace.mla.find(g=>g.id===m.id);if(!a){$('explain').textContent='Select an MLA module to inspect attention.';return;}const h=Math.min(head,a.heads-1),weights=a.attention[h][token],dim=a.v[0][h].length,context=Array(dim).fill(0);for(let t=0;t<=token;t++)for(let d=0;d<dim;d++)context[d]+=weights[t]*a.v[t][h][d];const out=bank(context,12,14,0,'Attention context Σ A·V');for(let t=0;t<=token;t++){const z=(t-token/2)*1.8,vals=a.v[t][h],v=bank(vals,-10,14,z,'V token '+t);for(let d=0;d<dim;d++){edge(v[d],out[d],weights[t]*vals[d],`A[${token},${t}]V[${t},${d}] = ${weights[t]*vals[d]}`,0,'dense');total++;}label([-10,9,z],'Byte '+t,'α = '+weights[t].toFixed(4));}label([12,9,0],'ATTENTION CONTEXT','Σ Aₜₛ Vₛ');camera.distance=Math.max(65,token*2);camera.target=[0,0,0];heatmap(a.attention[h],'MLA causal attention · query '+token+' · max output error '+a.max_error.toExponential(2));$('explain').textContent='Each link connects a previous token V channel to the matching context channel: AₜₛVₛ. A causal mask excludes future tokens. Q/K after RoPE determine A; output is checked against the model.';}
function heatmap(data,caption){const c=$('heat'),cx=c.getContext('2d');c.style.display='block';let max=Math.max(1e-8,...data.flat().map(Math.abs));cx.clearRect(0,0,256,256);data.forEach((row,i)=>row.forEach((v,j)=>{const col=color(v),s=Math.sqrt(Math.abs(v)/max);cx.fillStyle=`rgb(${col.slice(0,3).map(v=>Math.round(12+v*s*235)).join(',')})`;cx.fillRect(j*256/row.length,i*256/data.length,Math.ceil(256/row.length),Math.ceil(256/data.length));}));$('heatCaption').textContent=caption;}
/* @renderer */
function build(reset=true){if(!trace)return;const old=JSON.parse(JSON.stringify(camera)),selectedKey=focused?F.key(focused):null;previousNodeColors=lastNodeColors;previousEdgeColors=lastEdgeColors;focused=null;hover=null;frameTimes=[];edges=[];nodes=[];labels=[];total=0;document.body.classList.toggle('detail-view',mode!=='network');$('heat').style.display='none';$('heatCaption').textContent='';if(trace.version===4)productionScene();else ({network,projection,dar,memory,attention}[mode])();if(!reset)camera=old;if(trace.version===4){const dense=edges.filter(e=>e.kind==='dense').sort((a,b)=>Math.abs(b.v)-Math.abs(a.v)),keep=new Set(dense.slice(0,Math.ceil(dense.length*Number($('density').value)/100)));edges=edges.filter(e=>e.kind!=='dense'||keep.has(e));}focused=selectedKey?nodes.find(n=>F.key(n)===selectedKey)||null:null;uploadGeometry();setSelection(focused);transition=previousNodeColors.size?0:1;transitionStart=visualTime;pickDirty=true;$('labels').replaceChildren();for(const l of labels){const el=document.createElement('div');el.className='scene-label';const title=document.createElement('strong');title.textContent=l.title;const sub=document.createElement('span');sub.className='sub';sub.textContent=l.sub;el.append(title,sub);$('labels').append(el);l.el=el;}$('stats').textContent=`${trace.version===4?'HF · FP32 · ':''}${nodes.length.toLocaleString()} nodes · ${edges.filter(e=>e.kind!=='frame').length.toLocaleString()} links${total?' · Dense: '+kept.toLocaleString()+' / '+total.toLocaleString():''} · ${trace.channels} channels`;$('tokenLabel').textContent=`${trace.version===4?'TOKEN':'BYTE'} ${token+1} / ${trace.tokens.length} · ${trace.tokens[token].label}`;$('token').value=token;[...$('tokens').children].forEach((b,i)=>b.classList.toggle('active',i===token));$('predictions').replaceChildren();const p=document.createElement('p');p.className='eyebrow';p.textContent=trace.version===4?'NEXT GPT-2 TOKEN / TOP 5':'NEXT BYTE / TOP 5';$('predictions').append(p);for(const t of trace.top[token]){const d=document.createElement('div');const a=document.createElement('span'),b=document.createElement('span');a.textContent=t.label.replaceAll('\n','⏎').replaceAll('\t','⇥').replaceAll(' ','␠');b.textContent=(t.prob*100).toFixed(2)+'%';d.append(a,b);$('predictions').append(d);}if(focused)inspectNode(focused);}
function load(data){if(![3,4].includes(data.version)||!data.modules?.length||(data.version===3&&!data.dense?.length))throw Error('A complete version 3 or 4 trace is required');trace=data;normCache.clear();previousNodeColors.clear();previousEdgeColors.clear();lastNodeColors.clear();lastEdgeColors.clear();focused=null;if(document.body.dataset.replayOnly==='true'){$('text').readOnly=true;$('prompt').querySelector('button').textContent='New prompt in Colab';}$('detail40').disabled=data.version!==4;if(data.version!==4)expanded=false;$('detail40').classList.toggle('active',expanded);$('detail40').setAttribute('aria-pressed',String(expanded));token=data.version===4?data.detail_token:0;selected=0;head=0;$('text').value=data.text;$('module').replaceChildren();data.modules.forEach((m,i)=>{const o=document.createElement('option');o.value=i;o.textContent=m.label;$('module').append(o);});$('token').max=data.tokens.length-1;$('tokens').replaceChildren();data.tokens.forEach((t,i)=>{const b=document.createElement('button');b.textContent=t.label;b.title=(data.version===4?'Token ':'Byte ')+i;b.onclick=()=>{token=i;build(false);};$('tokens').append(b);});$('badge').textContent=`${data.version===4?'HF FP32':'TINY'} · ${data.channels}D · ${data.modules.length} MODULES`;if(data.version===4){$('head').replaceChildren();for(let h=0;h<data.metadata.config.n_heads;h++){const o=document.createElement('option');o.value=h;o.textContent='Head '+(h+1);$('head').append(o);}}$('provenance').textContent=`Tiny checkpoint · ${(data.metadata.checkpoint_sha256||data.metadata.checkpoint?.sha256||'').slice(0,12)}. Dense error ${(data.checks.dense_max_error||data.checks.projection_max_error||0).toExponential(2)}. MLA error ${(data.checks.mla_max_error||0).toExponential(2)}. GDN reference error ${(data.checks.gdn_reference_max_error||0).toExponential(2)}. Particles illustrate contribution direction; speed is illustrative, not processor timing.`;if(data.version===4)$('provenance').textContent=data.provenance+' · SHA256 '+data.metadata.checkpoint.sha256+' · '+data.seconds+' s';build();}
/* @interaction */
$('mode').onchange=e=>{mode=e.target.value;if(mode==='memory')selected=trace.modules.findIndex(m=>m.kind==='gdn2');if(mode==='attention')selected=trace.modules.findIndex(m=>m.kind==='mla');$('module').value=selected;build();};$('module').onchange=e=>{selected=Number(e.target.value);build();if(mode==='network'){const id=trace.modules[selected].stage,n=nodes.find(n=>n.id===id+':'+Math.floor(trace.version===4?Number($('groups').value)/2:trace.channels/2));if(n){camera.target=[n.p[0]-6,0,0];camera.distance=52;}}};$('head').onchange=e=>{head=Number(e.target.value);build(false);};$('density').oninput=e=>{$('densityValue').textContent=e.target.value+'%';build(false);};$('token').oninput=e=>{token=Number(e.target.value);build(false);};$('reset').onclick=()=>{cameraGoal=null;camera.yaw=-.14;camera.pitch=.13;build();};$('signals').onclick=()=>{signals=!signals;$('signals').textContent='Signals: '+(signals?'on':'off');};$('orbit').onclick=()=>{orbit=!orbit;$('orbit').textContent='Orbit: '+(orbit?'on':'off');};$('play').onclick=()=>{play=!play;$('play').textContent=play?'Ⅱ Pause':'▶ Tokens';};$('info').onclick=()=>document.body.classList.toggle('info-open');$('controls').onclick=()=>document.body.classList.toggle('controls-open');$('cinema').onclick=()=>{document.body.classList.toggle('cinematic');$('cinema').textContent=document.body.classList.contains('cinematic')?'Panels':'Cinema';};document.addEventListener('keydown',e=>{if(e.key==='Escape'){focused=null;hover=null;hoverX=-1;hoverY=-1;setSelection(null);document.body.classList.remove('cinematic');}});
$('export').onclick=()=>{const url=URL.createObjectURL(new Blob([JSON.stringify(trace)],{type:'application/json'})),a=document.createElement('a');a.href=url;a.download='atomic-trace-v'+trace.version+'.json';a.click();setTimeout(()=>URL.revokeObjectURL(url),5000);};$('detail40').onclick=()=>{expanded=!expanded;const reset=mode!=='network';mode='network';$('mode').value=mode;$('detail40').classList.toggle('active',expanded);$('detail40').setAttribute('aria-pressed',String(expanded));build(reset);};$('groups').onchange=()=>build();$('import').onchange=async e=>{try{const file=e.target.files[0];const raw=file.name.endsWith('.gz')?await new Response(file.stream().pipeThrough(new DecompressionStream('gzip'))).text():await file.text();load(JSON.parse(raw));$('message').textContent='Trace loaded';}catch(err){$('message').textContent=err.message;}};
$('prompt').onsubmit=async e=>{e.preventDefault();if(document.body.dataset.replayOnly==='true'){window.open(document.body.dataset.colabUrl,'_blank','noopener');return;}const b=e.target.querySelector('button');b.disabled=true;$('message').textContent='Running the model… The first pass may take several minutes.';try{let d;if(trace.version===4&&!window.google?.colab?.kernel)throw Error('This published-checkpoint capture runs in Colab. Enter a new prompt in the capture notebook.');if(window.google?.colab?.kernel){const r=await google.colab.kernel.invokeFunction(trace.version===4?'atomic.production.capture':'atomic.capture',[$('text').value],{});d=r.data['application/json'];}else{const r=await fetch('/api/trace',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({text:$('text').value})});if(!r.ok)throw Error(await r.text());d=await r.json();}load(d);$('message').textContent='Ready · '+d.seconds+' s';}catch(err){$('message').textContent='Capture failed: '+err.message;}finally{b.disabled=false;}};
const keys=new Set();
function panCamera(right,up,forward){const y=camera.yaw,p=camera.pitch,r=[Math.cos(y),0,-Math.sin(y)],f=[-Math.sin(y)*Math.cos(p),-Math.sin(p),-Math.cos(y)*Math.cos(p)],u=cross(r,f);camera.target=camera.target.map((v,i)=>v+r[i]*right+u[i]*up+f[i]*forward);}
function moveCamera(dt){if(!keys.size)return;cameraGoal=null;pickDirty=true;const speed=Math.max(2,camera.distance*.35)*dt*(keys.has('Shift')?3:1);panCamera(((keys.has('d')?1:0)-(keys.has('a')?1:0))*speed,((keys.has('e')?1:0)-(keys.has('q')?1:0))*speed,((keys.has('w')?1:0)-(keys.has('s')?1:0))*speed);}
window.addEventListener('keydown',e=>{if(/INPUT|TEXTAREA|SELECT/.test(e.target.tagName))return;const k=e.key==='Shift'?'Shift':e.key.toLowerCase();if(['w','a','s','d','q','e','Shift'].includes(k)){keys.add(k);e.preventDefault();}if(k==='f'&&(focused||hover)){focusCamera(focused||hover);}if(k==='home')$('reset').click();});
window.addEventListener('keyup',e=>keys.delete(e.key==='Shift'?'Shift':e.key.toLowerCase()));window.addEventListener('blur',()=>keys.clear());
const navigation=document.createElement('div');navigation.id='navigation';navigation.innerHTML='<button data-view="front">Front</button><button data-view="side">Side</button><button data-view="top">Top</button><button data-view="back">Back</button><button data-view="focus">Focus F</button><span>Drag: orbit · Right drag / Shift: pan · Wheel: zoom · WASD: fly · Q/E: elevation · Shift: faster · Home: reset</span>';document.body.append(navigation);
navigation.onclick=e=>{const v=e.target.dataset.view;if(!v)return;if(v==='focus'){if(focused||hover){focusCamera(focused||hover);}return;}cameraGoal=null;pickDirty=true;[camera.yaw,camera.pitch]=({front:[0,0],side:[Math.PI/2,0],top:[0,Math.PI/2-.001],back:[Math.PI,0]})[v];};
$('motion').onclick=()=>{moving=!moving;$('motion').textContent='Motion: '+(moving?'on':'paused');};$('near').onclick=()=>{const candidates=nodes.filter(n=>n.id?.includes('/selected y'));const target=focused||candidates.reduce((a,b)=>!a||Math.abs(b.p[0])+Math.abs(b.p[1])<Math.abs(a.p[0])+Math.abs(a.p[1])?b:a,null);focusCamera(target,125);};
window.addEventListener('error',e=>{$('message').textContent=e.message;});requestAnimationFrame(animate);(async()=>{try{let initial=window.ATOMIC_TRACE;if(!initial&&window.ATOMIC_TRACE_GZIP){const bytes=Uint8Array.from(atob(window.ATOMIC_TRACE_GZIP),c=>c.charCodeAt(0));initial=JSON.parse(await new Response(new Blob([bytes]).stream().pipeThrough(new DecompressionStream('gzip'))).text());}load(initial||await (await fetch('trace.json')).json());}catch(e){$('message').textContent=e.message;}})();
})();
|