Files
ollama-personal-trainer/public/index.html

345 lines
17 KiB
HTML

<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI-Trainer | Unsloth MoE & GRPO Control Center</title>
<!-- Google Fonts: Outfit, Inter, Fira Code -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700;800;900&family=Outfit:wght@400;600;700;800;900&display=swap" rel="stylesheet">
<!-- FontAwesome Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
cyberDark: '#07090E',
cyberCard: 'rgba(13, 18, 30, 0.85)',
cyberBorder: 'rgba(255, 255, 255, 0.08)',
neonCyan: '#00F0FF',
neonViolet: '#8A2BE2',
neonEmerald: '#00FF9D',
neonAmber: '#FFB800',
neonRose: '#FF3366'
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
outfit: ['Outfit', 'sans-serif'],
mono: ['Fira Code', 'monospace']
}
}
}
}
</script>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Custom Styles -->
<link rel="stylesheet" href="css/style.css">
</head>
<body class="bg-cyberDark text-slate-100 font-sans antialiased overflow-x-hidden min-h-screen flex flex-col">
<!-- Fullscreen Animated Loading Overlay -->
<div id="loadingOverlay" class="fixed inset-0 z-50 bg-cyberDark/95 backdrop-blur-xl flex flex-col items-center justify-center transition-all duration-500 opacity-0 pointer-events-none">
<div class="relative flex items-center justify-center">
<div class="w-28 h-28 border-4 border-cyan-500/20 border-t-cyan-400 rounded-full animate-spin"></div>
<div class="absolute w-20 h-20 border-4 border-violet-500/20 border-b-violet-400 rounded-full animate-spin-reverse"></div>
<div class="absolute w-12 h-12 border-4 border-emerald-500/20 border-t-emerald-400 rounded-full animate-spin"></div>
<i class="fa-solid fa-brain text-2xl text-cyan-400 animate-pulse"></i>
</div>
<h3 class="mt-8 text-2xl font-black tracking-widest text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-violet-400 to-emerald-400 uppercase font-outfit" id="loadingTitle">INITIALIZING NEURAL HARNESS...</h3>
<p class="text-xs text-slate-400 mt-2 font-mono" id="loadingSubtext">Loading Unsloth Triton Kernels & MoE Layer Router Maps</p>
</div>
<!-- Top Navigation Bar -->
<header class="border-b border-cyberBorder bg-slate-950/80 backdrop-blur-2xl sticky top-0 z-40 px-6 py-3.5 flex flex-wrap items-center justify-between gap-4">
<!-- Left: Brand Logo & Title -->
<div class="flex items-center gap-4">
<div class="relative group cursor-pointer">
<div class="absolute -inset-0.5 bg-gradient-to-r from-cyan-500 via-violet-600 to-emerald-500 rounded-xl blur opacity-60 group-hover:opacity-100 transition duration-300"></div>
<div class="relative w-11 h-11 bg-slate-950 rounded-xl flex items-center justify-center border border-white/10">
<i class="fa-solid fa-bolt text-cyan-400 text-xl group-hover:scale-110 transition duration-300"></i>
</div>
</div>
<div>
<div class="flex items-center gap-2.5">
<h1 class="text-xl font-black tracking-tight font-outfit text-white">AI-TRAINER</h1>
<span class="px-2.5 py-0.5 text-[10px] font-black tracking-widest bg-cyan-500/10 border border-cyan-500/30 text-cyan-400 rounded-full uppercase shadow-[0_0_10px_rgba(0,240,255,0.2)]">UNSLOTH GRPO MOE</span>
</div>
<p class="text-xs text-slate-400 font-mono">Proxify-ADB Autonomous Fleet Router & MoE Weight Shedder</p>
</div>
</div>
<!-- Middle: Live Telemetry Gauges -->
<div class="flex items-center gap-5 bg-slate-900/80 border border-cyberBorder px-5 py-2 rounded-2xl text-xs font-mono shadow-inner">
<div class="flex items-center gap-2.5">
<div class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></div>
<span class="text-slate-400">GPU VRAM:</span>
<strong class="text-cyan-300" id="gaugeVram">6.2 / 16.0 GB</strong>
</div>
<div class="w-px h-4 bg-slate-800"></div>
<div class="flex items-center gap-2.5">
<div class="w-2 h-2 rounded-full bg-violet-400 animate-pulse"></div>
<span class="text-slate-400">MoE Stream RAM:</span>
<strong class="text-violet-300" id="gaugeRam">34.5 / 64.0 GB</strong>
</div>
<div class="w-px h-4 bg-slate-800"></div>
<div class="flex items-center gap-2.5">
<div class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></div>
<span class="text-slate-400">ADB Fleet:</span>
<strong class="text-emerald-400" id="gaugeAdb">14 / 14 Connected</strong>
</div>
</div>
<!-- Right: Header Controls -->
<div class="flex items-center gap-3">
<button id="btnStartPipeline" class="btn-neon btn-emerald">
<i class="fa-solid fa-play"></i> RUN PIPELINE
</button>
<button id="btnStopPipeline" class="btn-neon btn-rose" disabled>
<i class="fa-solid fa-square"></i> STOP
</button>
<button id="btnOpenKnobs" class="btn-neon btn-ghost">
<i class="fa-solid fa-sliders"></i> TUNING KNOBS
</button>
<button id="btnSyncGitea" class="btn-neon btn-purple">
<i class="fa-solid fa-code-branch"></i> PUSH TO GITEA
</button>
</div>
</header>
<!-- Main Content Layout -->
<main class="flex-1 p-6 space-y-6 max-w-[1920px] mx-auto w-full pb-80">
<!-- Pipeline Canvas Stage Section -->
<section class="cyber-card p-6 rounded-2xl relative overflow-hidden">
<div class="flex flex-wrap items-center justify-between gap-4 mb-4">
<div>
<h2 class="text-lg font-black font-outfit text-white flex items-center gap-2.5">
<i class="fa-solid fa-diagram-project text-cyan-400"></i>
AUTONOMOUS UN SLOTH GRPO PIPELINE MAP
</h2>
<p class="text-xs text-slate-400">Real-time dynamic expert pruning, hard execution sandbox evaluation, and GGUF quant deployment</p>
</div>
<div class="flex items-center gap-4 text-xs font-mono">
<span class="status-badge status-idle" id="pipelineStatusBadge">STATUS: IDLE</span>
<div class="flex items-center gap-2 bg-slate-900/90 px-3 py-1 rounded-xl border border-slate-800">
<span class="text-slate-400">Overall Progress:</span>
<strong class="text-cyan-400 text-sm" id="overallProgressText">0%</strong>
</div>
</div>
</div>
<!-- Interactive Canvas Graph -->
<div class="relative w-full h-[240px] bg-slate-950/80 rounded-xl border border-slate-800/80 overflow-hidden shadow-2xl">
<canvas id="pipelineCanvas" class="w-full h-full block"></canvas>
</div>
</section>
<!-- Telemetry & Controls Grid -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<!-- Column 1: Charts & Expert Distributions (7 cols) -->
<div class="lg:col-span-7 space-y-6">
<!-- GRPO Reward Convergence Card -->
<div class="cyber-card p-5 rounded-2xl">
<div class="flex items-center justify-between mb-4">
<div>
<h3 class="text-sm font-bold font-outfit text-white flex items-center gap-2">
<i class="fa-solid fa-chart-line text-emerald-400"></i>
UNSLOTH GRPO HARD EXECUTION REWARD CONVERGENCE
</h3>
<p class="text-[11px] text-slate-400">Multi-vector reward curve ($R_{exec} = +3.0$, $R_{anti-hesit} = +2.0$, Safety = $-10.0$)</p>
</div>
<span class="text-xs font-mono text-emerald-400 bg-emerald-500/10 px-3 py-1 rounded-xl border border-emerald-500/30 font-bold">
Step <span id="grpoStepVal">0</span> / 300
</span>
</div>
<div class="h-[220px] w-full">
<canvas id="grpoChart"></canvas>
</div>
</div>
<!-- MoE Expert Pruning Distribution Card -->
<div class="cyber-card p-5 rounded-2xl">
<div class="flex items-center justify-between mb-4">
<div>
<h3 class="text-sm font-bold font-outfit text-white flex items-center gap-2">
<i class="fa-solid fa-scissors text-amber-400"></i>
DOMAIN MoE EXPERT RETENTION VS PRUNED TRIVIA EXPERTS
</h3>
<p class="text-[11px] text-slate-400">Dropping ~68.75% dormant botany/history experts across 61 layers</p>
</div>
<span class="text-xs font-mono text-amber-400 bg-amber-500/10 px-3 py-1 rounded-xl border border-amber-500/30 font-bold">
Retained: <span id="retainedExpertsVal">64</span> / 256
</span>
</div>
<div class="h-[180px] w-full">
<canvas id="moeChart"></canvas>
</div>
</div>
</div>
<!-- Column 2: Fleet Topology & Script Code Inspector (5 cols) -->
<div class="lg:col-span-5 space-y-6">
<!-- Proxmox Fleet Topology Card -->
<div class="cyber-card p-5 rounded-2xl">
<div class="flex items-center justify-between mb-3">
<h3 class="text-sm font-bold font-outfit text-white flex items-center gap-2">
<i class="fa-solid fa-network-wired text-cyan-400"></i>
10.30.20.0/24 PROXMOX FLEET TOPOLOGY
</h3>
<span class="text-[10px] font-mono text-cyan-400 bg-cyan-500/10 px-2 py-0.5 rounded border border-cyan-500/30">vmbr1 Isolated</span>
</div>
<div class="grid grid-cols-2 gap-3 text-xs font-mono mb-4">
<div class="bg-slate-950/80 border border-slate-800 p-3 rounded-xl">
<span class="text-slate-400 block text-[10px]">Gateway Control Node</span>
<strong class="text-cyan-300 text-sm">10.30.20.1</strong>
<div class="mt-1 text-[10px] text-slate-500">Port 5555 / REST API</div>
</div>
<div class="bg-slate-950/80 border border-slate-800 p-3 rounded-xl">
<span class="text-slate-400 block text-[10px]">Dynamic DHCP Pool</span>
<strong class="text-violet-300 text-sm">.100 ──► .254</strong>
<div class="mt-1 text-[10px] text-slate-500">dnsmasq 12h Leases</div>
</div>
</div>
<!-- Active VM Nodes Grid -->
<div class="space-y-2 max-h-[190px] overflow-y-auto custom-scrollbar pr-1" id="fleetNodeList">
<!-- Dynamically Rendered Cards -->
</div>
</div>
<!-- Python Script Viewer Card -->
<div class="cyber-card p-5 rounded-2xl flex flex-col h-[280px]">
<div class="flex items-center justify-between mb-3">
<h3 class="text-sm font-bold font-outfit text-white flex items-center gap-2">
<i class="fa-brands fa-python text-yellow-400"></i>
PIPELINE SCRIPT INSPECTOR
</h3>
<select id="scriptSelector" class="bg-slate-950 border border-slate-800 text-xs font-mono text-cyan-400 px-3 py-1 rounded-xl focus:outline-none focus:border-cyan-500">
<option value="harvester.py">harvester.py</option>
<option value="prune_moe.py">prune_moe.py</option>
<option value="harness_env.py">harness_env.py</option>
<option value="train_grpo.py">train_grpo.py</option>
<option value="deploy.py">deploy.py</option>
<option value="state_eye.py">state_eye.py</option>
</select>
</div>
<pre class="flex-1 bg-slate-950 p-4 rounded-xl border border-slate-900 text-xs font-mono text-slate-300 overflow-auto custom-scrollbar leading-relaxed" id="scriptCodeView"># Select a script to view source code...</pre>
</div>
</div>
</div>
</main>
<!-- Sticky Collapsible Cyber Terminal Log Console at Bottom -->
<div id="terminalContainer" class="fixed bottom-0 left-0 right-0 z-30 bg-slate-950/95 border-t border-slate-800 shadow-2xl backdrop-blur-2xl transition-all duration-300">
<!-- Terminal Header & Action Bar -->
<div class="px-6 py-2.5 bg-slate-900/90 border-b border-slate-800 flex flex-wrap items-center justify-between gap-4 text-xs font-mono">
<div class="flex items-center gap-3">
<button id="btnToggleTerminal" class="w-7 h-7 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 hover:text-white flex items-center justify-center transition">
<i class="fa-solid fa-chevron-down text-xs" id="terminalChevron"></i>
</button>
<span class="font-bold text-cyan-400 flex items-center gap-2 text-sm">
<i class="fa-solid fa-terminal"></i> LIVE LOG STREAM CONSOLE
</span>
<span class="bg-cyan-500/10 border border-cyan-500/30 text-cyan-400 px-2.5 py-0.5 rounded-full text-[10px] font-bold" id="logCountBadge">0 Logs</span>
</div>
<!-- Filter Buttons & Controls -->
<div class="flex items-center gap-3">
<div class="flex items-center gap-1 bg-slate-950 px-2 py-1 rounded-xl border border-slate-800">
<span class="text-slate-500 text-[10px] px-1 font-bold">LEVEL:</span>
<button class="log-filter-btn active" data-filter="ALL">ALL</button>
<button class="log-filter-btn" data-filter="INFO">INFO</button>
<button class="log-filter-btn" data-filter="HARNESS">HARNESS</button>
<button class="log-filter-btn" data-filter="REWARD">REWARD</button>
<button class="log-filter-btn" data-filter="WARN">WARN</button>
</div>
<button id="btnAutoScroll" class="px-3 py-1 rounded-xl bg-cyan-500/20 text-cyan-400 border border-cyan-500/40 text-[11px] font-bold hover:bg-cyan-500/30 transition">
<i class="fa-solid fa-angles-down"></i> Auto-Scroll
</button>
<button id="btnClearLogs" class="px-3 py-1 rounded-xl bg-slate-800 text-slate-400 hover:text-white text-[11px] border border-slate-700 transition">
<i class="fa-solid fa-trash-can"></i> Clear
</button>
</div>
</div>
<!-- Rolling Terminal Stream Body -->
<div id="terminalBody" class="h-60 p-4 font-mono text-xs overflow-y-auto space-y-1 custom-scrollbar bg-slate-950 select-text">
<!-- Live Stream Logs Added Here -->
</div>
</div>
<!-- Tuning Knobs Modal -->
<div id="knobsModal" class="fixed inset-0 z-50 bg-black/80 backdrop-blur-xl flex items-center justify-center p-4 opacity-0 pointer-events-none transition-opacity duration-300">
<div class="cyber-card max-w-lg w-full p-6 rounded-2xl border border-slate-800 space-y-6 shadow-2xl">
<div class="flex items-center justify-between border-b border-slate-800 pb-3">
<h3 class="text-lg font-black font-outfit text-white flex items-center gap-2">
<i class="fa-solid fa-sliders text-cyan-400"></i> TUNING KNOBS & REWARD WEIGHTS
</h3>
<button id="btnCloseKnobs" class="text-slate-400 hover:text-white text-lg"><i class="fa-solid fa-xmark"></i></button>
</div>
<div class="space-y-5 text-xs font-mono">
<div>
<label class="flex justify-between text-slate-300 mb-1.5">
<span>Retained MoE Experts per Layer:</span>
<strong class="text-cyan-400 text-sm" id="knobExpertsVal">64 / 256</strong>
</label>
<input type="range" id="knobExperts" min="16" max="128" step="16" value="64" class="w-full accent-cyan-400">
</div>
<div>
<label class="flex justify-between text-slate-300 mb-1.5">
<span>Hard Execution Reward Weight ($w_1$):</span>
<strong class="text-emerald-400 text-sm" id="knobExecVal">3.0</strong>
</label>
<input type="range" id="knobExec" min="1.0" max="5.0" step="0.5" value="3.0" class="w-full accent-emerald-400">
</div>
<div>
<label class="flex justify-between text-slate-300 mb-1.5">
<span>Anti-Hesitation Penalty Weight ($w_2$):</span>
<strong class="text-amber-400 text-sm" id="knobHesitVal">2.0</strong>
</label>
<input type="range" id="knobHesit" min="0.5" max="4.0" step="0.5" value="2.0" class="w-full accent-amber-400">
</div>
<div class="bg-slate-950 p-3 rounded-xl border border-slate-800">
<span class="text-slate-400 block text-[11px]">Hardware Memory Target:</span>
<strong class="text-violet-300">16.0 GB VRAM + 64.0 GB System RAM Streaming</strong>
</div>
</div>
<div class="flex justify-end gap-3 pt-3 border-t border-slate-800">
<button id="btnSaveKnobs" class="btn-neon btn-emerald w-full justify-center">SAVE & APPLY PARAMETERS</button>
</div>
</div>
</div>
<!-- Scripts -->
<script src="js/pipeline.js"></script>
<script src="js/charts.js"></script>
<script src="js/terminal.js"></script>
<script src="js/app.js"></script>
</body>
</html>