DakshBeniwal111 commited on
Commit
60953bf
Β·
verified Β·
1 Parent(s): 694ce87

Upload threejs_component.py

Browse files
Files changed (1) hide show
  1. threejs_component.py +281 -0
threejs_component.py ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Three.js 3D BDH Walkthrough β€” self-contained HTML for st.components.v1.html()"""
2
+
3
+ def get_threejs_html(bdh_layer_activations, tf_layer_activations):
4
+ import json, numpy as np
5
+
6
+ N_NEURONS = 25 # 5Γ—5 grid per layer
7
+ def prep(stats_list, n=N_NEURONS):
8
+ layers = []
9
+ for s in stats_list:
10
+ acts = s["activations"].mean(0)[:n]
11
+ acts = (acts - acts.min()) / (acts.max() - acts.min() + 1e-8)
12
+ layers.append(acts.tolist())
13
+ return layers
14
+
15
+ bdh_data = json.dumps(prep(bdh_layer_activations))
16
+ tf_data = json.dumps(prep(tf_layer_activations))
17
+ n_layers = len(bdh_layer_activations)
18
+
19
+ return f"""<!DOCTYPE html>
20
+ <html>
21
+ <head>
22
+ <style>
23
+ body{{margin:0;background:#0d1117;overflow:hidden;font-family:monospace}}
24
+ canvas{{display:block}}
25
+ #ui{{position:absolute;top:12px;left:50%;transform:translateX(-50%);
26
+ display:flex;gap:10px;align-items:center;z-index:10}}
27
+ .btn{{background:#f97316;color:#fff;border:none;padding:7px 16px;
28
+ border-radius:8px;font-size:.82rem;font-weight:700;cursor:pointer}}
29
+ .btn:hover{{background:#fb923c}}
30
+ .btn.on{{background:#22c55e}}
31
+ #lbdh{{position:absolute;top:52px;left:25%;transform:translateX(-50%);
32
+ color:#f97316;font-weight:700;font-size:.95rem;pointer-events:none;
33
+ text-shadow:0 0 12px #f97316}}
34
+ #ltf{{position:absolute;top:52px;left:75%;transform:translateX(-50%);
35
+ color:#3b82f6;font-weight:700;font-size:.95rem;pointer-events:none;
36
+ text-shadow:0 0 12px #3b82f6}}
37
+ #info{{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);
38
+ color:#8b949e;font-size:.75rem;text-align:center;pointer-events:none}}
39
+ #leg{{position:absolute;top:52px;right:14px;color:#8b949e;
40
+ font-size:.73rem;line-height:1.9}}
41
+ .dot{{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:5px}}
42
+ </style>
43
+ </head>
44
+ <body>
45
+ <div id="ui">
46
+ <button class="btn" id="bRot">⟳ Auto-rotate</button>
47
+ <button class="btn" id="bPulse">⚑ Pulse Signal</button>
48
+ <button class="btn" id="bReset">β†Ί Reset</button>
49
+ </div>
50
+ <div id="lbdh">πŸ‰ BDH β€” Sparse ReLU</div>
51
+ <div id="ltf">πŸ€– Transformer β€” Dense GELU</div>
52
+ <div id="leg">
53
+ <div><span class="dot" style="background:#f97316"></span>BDH active</div>
54
+ <div><span class="dot" style="background:#4b6484;border:1px solid #5b7494"></span>BDH silent (~50%)</div>
55
+ <div><span class="dot" style="background:#3b82f6"></span>Transformer (always on)</div>
56
+ <div style="margin-top:5px;color:#6b7280">Drag Β· Scroll to zoom</div>
57
+ </div>
58
+ <div id="info">3D BDH Walkthrough β€” {n_layers} layers Γ— {N_NEURONS} neurons (5Γ—5) per side</div>
59
+
60
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
61
+ <script>
62
+ const BDH_DATA = {bdh_data};
63
+ const TF_DATA = {tf_data};
64
+ const N_LAYERS = {n_layers};
65
+ const N_NEURONS = {N_NEURONS};
66
+ const COLS = 5; // 5Γ—5 grid
67
+
68
+ const scene = new THREE.Scene();
69
+ scene.background = new THREE.Color(0x0d1117);
70
+ scene.fog = new THREE.Fog(0x0d1117, 35, 95);
71
+
72
+ const W = window.innerWidth, H = window.innerHeight;
73
+ const camera = new THREE.PerspectiveCamera(52, W/H, 0.1, 200);
74
+ camera.position.set(0, 4, 30);
75
+
76
+ const renderer = new THREE.WebGLRenderer({{antialias:true}});
77
+ renderer.setPixelRatio(window.devicePixelRatio);
78
+ renderer.setSize(W, H);
79
+ document.body.appendChild(renderer.domElement);
80
+
81
+ scene.add(new THREE.AmbientLight(0xffffff, 0.4));
82
+ const pl1 = new THREE.PointLight(0xf97316, 1.8, 70);
83
+ pl1.position.set(-9, 9, 14); scene.add(pl1);
84
+ const pl2 = new THREE.PointLight(0x3b82f6, 1.8, 70);
85
+ pl2.position.set(9, 9, 14); scene.add(pl2);
86
+
87
+ // ── Pivot: ALL objects go in here so rotation works ────────────────────────
88
+ const pivot = new THREE.Group();
89
+ scene.add(pivot);
90
+
91
+ const SPHERE = new THREE.SphereGeometry(0.23, 10, 10);
92
+ const LAYER_SEP = 4.8;
93
+ const SIDE_OFFSET = 8.5;
94
+ const GRID_SCALE = 0.9;
95
+
96
+ function gridPos(idx) {{
97
+ const col = idx % COLS, row = Math.floor(idx / COLS);
98
+ const cx = (COLS-1)/2, cy = (Math.ceil(N_NEURONS/COLS)-1)/2;
99
+ return {{x:(col-cx)*GRID_SCALE, y:(cy-row)*GRID_SCALE}};
100
+ }}
101
+
102
+ const bdhMeshes=[], tfMeshes=[], bdhMats=[], tfMats=[];
103
+
104
+ for (let l=0; l<N_LAYERS; l++) {{
105
+ const z = -(l-(N_LAYERS-1)/2)*LAYER_SEP;
106
+ for (let ni=0; ni<N_NEURONS; ni++) {{
107
+ const gp = gridPos(ni);
108
+
109
+ // ── BDH neuron ──────────────────────────────────────────────────────
110
+ const bAct = BDH_DATA[l][ni];
111
+ const silent = bAct < 0.08; // ReLU hard zero threshold
112
+ const bMat = new THREE.MeshPhongMaterial({{
113
+ color: silent ? 0x4b6484 : 0xf97316,
114
+ emissive: silent ? new THREE.Color(0x1a2535) : new THREE.Color(0xf97316).multiplyScalar(bAct*0.55),
115
+ transparent: true,
116
+ opacity: silent ? 0.55 : 0.88 + bAct*0.12,
117
+ shininess: silent ? 10 : 60,
118
+ }});
119
+ const bMesh = new THREE.Mesh(SPHERE, bMat);
120
+ bMesh.position.set(-SIDE_OFFSET+gp.x, gp.y, z);
121
+ bMesh.scale.setScalar(silent ? 0.58 : 0.78+bAct*0.48);
122
+ bMesh.userData = {{l, ni, act:bAct, silent}};
123
+ pivot.add(bMesh); // ← pivot, not scene
124
+ bdhMeshes.push(bMesh); bdhMats.push(bMat);
125
+
126
+ // ── Transformer neuron (GELU: always active) ────────────────────────
127
+ const tAct = TF_DATA[l][ni];
128
+ const tMat = new THREE.MeshPhongMaterial({{
129
+ color: 0x3b82f6,
130
+ emissive:new THREE.Color(0x3b82f6).multiplyScalar(0.38+tAct*0.38),
131
+ transparent:true, opacity:0.80+tAct*0.18, shininess:50,
132
+ }});
133
+ const tMesh = new THREE.Mesh(SPHERE, tMat);
134
+ tMesh.position.set(SIDE_OFFSET+gp.x, gp.y, z);
135
+ tMesh.scale.setScalar(0.72+tAct*0.42);
136
+ tMesh.userData = {{l, ni, act:tAct, silent:false}};
137
+ pivot.add(tMesh); // ← pivot
138
+ tfMeshes.push(tMesh); tfMats.push(tMat);
139
+ }}
140
+ }}
141
+
142
+ // ── Edges β€” also added to pivot so they rotate with neurons ───────────────
143
+ const bdhEdgeMats = [], tfEdgeMats = [];
144
+
145
+ function addEdges(meshes, color, maxEdgesPerLayer, edgeMatsArr) {{
146
+ const pts = [];
147
+ for (let l=0; l<N_LAYERS-1; l++) {{
148
+ const base = l*N_NEURONS;
149
+ let count = 0;
150
+ // Connect neurons between current layer (l) and next layer (l+1)
151
+ for (let ni=0; ni<N_NEURONS; ni++) {{
152
+ const src = meshes[base+ni];
153
+ if (src.userData.silent) continue;
154
+
155
+ for (let nj=0; nj<N_NEURONS; nj+=2) {{ // nj+=2 spreads edges out visually
156
+ const dst = meshes[base+N_NEURONS+nj];
157
+ if (dst.userData.silent) continue;
158
+
159
+ if (count < maxEdgesPerLayer) {{
160
+ pts.push(src.position.x, src.position.y, src.position.z,
161
+ dst.position.x, dst.position.y, dst.position.z);
162
+ count++;
163
+ }}
164
+ }}
165
+ }}
166
+ }}
167
+ const geo = new THREE.BufferGeometry();
168
+ geo.setAttribute("position", new THREE.Float32BufferAttribute(pts, 3));
169
+ const mat = new THREE.LineBasicMaterial({{color, transparent:true, opacity:0.18}});
170
+ const lines = new THREE.LineSegments(geo, mat);
171
+ pivot.add(lines);
172
+ edgeMatsArr.push(mat);
173
+ return mat;
174
+ }}
175
+
176
+ // Update the function calls right below it to pass edges PER LAYER:
177
+ addEdges(bdhMeshes, 0xf97316, 40, bdhEdgeMats); // 40 lines max between each BDH layer
178
+ addEdges(tfMeshes, 0x3b82f6, 80, tfEdgeMats); // 80 lines max between each TF layer
179
+
180
+ // ── Layer separator planes ─────────────────────────────────────────────────
181
+ for (let l=0; l<N_LAYERS; l++) {{
182
+ const z = -(l-(N_LAYERS-1)/2)*LAYER_SEP;
183
+ const pl = new THREE.Mesh(
184
+ new THREE.PlaneGeometry(14, 0.015),
185
+ new THREE.MeshBasicMaterial({{color:0x374151, transparent:true, opacity:0.4}})
186
+ );
187
+ pl.position.set(0,-2.4,z);
188
+ pivot.add(pl); // ← pivot
189
+ }}
190
+
191
+ // ── Mouse orbit ─────────────────────────────────────────────────────────────
192
+ let drag=false, pm={{x:0,y:0}}, rotX=0.1, rotY=0;
193
+ renderer.domElement.addEventListener("mousedown", e=>{{drag=true; pm={{x:e.clientX,y:e.clientY}}}});
194
+ renderer.domElement.addEventListener("mouseup", ()=>drag=false);
195
+ renderer.domElement.addEventListener("mousemove", e=>{{
196
+ if(!drag) return;
197
+ rotY+=(e.clientX-pm.x)*0.008; rotX+=(e.clientY-pm.y)*0.008;
198
+ pm={{x:e.clientX,y:e.clientY}};
199
+ }});
200
+ renderer.domElement.addEventListener("wheel", e=>{{
201
+ camera.position.z=Math.max(8,Math.min(55,camera.position.z+e.deltaY*0.04));
202
+ }});
203
+
204
+ // ── State ─────────────────────────────────────────────────────────────────
205
+ let autoRot=false, pulseActive=false, pulseT=0;
206
+ const clock=new THREE.Clock();
207
+
208
+ document.getElementById("bRot").onclick=function(){{
209
+ autoRot=!autoRot;
210
+ this.textContent=autoRot?"⏸ Pause":"⟳ Auto-rotate";
211
+ this.classList.toggle("on",autoRot);
212
+ }};
213
+ document.getElementById("bPulse").onclick=function(){{
214
+ pulseActive=true; pulseT=0;
215
+ this.textContent="⚑ Pulsing...";
216
+ setTimeout(()=>{{pulseActive=false; this.textContent="⚑ Pulse Signal";}},3000);
217
+ }};
218
+ document.getElementById("bReset").onclick=()=>{{
219
+ rotX=0.1; rotY=0; camera.position.set(0,4,30);
220
+ }};
221
+
222
+ // ── Animate ───────────────────────────────────────────────────────────────
223
+ function animate(){{
224
+ requestAnimationFrame(animate);
225
+ const t=clock.getElapsedTime();
226
+ if(autoRot) rotY+=0.005;
227
+ pivot.rotation.y=rotY; pivot.rotation.x=rotX;
228
+
229
+ // Idle pulse on active BDH neurons
230
+ for(let i=0;i<bdhMeshes.length;i++){{
231
+ if(!bdhMeshes[i].userData.silent){{
232
+ const p=1+0.07*Math.sin(t*2.4+i*0.35);
233
+ bdhMeshes[i].scale.setScalar((0.78+bdhMeshes[i].userData.act*0.48)*p);
234
+ }}
235
+ }}
236
+
237
+ // Signal pulse sweep β€” lights up neurons AND edges
238
+ if(pulseActive){{
239
+ pulseT+=0.018;
240
+ const waveZ=(pulseT*3.2-(N_LAYERS)*0.5)*LAYER_SEP;
241
+ // Neurons
242
+ for(let i=0;i<bdhMeshes.length;i++){{
243
+ const dist=Math.abs(bdhMeshes[i].position.z-waveZ);
244
+ const glow=Math.max(0,1-dist/2.2);
245
+ if(!bdhMeshes[i].userData.silent){{
246
+ bdhMats[i].emissive=new THREE.Color(1,0.6,0.1).multiplyScalar(glow*0.9+bdhMeshes[i].userData.act*0.35);
247
+ bdhMats[i].color=new THREE.Color(0xffffff).lerp(new THREE.Color(0xf97316),1-glow*0.6);
248
+ }} else {{
249
+ // Silent neurons flash dim on pulse wavefront
250
+ bdhMats[i].opacity=0.55+glow*0.35;
251
+ bdhMats[i].emissive=new THREE.Color(0x2a3d55).multiplyScalar(glow*0.5);
252
+ }}
253
+ }}
254
+ // Edges brighten on pulse
255
+ for(let m of bdhEdgeMats) m.opacity=0.18+Math.sin(pulseT*8)*0.25;
256
+ for(let m of tfEdgeMats) m.opacity=0.18;
257
+ }} else {{
258
+ // Reset to normal
259
+ for(let i=0;i<bdhMeshes.length;i++){{
260
+ const act=bdhMeshes[i].userData.act;
261
+ const sl=bdhMeshes[i].userData.silent;
262
+ bdhMats[i].color.set(sl?0x4b6484:0xf97316);
263
+ bdhMats[i].emissive=sl?new THREE.Color(0x1a2535):new THREE.Color(0xf97316).multiplyScalar(act*0.55);
264
+ bdhMats[i].opacity=sl?0.55:0.88+act*0.12;
265
+ }}
266
+ for(let m of bdhEdgeMats) m.opacity=0.18;
267
+ for(let m of tfEdgeMats) m.opacity=0.18;
268
+ }}
269
+
270
+ renderer.render(scene,camera);
271
+ }}
272
+ animate();
273
+
274
+ window.addEventListener("resize",()=>{{
275
+ camera.aspect=window.innerWidth/window.innerHeight;
276
+ camera.updateProjectionMatrix();
277
+ renderer.setSize(window.innerWidth,window.innerHeight);
278
+ }});
279
+ </script>
280
+ </body></html>"""
281
+