Spaces:
Sleeping
Sleeping
Upload app.py
Browse files- dvnc_ai_v2_hf/app.py +144 -37
dvnc_ai_v2_hf/app.py
CHANGED
|
@@ -69,9 +69,13 @@ def build_metrics_md(metrics, model_used):
|
|
| 69 |
|
| 70 |
|
| 71 |
def build_frontend_payload(data):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
return f"""
|
| 73 |
<script>
|
| 74 |
-
window.__DVNC_GRAPH__ = {json.dumps(
|
| 75 |
</script>
|
| 76 |
{CONNECTOME_SNIPPET}
|
| 77 |
"""
|
|
@@ -153,7 +157,17 @@ html,body,.gradio-container{background:linear-gradient(180deg,#fffaf7 0%,#fff 10
|
|
| 153 |
}
|
| 154 |
.querybox,.querybox>div{background:#fff!important;border:1.5px solid rgba(255,107,53,.28)!important;border-radius:20px!important;box-shadow:0 6px 22px rgba(255,107,53,.08)!important}.querybox textarea{color:#000!important;background:#fff!important}.querybox:focus-within,.querybox>div:focus-within{border-color:#ff6b35!important;box-shadow:0 0 0 4px rgba(255,107,53,.10),0 8px 28px rgba(255,107,53,.10)!important}
|
| 155 |
.chat-panel{padding:14px;display:flex;flex-direction:column;gap:10px;min-height:240px;max-height:300px;overflow:auto}.bubble{max-width:86%;padding:14px 16px;border:1px solid var(--line);border-radius:20px}.bubble .role{font-size:.72rem;text-transform:uppercase;letter-spacing:.14em;color:var(--muted)}.bubble p{margin:6px 0 0;line-height:1.55;color:var(--text)}.bubble.user{margin-left:auto;background:var(--orange-pale);border-color:rgba(255,107,53,.22)}.bubble.ai{background:#fff}.bubble.system{background:var(--orange-pale);border-color:rgba(255,107,53,.22)}
|
| 156 |
-
.brain-shell{padding:14px}.brain-head{display:flex;justify-content:space-between;gap:16px;align-items:flex-end;margin-bottom:10px}.eyebrow{margin:0 0 4px;font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--orange)}.brain-head h3{margin:0;font-size:1.02rem;color:var(--text)}.brain-help{color:var(--muted);font-size:.8rem}#dvnc-three-root{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
.working-orb{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:80px;height:80px;border-radius:50%;background:radial-gradient(circle at 30% 30%,rgba(255,143,102,.9),var(--orange));box-shadow:0 8px 32px rgba(255,107,53,.4),inset 0 -4px 12px rgba(0,0,0,.15);animation:orbPulse 2.5s ease-in-out infinite,orbFloat 4s ease-in-out infinite}
|
| 158 |
@keyframes orbPulse{0%,100%{box-shadow:0 8px 32px rgba(255,107,53,.4),inset 0 -4px 12px rgba(0,0,0,.15)}50%{box-shadow:0 12px 48px rgba(255,107,53,.7),inset 0 -4px 12px rgba(0,0,0,.2)}}
|
| 159 |
@keyframes orbFloat{0%,100%{transform:translate(-50%,-50%) translateY(0)}50%{transform:translate(-50%,-50%) translateY(-12px)}}
|
|
@@ -181,68 +195,156 @@ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
| 181 |
|
| 182 |
function initDVNC(){
|
| 183 |
const root = document.getElementById('dvnc-three-root');
|
| 184 |
-
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
root.dataset.ready = '1';
|
|
|
|
| 187 |
const scene = new THREE.Scene();
|
| 188 |
-
const camera = new THREE.PerspectiveCamera(
|
| 189 |
-
camera.position.set(0, 0,
|
|
|
|
| 190 |
const renderer = new THREE.WebGLRenderer({ antialias:true, alpha:true });
|
| 191 |
renderer.setSize(root.clientWidth, root.clientHeight);
|
| 192 |
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
| 193 |
-
|
| 194 |
root.appendChild(renderer.domElement);
|
| 195 |
|
| 196 |
const controls = new OrbitControls(camera, renderer.domElement);
|
| 197 |
controls.enableDamping = true;
|
| 198 |
-
controls.autoRotate = true;
|
| 199 |
-
controls.autoRotateSpeed = .45;
|
| 200 |
controls.enablePan = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 201 |
|
| 202 |
-
const ambient = new THREE.AmbientLight(0xffffff, .7); scene.add(ambient);
|
| 203 |
-
const key = new THREE.PointLight(0xff6b35, 2.5, 260); key.position.set(30, 40, 50); scene.add(key);
|
| 204 |
-
const fill = new THREE.PointLight(0xff8f66, 2.0, 240); fill.position.set(-40, -20, 40); scene.add(fill);
|
| 205 |
-
|
| 206 |
-
const nodeMeshes = {};
|
| 207 |
const active = new Set(graph.active_path || []);
|
| 208 |
-
const
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
|
| 213 |
for(const n of graph.nodes || []){
|
| 214 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
const mesh = new THREE.Mesh(nodeGeom, mat);
|
| 216 |
-
mesh.position.set(n.x, n.y, n.z);
|
| 217 |
scene.add(mesh);
|
| 218 |
nodeMeshes[n.id] = mesh;
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
}
|
| 226 |
|
| 227 |
function edgeActive(a,b){
|
| 228 |
const path = graph.active_path || [];
|
| 229 |
const ia = path.indexOf(a), ib = path.indexOf(b);
|
| 230 |
-
return ia >= 0 && ib >= 0 && Math.abs(ia-ib) === 1;
|
| 231 |
}
|
| 232 |
|
| 233 |
for(const e of graph.edges || []){
|
| 234 |
const [a,b] = e;
|
| 235 |
if(!nodeMeshes[a] || !nodeMeshes[b]) continue;
|
|
|
|
| 236 |
const pts = [nodeMeshes[a].position, nodeMeshes[b].position];
|
| 237 |
const geo = new THREE.BufferGeometry().setFromPoints(pts);
|
| 238 |
-
const
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
scene.add(line);
|
| 241 |
}
|
| 242 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
const stars = new THREE.Points(
|
| 244 |
-
new THREE.BufferGeometry().setAttribute(
|
| 245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
);
|
| 247 |
scene.add(stars);
|
| 248 |
|
|
@@ -250,24 +352,29 @@ function initDVNC(){
|
|
| 250 |
function animate(){
|
| 251 |
requestAnimationFrame(animate);
|
| 252 |
const t = clock.getElapsedTime();
|
| 253 |
-
|
| 254 |
-
|
|
|
|
|
|
|
| 255 |
if(m.userData.halo){
|
| 256 |
-
const
|
| 257 |
-
m.userData.halo.scale.setScalar(
|
| 258 |
}
|
| 259 |
});
|
|
|
|
|
|
|
| 260 |
controls.update();
|
| 261 |
-
renderer.render(scene,camera);
|
| 262 |
}
|
| 263 |
animate();
|
| 264 |
|
| 265 |
-
const resize = ()=>{
|
| 266 |
if(!root.clientWidth || !root.clientHeight) return;
|
| 267 |
camera.aspect = root.clientWidth / root.clientHeight;
|
| 268 |
camera.updateProjectionMatrix();
|
| 269 |
renderer.setSize(root.clientWidth, root.clientHeight);
|
| 270 |
};
|
|
|
|
| 271 |
window.addEventListener('resize', resize, { passive:true });
|
| 272 |
}
|
| 273 |
|
|
|
|
| 69 |
|
| 70 |
|
| 71 |
def build_frontend_payload(data):
|
| 72 |
+
graph = data.get("graph") or {}
|
| 73 |
+
graph.setdefault("nodes", [])
|
| 74 |
+
graph.setdefault("edges", [])
|
| 75 |
+
graph.setdefault("active_path", [])
|
| 76 |
return f"""
|
| 77 |
<script>
|
| 78 |
+
window.__DVNC_GRAPH__ = {json.dumps(graph)};
|
| 79 |
</script>
|
| 80 |
{CONNECTOME_SNIPPET}
|
| 81 |
"""
|
|
|
|
| 157 |
}
|
| 158 |
.querybox,.querybox>div{background:#fff!important;border:1.5px solid rgba(255,107,53,.28)!important;border-radius:20px!important;box-shadow:0 6px 22px rgba(255,107,53,.08)!important}.querybox textarea{color:#000!important;background:#fff!important}.querybox:focus-within,.querybox>div:focus-within{border-color:#ff6b35!important;box-shadow:0 0 0 4px rgba(255,107,53,.10),0 8px 28px rgba(255,107,53,.10)!important}
|
| 159 |
.chat-panel{padding:14px;display:flex;flex-direction:column;gap:10px;min-height:240px;max-height:300px;overflow:auto}.bubble{max-width:86%;padding:14px 16px;border:1px solid var(--line);border-radius:20px}.bubble .role{font-size:.72rem;text-transform:uppercase;letter-spacing:.14em;color:var(--muted)}.bubble p{margin:6px 0 0;line-height:1.55;color:var(--text)}.bubble.user{margin-left:auto;background:var(--orange-pale);border-color:rgba(255,107,53,.22)}.bubble.ai{background:#fff}.bubble.system{background:var(--orange-pale);border-color:rgba(255,107,53,.22)}
|
| 160 |
+
.brain-shell{padding:14px}.brain-head{display:flex;justify-content:space-between;gap:16px;align-items:flex-end;margin-bottom:10px}.eyebrow{margin:0 0 4px;font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:var(--orange)}.brain-head h3{margin:0;font-size:1.02rem;color:var(--text)}.brain-help{color:var(--muted);font-size:.8rem}#dvnc-three-root{
|
| 161 |
+
height:340px;
|
| 162 |
+
border-radius:20px;
|
| 163 |
+
border:1px solid var(--line);
|
| 164 |
+
overflow:hidden;
|
| 165 |
+
background:
|
| 166 |
+
radial-gradient(circle at 50% 45%, rgba(255,107,53,.10), rgba(255,107,53,0) 34%),
|
| 167 |
+
linear-gradient(180deg,#fff8f5 0%, #fff 100%);
|
| 168 |
+
position:relative;
|
| 169 |
+
display:block;
|
| 170 |
+
}
|
| 171 |
.working-orb{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:80px;height:80px;border-radius:50%;background:radial-gradient(circle at 30% 30%,rgba(255,143,102,.9),var(--orange));box-shadow:0 8px 32px rgba(255,107,53,.4),inset 0 -4px 12px rgba(0,0,0,.15);animation:orbPulse 2.5s ease-in-out infinite,orbFloat 4s ease-in-out infinite}
|
| 172 |
@keyframes orbPulse{0%,100%{box-shadow:0 8px 32px rgba(255,107,53,.4),inset 0 -4px 12px rgba(0,0,0,.15)}50%{box-shadow:0 12px 48px rgba(255,107,53,.7),inset 0 -4px 12px rgba(0,0,0,.2)}}
|
| 173 |
@keyframes orbFloat{0%,100%{transform:translate(-50%,-50%) translateY(0)}50%{transform:translate(-50%,-50%) translateY(-12px)}}
|
|
|
|
| 195 |
|
| 196 |
function initDVNC(){
|
| 197 |
const root = document.getElementById('dvnc-three-root');
|
| 198 |
+
if(!root || root.clientWidth === 0 || root.clientHeight === 0) return;
|
| 199 |
+
|
| 200 |
+
let graph = window.__DVNC_GRAPH__ || {};
|
| 201 |
+
const hasRealGraph = Array.isArray(graph.nodes) && graph.nodes.length > 0;
|
| 202 |
+
|
| 203 |
+
if(!hasRealGraph){
|
| 204 |
+
graph = {
|
| 205 |
+
nodes: [
|
| 206 |
+
{id:"query", group:"core", x:0, y:0, z:0},
|
| 207 |
+
{id:"mechanics", group:"domain", x:-26, y:16, z:-8},
|
| 208 |
+
{id:"conductivity", group:"bridge", x:26, y:12, z:10},
|
| 209 |
+
{id:"immune", group:"mechanism", x:-18, y:-18, z:14},
|
| 210 |
+
{id:"repair", group:"outcome", x:24, y:-16, z:-12},
|
| 211 |
+
{id:"candidate", group:"candidate", x:0, y:26, z:18}
|
| 212 |
+
],
|
| 213 |
+
edges: [
|
| 214 |
+
["query","mechanics"],
|
| 215 |
+
["query","conductivity"],
|
| 216 |
+
["query","immune"],
|
| 217 |
+
["mechanics","candidate"],
|
| 218 |
+
["conductivity","candidate"],
|
| 219 |
+
["immune","repair"],
|
| 220 |
+
["candidate","repair"]
|
| 221 |
+
],
|
| 222 |
+
active_path: ["query","conductivity","candidate","repair"]
|
| 223 |
+
};
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
root.innerHTML = '';
|
| 227 |
root.dataset.ready = '1';
|
| 228 |
+
|
| 229 |
const scene = new THREE.Scene();
|
| 230 |
+
const camera = new THREE.PerspectiveCamera(54, root.clientWidth / root.clientHeight, 0.1, 1000);
|
| 231 |
+
camera.position.set(0, 0, 115);
|
| 232 |
+
|
| 233 |
const renderer = new THREE.WebGLRenderer({ antialias:true, alpha:true });
|
| 234 |
renderer.setSize(root.clientWidth, root.clientHeight);
|
| 235 |
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
| 236 |
+
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
| 237 |
root.appendChild(renderer.domElement);
|
| 238 |
|
| 239 |
const controls = new OrbitControls(camera, renderer.domElement);
|
| 240 |
controls.enableDamping = true;
|
|
|
|
|
|
|
| 241 |
controls.enablePan = false;
|
| 242 |
+
controls.autoRotate = true;
|
| 243 |
+
controls.autoRotateSpeed = 0.55;
|
| 244 |
+
|
| 245 |
+
scene.add(new THREE.AmbientLight(0xffffff, 1.15));
|
| 246 |
+
|
| 247 |
+
const key = new THREE.PointLight(0xff6b35, 4.2, 320);
|
| 248 |
+
key.position.set(38, 42, 60);
|
| 249 |
+
scene.add(key);
|
| 250 |
+
|
| 251 |
+
const fill = new THREE.PointLight(0xffb089, 2.4, 280);
|
| 252 |
+
fill.position.set(-45, -18, 42);
|
| 253 |
+
scene.add(fill);
|
| 254 |
+
|
| 255 |
+
const rim = new THREE.PointLight(0xffffff, 1.4, 260);
|
| 256 |
+
rim.position.set(0, 0, 90);
|
| 257 |
+
scene.add(rim);
|
| 258 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
const active = new Set(graph.active_path || []);
|
| 260 |
+
const nodeMeshes = {};
|
| 261 |
+
const palette = {
|
| 262 |
+
core: 0xff6b35,
|
| 263 |
+
domain: 0xff955f,
|
| 264 |
+
bridge: 0xff8a4c,
|
| 265 |
+
mechanism: 0xffb38f,
|
| 266 |
+
outcome: 0xffc7b3,
|
| 267 |
+
candidate: 0xff7b47
|
| 268 |
+
};
|
| 269 |
+
|
| 270 |
+
const nodeGeom = new THREE.SphereGeometry(3.2, 28, 28);
|
| 271 |
+
const haloGeom = new THREE.SphereGeometry(5.8, 28, 28);
|
| 272 |
|
| 273 |
for(const n of graph.nodes || []){
|
| 274 |
+
const isActive = active.has(n.id);
|
| 275 |
+
const color = palette[n.group] || 0xd38d73;
|
| 276 |
+
|
| 277 |
+
const mat = new THREE.MeshStandardMaterial({
|
| 278 |
+
color,
|
| 279 |
+
emissive: isActive ? 0xff6b35 : color,
|
| 280 |
+
emissiveIntensity: isActive ? 1.9 : 0.28,
|
| 281 |
+
roughness: 0.22,
|
| 282 |
+
metalness: 0.1
|
| 283 |
+
});
|
| 284 |
+
|
| 285 |
const mesh = new THREE.Mesh(nodeGeom, mat);
|
| 286 |
+
mesh.position.set(n.x || 0, n.y || 0, n.z || 0);
|
| 287 |
scene.add(mesh);
|
| 288 |
nodeMeshes[n.id] = mesh;
|
| 289 |
+
|
| 290 |
+
const halo = new THREE.Mesh(
|
| 291 |
+
haloGeom,
|
| 292 |
+
new THREE.MeshBasicMaterial({
|
| 293 |
+
color: isActive ? 0xff6b35 : color,
|
| 294 |
+
transparent: true,
|
| 295 |
+
opacity: isActive ? 0.14 : 0.05
|
| 296 |
+
})
|
| 297 |
+
);
|
| 298 |
+
halo.position.copy(mesh.position);
|
| 299 |
+
scene.add(halo);
|
| 300 |
+
mesh.userData.halo = halo;
|
| 301 |
}
|
| 302 |
|
| 303 |
function edgeActive(a,b){
|
| 304 |
const path = graph.active_path || [];
|
| 305 |
const ia = path.indexOf(a), ib = path.indexOf(b);
|
| 306 |
+
return ia >= 0 && ib >= 0 && Math.abs(ia - ib) === 1;
|
| 307 |
}
|
| 308 |
|
| 309 |
for(const e of graph.edges || []){
|
| 310 |
const [a,b] = e;
|
| 311 |
if(!nodeMeshes[a] || !nodeMeshes[b]) continue;
|
| 312 |
+
|
| 313 |
const pts = [nodeMeshes[a].position, nodeMeshes[b].position];
|
| 314 |
const geo = new THREE.BufferGeometry().setFromPoints(pts);
|
| 315 |
+
const isActive = edgeActive(a,b);
|
| 316 |
+
|
| 317 |
+
const line = new THREE.Line(
|
| 318 |
+
geo,
|
| 319 |
+
new THREE.LineBasicMaterial({
|
| 320 |
+
color: isActive ? 0xff6b35 : 0xd9c4bb,
|
| 321 |
+
transparent: true,
|
| 322 |
+
opacity: isActive ? 1.0 : 0.72
|
| 323 |
+
})
|
| 324 |
+
);
|
| 325 |
+
|
| 326 |
+
line.userData.active = isActive;
|
| 327 |
scene.add(line);
|
| 328 |
}
|
| 329 |
|
| 330 |
+
const starPositions = [];
|
| 331 |
+
for(let i = 0; i < 900; i++){
|
| 332 |
+
starPositions.push((Math.random() - 0.5) * 220);
|
| 333 |
+
starPositions.push((Math.random() - 0.5) * 220);
|
| 334 |
+
starPositions.push((Math.random() - 0.5) * 220);
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
const stars = new THREE.Points(
|
| 338 |
+
new THREE.BufferGeometry().setAttribute(
|
| 339 |
+
'position',
|
| 340 |
+
new THREE.Float32BufferAttribute(starPositions, 3)
|
| 341 |
+
),
|
| 342 |
+
new THREE.PointsMaterial({
|
| 343 |
+
color: 0xf1b6a1,
|
| 344 |
+
size: 0.85,
|
| 345 |
+
transparent: true,
|
| 346 |
+
opacity: 0.55
|
| 347 |
+
})
|
| 348 |
);
|
| 349 |
scene.add(stars);
|
| 350 |
|
|
|
|
| 352 |
function animate(){
|
| 353 |
requestAnimationFrame(animate);
|
| 354 |
const t = clock.getElapsedTime();
|
| 355 |
+
|
| 356 |
+
Object.values(nodeMeshes).forEach((m, i) => {
|
| 357 |
+
const pulse = 1 + Math.sin(t * 1.8 + i) * 0.06;
|
| 358 |
+
m.scale.setScalar(pulse);
|
| 359 |
if(m.userData.halo){
|
| 360 |
+
const hs = 1 + (Math.sin(t * 2.3 + i) + 1) * 0.08;
|
| 361 |
+
m.userData.halo.scale.setScalar(hs);
|
| 362 |
}
|
| 363 |
});
|
| 364 |
+
|
| 365 |
+
stars.rotation.y += 0.0008;
|
| 366 |
controls.update();
|
| 367 |
+
renderer.render(scene, camera);
|
| 368 |
}
|
| 369 |
animate();
|
| 370 |
|
| 371 |
+
const resize = () => {
|
| 372 |
if(!root.clientWidth || !root.clientHeight) return;
|
| 373 |
camera.aspect = root.clientWidth / root.clientHeight;
|
| 374 |
camera.updateProjectionMatrix();
|
| 375 |
renderer.setSize(root.clientWidth, root.clientHeight);
|
| 376 |
};
|
| 377 |
+
|
| 378 |
window.addEventListener('resize', resize, { passive:true });
|
| 379 |
}
|
| 380 |
|