From 25a8af8d4e16d16cd688b843a7fade808639a3c0 Mon Sep 17 00:00:00 2001 From: drjones Date: Thu, 13 Aug 2026 06:46:03 -0700 Subject: [PATCH] Revamp Web UI: Added Tailwind CSS CDN, cyberpunk glassmorphism layout, glowing neon visualizers, and enhanced telemetry gauges --- public/css/style.css | 153 ++++++++----- public/index.html | 496 +++++++++++++++++++++++------------------- public/js/pipeline.js | 93 +++++--- 3 files changed, 420 insertions(+), 322 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index 1090b71..3becdc7 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1,89 +1,104 @@ -/* Cyberpunk Glassmorphism Design Token System */ -@tailwind base; -@tailwind components; -@tailwind utilities; +/* Cyberpunk Design System & Styling Rules */ -:root { - --bg-dark: #07090E; - --panel-bg: rgba(15, 23, 42, 0.75); - --cyan-glow: #00F0FF; - --violet-glow: #8A2BE2; - --emerald-glow: #00FF9D; - --amber-glow: #FFB800; - --rose-glow: #FF3366; -} - -body { - background-color: var(--bg-dark); - background-image: - radial-gradient(at 0% 0%, rgba(0, 240, 255, 0.08) 0px, transparent 50%), - radial-gradient(at 100% 0%, rgba(138, 43, 226, 0.08) 0px, transparent 50%), - radial-gradient(at 50% 100%, rgba(0, 255, 157, 0.04) 0px, transparent 50%); - font-family: 'Inter', sans-serif; - color: #F8FAFC; -} - -/* Glassmorphism Panel Component */ -.glass-panel { - background: rgba(15, 23, 42, 0.7); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); +/* Cyber Card Glassmorphism */ +.cyber-card { + background: rgba(13, 18, 30, 0.85); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.08); - box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); + box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5); + transition: all 0.3s ease; } -.glass-panel:hover { - border-color: rgba(0, 240, 255, 0.2); +.cyber-card:hover { + border-color: rgba(0, 240, 255, 0.25); + box-shadow: 0 15px 35px -10px rgba(0, 240, 255, 0.15); } -/* Buttons */ -.btn { - @apply px-4 py-2 rounded-xl text-xs font-bold font-mono tracking-wider transition-all duration-200 flex items-center gap-2 cursor-pointer border shadow-lg; +/* Neon Buttons */ +.btn-neon { + padding: 0.5rem 1rem; + border-radius: 0.75rem; + font-size: 0.75rem; + font-weight: 800; + font-family: 'Fira Code', monospace; + letter-spacing: 0.05em; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + display: inline-flex; + items-center: center; + gap: 0.5rem; + cursor: pointer; + border: 1px solid transparent; + user-select: none; } .btn-emerald { background: linear-gradient(135deg, rgba(0, 255, 157, 0.2), rgba(0, 200, 120, 0.1)); border-color: rgba(0, 255, 157, 0.4); color: #00FF9D; + box-shadow: 0 0 15px rgba(0, 255, 157, 0.15); } -.btn-emerald:hover { +.btn-emerald:hover:not(:disabled) { background: rgba(0, 255, 157, 0.3); - box-shadow: 0 0 20px rgba(0, 255, 157, 0.4); + box-shadow: 0 0 25px rgba(0, 255, 157, 0.5); + transform: translateY(-1px); } .btn-rose { background: linear-gradient(135deg, rgba(255, 51, 102, 0.2), rgba(200, 40, 80, 0.1)); border-color: rgba(255, 51, 102, 0.4); color: #FF3366; + box-shadow: 0 0 15px rgba(255, 51, 102, 0.15); } -.btn-rose:hover { +.btn-rose:hover:not(:disabled) { background: rgba(255, 51, 102, 0.3); - box-shadow: 0 0 20px rgba(255, 51, 102, 0.4); + box-shadow: 0 0 25px rgba(255, 51, 102, 0.5); + transform: translateY(-1px); } .btn-ghost { - background: rgba(30, 41, 59, 0.6); + background: rgba(30, 41, 59, 0.7); border-color: rgba(255, 255, 255, 0.1); color: #94A3B8; } -.btn-ghost:hover { - background: rgba(51, 65, 85, 0.8); - color: #FFF; +.btn-ghost:hover:not(:disabled) { + background: rgba(51, 65, 85, 0.9); + color: #FFFFFF; + border-color: rgba(0, 240, 255, 0.3); } .btn-purple { background: linear-gradient(135deg, rgba(138, 43, 226, 0.25), rgba(100, 30, 180, 0.15)); border-color: rgba(138, 43, 226, 0.5); color: #C084FC; + box-shadow: 0 0 15px rgba(138, 43, 226, 0.15); } -.btn-purple:hover { +.btn-purple:hover:not(:disabled) { background: rgba(138, 43, 226, 0.35); - box-shadow: 0 0 20px rgba(138, 43, 226, 0.4); + box-shadow: 0 0 25px rgba(138, 43, 226, 0.5); + transform: translateY(-1px); +} + +.btn-neon:disabled { + opacity: 0.4; + cursor: not-allowed; + transform: none !important; + box-shadow: none !important; } /* Status Badges */ .status-badge { - @apply px-3 py-1 rounded-full text-[11px] font-bold font-mono tracking-widest border uppercase inline-flex items-center gap-1.5; + padding: 0.25rem 0.75rem; + border-radius: 9999px; + font-size: 0.6875rem; + font-weight: 800; + font-family: 'Fira Code', monospace; + letter-spacing: 0.05em; + border: 1px solid transparent; + display: inline-flex; + align-items: center; + gap: 0.375rem; + text-transform: uppercase; } .status-idle { @@ -96,12 +111,13 @@ body { background: rgba(0, 240, 255, 0.15); border-color: rgba(0, 240, 255, 0.4); color: #00F0FF; - animation: pulse-glow 2s infinite; + box-shadow: 0 0 15px rgba(0, 240, 255, 0.3); + animation: badge-pulse 2s infinite; } -@keyframes pulse-glow { - 0%, 100% { box-shadow: 0 0 10px rgba(0, 240, 255, 0.3); } - 50% { box-shadow: 0 0 25px rgba(0, 240, 255, 0.7); } +@keyframes badge-pulse { + 0%, 100% { box-shadow: 0 0 10px rgba(0, 240, 255, 0.2); } + 50% { box-shadow: 0 0 25px rgba(0, 240, 255, 0.6); } } @keyframes spin-reverse { @@ -112,25 +128,35 @@ body { animation: spin-reverse 3s linear infinite; } -/* Scrollbar Customization */ +/* Custom Scrollbar */ .custom-scrollbar::-webkit-scrollbar { width: 6px; height: 6px; } .custom-scrollbar::-webkit-scrollbar-track { - background: rgba(15, 23, 42, 0.6); + background: rgba(7, 9, 14, 0.8); } .custom-scrollbar::-webkit-scrollbar-thumb { background: rgba(51, 65, 85, 0.8); - border-radius: 3px; + border-radius: 4px; } .custom-scrollbar::-webkit-scrollbar-thumb:hover { - background: rgba(0, 240, 255, 0.5); + background: rgba(0, 240, 255, 0.6); } -/* Terminal Log Badges */ +/* Terminal Log Stream Elements */ .log-line { - @apply font-mono text-xs flex items-start gap-2 py-0.5 border-b border-slate-900/40 hover:bg-slate-900/50 px-1 rounded transition; + font-family: 'Fira Code', monospace; + font-size: 0.75rem; + display: flex; + align-items: flex-start; + gap: 0.5rem; + padding: 0.25rem 0.5rem; + border-radius: 0.375rem; + transition: background 0.15s ease; +} +.log-line:hover { + background: rgba(30, 41, 59, 0.4); } .log-timestamp { color: #64748B; @@ -143,8 +169,19 @@ body { .badge-error { background: rgba(255, 51, 102, 0.15); color: #FF3366; border: 1px solid rgba(255, 51, 102, 0.3); } .log-filter-btn { - @apply px-2 py-0.5 rounded text-[10px] font-bold text-slate-400 hover:text-white transition; + padding: 0.2rem 0.5rem; + border-radius: 0.375rem; + font-size: 0.625rem; + font-weight: 700; + font-family: 'Fira Code', monospace; + color: #94A3B8; + transition: all 0.15s ease; +} +.log-filter-btn:hover { + color: #FFFFFF; } .log-filter-btn.active { - @apply bg-cyan-500/20 text-cyan-400 border border-cyan-500/40; + background: rgba(0, 240, 255, 0.2); + color: #00F0FF; + border: 1px solid rgba(0, 240, 255, 0.4); } diff --git a/public/index.html b/public/index.html index 722cb9c..1350c0a 100644 --- a/public/index.html +++ b/public/index.html @@ -1,300 +1,338 @@ - + AI-Trainer | Unsloth MoE & GRPO Control Center - - + + - + + + + + + + + - + - -
+ +
-
-
+
+
+
-

Initializing Neural Environment...

-

Loading Unsloth Triton Kernels & MoE Router Maps

+

INITIALIZING NEURAL HARNESS...

+

Loading Unsloth Triton Kernels & MoE Layer Router Maps

- -
- - -
-
-
-
- -
+ +
+ +
+
+
+
+
+
+
+
+

AI-TRAINER

+ UNSLOTH GRPO MOE +
+

Proxify-ADB Autonomous Fleet Router & MoE Weight Shedder

+
+
+ + +
+
+
+ GPU VRAM: + 6.2 / 16.0 GB +
+
+
+
+ MoE Stream RAM: + 34.5 / 64.0 GB +
+
+
+
+ ADB Fleet: + 14 / 14 Connected +
+
+ + +
+ + + + +
+
+ + +
+ + +
+
-
-

AI-TRAINER

- UNSLOTH GRPO MOE +

+ + AUTONOMOUS UN SLOTH GRPO PIPELINE MAP +

+

Real-time dynamic expert pruning, hard execution sandbox evaluation, and GGUF quant deployment

+
+
+ STATUS: IDLE +
+ Overall Progress: + 0%
-

Proxify-ADB Fleet Orchestrator & MoE Pruner

- -
-
- - VRAM: - 6.2 / 16.0 GB -
-
-
- - RAM: - 34.5 / 64.0 GB -
-
-
- - ADB Fleet: - 14 / 14 Online -
+ +
+
+
- -
- - - - -
-
+ +
- -
+ +
- -
-
-
-

- - AUTONOMOUS FINE-TUNING PIPELINE VISUALIZER -

-

Interactive execution path with dynamic layer pruning & execution rewards

-
-
- STATUS: IDLE - Progress: 0% -
-
- - -
- -
-
- - -
- - -
- - -
-
+ +
+
+

UNSLOTH GRPO HARD EXECUTION REWARD CONVERGENCE

- - Step 0 / 300 - -
-
- +

Multi-vector reward curve ($R_{exec} = +3.0$, $R_{anti-hesit} = +2.0$, Safety = $-10.0$)

+ + Step 0 / 300 +
+
+ +
+
- -
-
+ +
+
+

DOMAIN MoE EXPERT RETENTION VS PRUNED TRIVIA EXPERTS

- - Retained: 64 / 256 - -
-
- +

Dropping ~68.75% dormant botany/history experts across 61 layers

+ + Retained: 64 / 256 + +
+
+
-
- -
+
- -
-

+ +
+ + +
+
+

10.30.20.0/24 PROXMOX FLEET TOPOLOGY

+ vmbr1 Isolated +
-
-
- Control Gateway - 10.30.20.1 -
vmbr1 (Isolated Bridge)
-
-
- DHCP Pool - .100 - .254 -
dnsmasq 12h Leases
-
+
+
+ Gateway Control Node + 10.30.20.1 +
Port 5555 / REST API
- - -
- +
+ Dynamic DHCP Pool + .100 ──► .254 +
dnsmasq 12h Leases
- -
-
-

- - PIPELINE SCRIPT INSPECTOR -

- -
-
# Loading script content...
+ +
+
- -
-
- -

- - -
- - -
-
- - - LIVE LOG STREAM - - 0 Logs
- -
-
- Filter: - - - - - + +
+
+

+ + PIPELINE SCRIPT INSPECTOR +

+
- - - +
# Select a script to view source code...
-
- -
-
- -
-
-
-

- TUNING KNOBS & REWARD WEIGHTS -

- + + + +
+ + +
+
+ + + LIVE LOG STREAM CONSOLE + + 0 Logs +
+ + +
+
+ LEVEL: + + + + +
-
-
- - -
- -
- - -
- -
- - -
- -
- -
-
- -
- -
+ +
+ +
+ +
+
+ + +
+
+
+

+ TUNING KNOBS & REWARD WEIGHTS +

+ +
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ Hardware Memory Target: + 16.0 GB VRAM + 64.0 GB System RAM Streaming +
+
+ +
+ +
+
diff --git a/public/js/pipeline.js b/public/js/pipeline.js index be5b027..4e8a507 100644 --- a/public/js/pipeline.js +++ b/public/js/pipeline.js @@ -1,20 +1,22 @@ /** - * pipeline.js - Interactive Canvas Pipeline Visualizer - * Renders nodes, dynamic connections, glowing particle pulses, and interactive states. + * pipeline.js - Interactive HTML5 Canvas Pipeline Visualizer + * Renders glowing neon nodes, animated pulse particles, laser beams, and stage cards. */ class PipelineVisualizer { constructor(canvasId) { this.canvas = document.getElementById(canvasId); this.ctx = this.canvas.getContext('2d'); + this.nodes = [ - { id: 'harvester', name: '1. Config Harvester', icon: '⚡', x: 0.12, y: 0.5, status: 'idle', desc: 'Scrapes /etc/dnsmasq.d & ADB nodes' }, - { id: 'pruner', name: '2. MoE Expert Pruner', icon: '✂️', x: 0.28, y: 0.5, status: 'idle', desc: 'Drops 70% dormant trivia experts (256->64)' }, - { id: 'harness', name: '3. Execution Gym', icon: '🛡️', x: 0.44, y: 0.5, status: 'idle', desc: 'Command safety sandbox & STDERR check' }, - { id: 'grpo', name: '4. Unsloth GRPO', icon: '🧠', x: 0.60, y: 0.5, status: 'idle', desc: 'Hard execution & anti-hesitation rewards' }, - { id: 'export', name: '5. GGUF Quantizer', icon: '📦', x: 0.76, y: 0.5, status: 'idle', desc: 'Dual-offload Q4_K_M GGUF packaging' }, - { id: 'telemetry', name: '6. State Eye Daemon', icon: '👁️', x: 0.90, y: 0.5, status: 'idle', desc: '10.30.20.1 live state context injector' } + { id: 'harvester', name: '1. Config Harvester', icon: '⚡', x: 0.10, y: 0.5, status: 'idle', color: '#00F0FF', desc: 'Scrapes /etc/dnsmasq.d & ADB nodes' }, + { id: 'pruner', name: '2. MoE Expert Pruner', icon: '✂️', x: 0.26, y: 0.5, status: 'idle', color: '#FFB800', desc: 'Drops 70% dormant trivia experts (256->64)' }, + { id: 'harness', name: '3. Execution Gym', icon: '🛡️', x: 0.42, y: 0.5, status: 'idle', color: '#8A2BE2', desc: 'Command safety sandbox & STDERR check' }, + { id: 'grpo', name: '4. Unsloth GRPO', icon: '🧠', x: 0.58, y: 0.5, status: 'idle', color: '#00FF9D', desc: 'Hard execution & anti-hesitation rewards' }, + { id: 'export', name: '5. GGUF Quantizer', icon: '📦', x: 0.74, y: 0.5, status: 'idle', color: '#C084FC', desc: 'Dual-offload Q4_K_M GGUF packaging' }, + { id: 'telemetry', name: '6. State Eye Daemon', icon: '👁️', x: 0.90, y: 0.5, status: 'idle', color: '#00F0FF', desc: '10.30.20.1 live state context injector' } ]; + this.particles = []; this.activeStage = null; this.animId = null; @@ -27,17 +29,20 @@ class PipelineVisualizer { resize() { const parent = this.canvas.parentElement; - this.canvas.width = parent.clientWidth; - this.canvas.height = parent.clientHeight; + if (parent) { + this.canvas.width = parent.clientWidth; + this.canvas.height = parent.clientHeight; + } } initParticles() { this.particles = []; - for (let i = 0; i < 20; i++) { + for (let i = 0; i < 25; i++) { this.particles.push({ progress: Math.random(), speed: 0.003 + Math.random() * 0.004, - size: 3 + Math.random() * 2 + size: 3 + Math.random() * 2, + alpha: 0.5 + Math.random() * 0.5 }); } } @@ -74,7 +79,7 @@ class PipelineVisualizer { const h = this.canvas.height; this.ctx.clearRect(0, 0, w, h); - // 1. Draw Connecting Lines + // 1. Draw Connecting Laser Beams for (let i = 0; i < this.nodes.length - 1; i++) { const n1 = this.nodes[i]; const n2 = this.nodes[i + 1]; @@ -85,17 +90,31 @@ class PipelineVisualizer { const isPassed = this.activeStage && this.getStageIndex(n1.id) <= this.getStageIndex(this.activeStage); + // Base Beam this.ctx.beginPath(); this.ctx.moveTo(x1, y1); this.ctx.lineTo(x2, y2); - this.ctx.strokeStyle = isPassed ? 'rgba(0, 240, 255, 0.6)' : 'rgba(51, 65, 85, 0.5)'; - this.ctx.lineWidth = isPassed ? 3 : 2; - this.ctx.setLineDash(isPassed ? [] : [5, 5]); + this.ctx.strokeStyle = isPassed ? 'rgba(0, 240, 255, 0.4)' : 'rgba(30, 41, 59, 0.6)'; + this.ctx.lineWidth = isPassed ? 4 : 2; + if (!isPassed) this.ctx.setLineDash([6, 6]); this.ctx.stroke(); this.ctx.setLineDash([]); + + // Neon Glow Line + if (isPassed) { + this.ctx.beginPath(); + this.ctx.moveTo(x1, y1); + this.ctx.lineTo(x2, y2); + this.ctx.strokeStyle = 'rgba(0, 240, 255, 0.8)'; + this.ctx.lineWidth = 2; + this.ctx.shadowColor = '#00F0FF'; + this.ctx.shadowBlur = 15; + this.ctx.stroke(); + this.ctx.shadowBlur = 0; + } } - // 2. Draw Moving Data Particles + // 2. Draw Animated Particles on Active Segment if (this.activeStage) { this.particles.forEach(p => { p.progress += p.speed; @@ -114,40 +133,44 @@ class PipelineVisualizer { this.ctx.beginPath(); this.ctx.arc(px, py, p.size, 0, Math.PI * 2); - this.ctx.fillStyle = '#00F0FF'; - this.ctx.shadowColor = '#00F0FF'; - this.ctx.shadowBlur = 10; + this.ctx.fillStyle = '#00FF9D'; + this.ctx.shadowColor = '#00FF9D'; + this.ctx.shadowBlur = 12; this.ctx.fill(); this.ctx.shadowBlur = 0; } }); } - // 3. Draw Nodes + // 3. Draw Nodes & Cards this.nodes.forEach(node => { const nx = node.x * w; const ny = node.y * h; - // Glow effect for active/completed nodes + // Pulsing outer aura ring for active node if (node.status === 'running') { + const pulse = 34 + Math.sin(Date.now() * 0.006) * 6; this.ctx.beginPath(); - this.ctx.arc(nx, ny, 32, 0, Math.PI * 2); + this.ctx.arc(nx, ny, pulse, 0, Math.PI * 2); this.ctx.fillStyle = 'rgba(0, 240, 255, 0.15)'; + this.ctx.strokeStyle = 'rgba(0, 240, 255, 0.6)'; + this.ctx.lineWidth = 2; this.ctx.shadowColor = '#00F0FF'; - this.ctx.shadowBlur = 20; + this.ctx.shadowBlur = 25; this.ctx.fill(); + this.ctx.stroke(); this.ctx.shadowBlur = 0; } - // Outer Circle + // Outer Node Circle this.ctx.beginPath(); - this.ctx.arc(nx, ny, 24, 0, Math.PI * 2); + this.ctx.arc(nx, ny, 26, 0, Math.PI * 2); if (node.status === 'running') { - this.ctx.fillStyle = '#0F172A'; - this.ctx.strokeStyle = '#00F0FF'; + this.ctx.fillStyle = '#090D16'; + this.ctx.strokeStyle = node.color; this.ctx.lineWidth = 3; } else if (node.status === 'completed') { - this.ctx.fillStyle = 'rgba(0, 255, 157, 0.2)'; + this.ctx.fillStyle = 'rgba(0, 255, 157, 0.15)'; this.ctx.strokeStyle = '#00FF9D'; this.ctx.lineWidth = 2; } else { @@ -158,8 +181,8 @@ class PipelineVisualizer { this.ctx.fill(); this.ctx.stroke(); - // Icon - this.ctx.font = '16px sans-serif'; + // Node Icon Emoji + this.ctx.font = '18px sans-serif'; this.ctx.textAlign = 'center'; this.ctx.textBaseline = 'middle'; this.ctx.fillText(node.icon, nx, ny); @@ -167,12 +190,12 @@ class PipelineVisualizer { // Node Name Label this.ctx.font = 'bold 11px Outfit, sans-serif'; this.ctx.fillStyle = node.status === 'running' ? '#00F0FF' : node.status === 'completed' ? '#00FF9D' : '#94A3B8'; - this.ctx.fillText(node.name, nx, ny + 42); + this.ctx.fillText(node.name, nx, ny + 46); - // Status Badge + // Status Badge Sub-label this.ctx.font = '9px Fira Code, monospace'; - this.ctx.fillStyle = '#64748B'; - this.ctx.fillText(node.status.toUpperCase(), nx, ny + 56); + this.ctx.fillStyle = node.status === 'running' ? '#00FF9D' : '#64748B'; + this.ctx.fillText(node.status.toUpperCase(), nx, ny + 62); }); }