microd_v1 / micro_distillery /micro_distillery.html
webxos's picture
Rename generator/microd.html to micro_distillery/micro_distillery.html
e8aaec3 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#000000">
<meta name="description" content="Micro Distillery: GRPO + VAE Enhanced Training System">
<title>[mD] MICRO DISTILLERY | webXOS 2025</title>
<!-- PWA Manifest -->
<link rel="manifest" href="manifest.json">
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" href="icon-192.png">
<style>
:root {
--bg: #000000;
--text: #00ff00;
--border: #008000;
--accent: #00ffff;
--error: #ff0000;
--success: #00ff00;
--warning: #ffff00;
--distill: #00ff9d;
--quantize: #ff00ff;
--teacher: #ff6b00;
--upload: #00ccff;
--export: #9d00ff;
--panel-bg: rgba(0, 20, 0, 0.1);
--grpo: #ff00ff;
--vae: #00ddff;
--cache: #ff9900;
--mask: #aa00ff;
--sandbox: #00aa88;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Courier New', monospace;
}
body {
background: var(--bg);
color: var(--text);
padding: 10px;
font-size: 12px;
line-height: 1.3;
max-width: 1600px;
margin: 0 auto;
min-height: 100vh;
overflow-x: hidden;
}
.header {
padding: 10px 0;
margin-bottom: 15px;
text-align: center;
border-bottom: 1px solid var(--border);
}
.title {
font-size: 18px;
color: var(--text);
margin-bottom: 5px;
}
.subtitle {
font-size: 12px;
color: var(--accent);
margin-bottom: 10px;
}
.header-controls {
display: flex;
justify-content: center;
gap: 10px;
margin-top: 10px;
}
.main-grid {
display: grid;
grid-template-columns: 350px 350px 1fr;
gap: 15px;
margin-bottom: 15px;
}
@media (max-width: 1200px) {
.main-grid {
grid-template-columns: 1fr;
}
}
.panel {
border: 1px solid var(--border);
padding: 15px;
background: var(--panel-bg);
border-radius: 3px;
min-height: 500px;
}
.panel-title {
color: var(--accent);
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px solid var(--border);
font-size: 12px;
font-weight: bold;
}
.section {
padding: 10px;
border-radius: 3px;
margin: 10px 0;
}
.grpo-section {
border: 1px solid var(--grpo);
background: rgba(255, 0, 255, 0.05);
}
.vae-section {
border: 1px solid var(--vae);
background: rgba(0, 221, 255, 0.05);
}
.cache-section {
border: 1px solid var(--cache);
background: rgba(255, 153, 0, 0.05);
}
.mask-section {
border: 1px solid var(--mask);
background: rgba(170, 0, 255, 0.05);
}
.sandbox-section {
border: 1px solid var(--sandbox);
background: rgba(0, 170, 136, 0.05);
}
.slider-container {
margin: 8px 0;
}
.slider-container label {
display: block;
font-size: 11px;
color: var(--accent);
margin-bottom: 3px;
}
.slider-value {
float: right;
font-size: 10px;
color: #008000;
}
input[type="range"] {
width: 100%;
height: 4px;
background: #111;
border-radius: 2px;
outline: none;
-webkit-appearance: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
background: var(--grpo);
border-radius: 50%;
cursor: pointer;
}
.action-btn {
background: #001100;
border: 1px solid var(--border);
color: var(--text);
padding: 10px;
font-size: 12px;
cursor: pointer;
border-radius: 3px;
font-family: 'Courier New', monospace;
transition: all 0.2s;
width: 100%;
margin: 5px 0;
}
.action-btn:hover {
background: #002200;
border-color: var(--accent);
box-shadow: 0 0 5px var(--accent);
}
.btn-grpo {
border-color: var(--grpo);
color: var(--grpo);
}
.btn-vae {
border-color: var(--vae);
color: var(--vae);
}
.btn-sandbox {
border-color: var(--sandbox);
color: var(--sandbox);
}
.btn-export {
border-color: var(--export);
color: var(--export);
padding: 8px 15px;
width: auto;
}
#terminal {
height: 300px;
overflow-y: auto;
background: #000;
border: 1px solid var(--border);
padding: 10px;
font-size: 11px;
font-family: 'Courier New', monospace;
line-height: 1.3;
margin-bottom: 15px;
}
.log-entry {
margin-bottom: 2px;
padding: 1px 0;
border-bottom: 1px solid rgba(0, 255, 0, 0.05);
}
.log-grpo { color: var(--grpo); }
.log-vae { color: var(--vae); }
.log-cache { color: var(--cache); }
.log-mask { color: var(--mask); }
.log-sandbox { color: var(--sandbox); }
.log-error { color: var(--error); }
.log-success { color: var(--success); }
.log-export { color: var(--export); }
.metrics-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 5px;
margin: 10px 0;
}
.metric-card {
background: rgba(0, 30, 0, 0.2);
border: 1px solid var(--border);
padding: 5px;
border-radius: 2px;
text-align: center;
font-size: 10px;
}
.metric-value {
font-size: 12px;
font-weight: bold;
}
.metric-grpo { color: var(--grpo); }
.metric-vae { color: var(--vae); }
.metric-cache { color: var(--cache); }
.metric-mask { color: var(--mask); }
.sandbox-container {
margin-top: 15px;
border: 1px solid var(--border);
border-radius: 3px;
overflow: hidden;
}
.sandbox-header {
background: rgba(0, 30, 0, 0.3);
padding: 8px;
border-bottom: 1px solid var(--border);
color: var(--sandbox);
font-weight: bold;
}
.sandbox-content {
padding: 10px;
background: rgba(0, 0, 0, 0.5);
height: 150px;
overflow-y: auto;
font-family: monospace;
font-size: 11px;
white-space: pre-wrap;
}
.sandbox-input {
display: flex;
border-top: 1px solid var(--border);
background: rgba(0, 30, 0, 0.2);
}
.sandbox-input input {
flex: 1;
background: transparent;
color: var(--text);
border: none;
padding: 8px;
font-family: monospace;
font-size: 11px;
}
.sandbox-input button {
background: rgba(0, 170, 136, 0.2);
border: none;
border-left: 1px solid var(--border);
color: var(--sandbox);
padding: 8px 15px;
cursor: pointer;
font-size: 11px;
}
.token-display {
display: flex;
flex-wrap: wrap;
gap: 3px;
margin: 10px 0;
padding: 10px;
background: rgba(0, 0, 0, 0.3);
border-radius: 3px;
max-height: 100px;
overflow-y: auto;
}
.token {
padding: 2px 5px;
background: rgba(0, 255, 0, 0.1);
border: 1px solid rgba(0, 255, 0, 0.3);
border-radius: 2px;
font-size: 9px;
font-family: monospace;
}
.token.cached {
background: rgba(255, 153, 0, 0.2);
border-color: var(--cache);
}
.token.masked {
background: rgba(170, 0, 255, 0.2);
border-color: var(--mask);
opacity: 0.6;
}
.progress-container {
margin: 10px 0;
}
.progress-bar {
height: 8px;
background: #111;
border: 1px solid var(--border);
overflow: hidden;
border-radius: 2px;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #008000, #00ff00);
width: 0%;
transition: width 0.3s;
}
.progress-text {
text-align: center;
margin-top: 3px;
font-size: 10px;
color: #008000;
}
.hidden {
display: none !important;
}
.latent-space {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 5px;
margin: 10px 0;
}
.latent-dim {
padding: 5px;
background: rgba(0, 221, 255, 0.1);
border: 1px solid var(--vae);
border-radius: 2px;
text-align: center;
font-size: 9px;
}
.latent-value {
font-size: 10px;
font-weight: bold;
color: var(--vae);
display: block;
margin-top: 2px;
}
.status-indicator {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 5px;
}
.status-active { background: var(--success); }
.status-inactive { background: #333; }
.status-error { background: var(--error); }
select {
width: 100%;
background: #001100;
color: #00ff00;
border: 1px solid var(--border);
padding: 6px;
border-radius: 2px;
font-size: 11px;
font-family: 'Courier New', monospace;
margin: 5px 0;
}
/* Export Modal Styles */
.export-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.export-modal.hidden {
display: none;
}
.export-window {
background: var(--bg);
border: 2px solid var(--export);
border-radius: 5px;
width: 800px;
max-width: 90%;
height: 600px;
display: flex;
flex-direction: column;
box-shadow: 0 0 30px rgba(157, 0, 255, 0.3);
}
.export-header {
background: rgba(157, 0, 255, 0.1);
padding: 15px;
border-bottom: 1px solid var(--export);
color: var(--export);
font-size: 14px;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center;
}
.close-export {
background: none;
border: 1px solid var(--export);
color: var(--export);
padding: 5px 10px;
cursor: pointer;
border-radius: 3px;
font-family: 'Courier New', monospace;
font-size: 12px;
}
.close-export:hover {
background: rgba(157, 0, 255, 0.2);
}
.export-body {
display: flex;
flex: 1;
overflow: hidden;
}
.export-sidebar {
width: 200px;
background: rgba(0, 20, 0, 0.2);
border-right: 1px solid var(--border);
padding: 15px;
overflow-y: auto;
}
.export-main {
flex: 1;
padding: 15px;
overflow-y: auto;
}
.export-format {
margin-bottom: 20px;
}
.format-option {
padding: 8px;
border: 1px solid var(--border);
margin: 5px 0;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s;
font-size: 11px;
}
.format-option:hover {
border-color: var(--export);
background: rgba(157, 0, 255, 0.1);
}
.format-option.selected {
border-color: var(--export);
background: rgba(157, 0, 255, 0.2);
}
.file-browser {
margin-top: 20px;
}
.file-item {
padding: 5px 10px;
border-bottom: 1px solid rgba(0, 255, 0, 0.1);
cursor: pointer;
font-size: 11px;
display: flex;
align-items: center;
gap: 8px;
}
.file-item:hover {
background: rgba(0, 255, 0, 0.05);
}
.file-item.selected {
background: rgba(157, 0, 255, 0.1);
}
.file-icon {
color: var(--export);
font-size: 12px;
}
.file-content {
background: rgba(0, 0, 0, 0.5);
border: 1px solid var(--border);
border-radius: 3px;
padding: 15px;
margin-top: 15px;
max-height: 300px;
overflow-y: auto;
font-family: monospace;
font-size: 10px;
white-space: pre-wrap;
}
.export-footer {
padding: 15px;
border-top: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
background: rgba(0, 20, 0, 0.2);
}
.export-btn {
background: rgba(157, 0, 255, 0.2);
border: 1px solid var(--export);
color: var(--export);
padding: 10px 20px;
cursor: pointer;
border-radius: 3px;
font-family: 'Courier New', monospace;
font-size: 12px;
transition: all 0.2s;
}
.export-btn:hover {
background: rgba(157, 0, 255, 0.3);
box-shadow: 0 0 10px rgba(157, 0, 255, 0.5);
}
.export-info {
font-size: 11px;
color: var(--accent);
}
.file-size {
color: var(--cache);
font-size: 10px;
margin-left: auto;
}
.export-progress {
margin-top: 15px;
padding: 10px;
background: rgba(0, 20, 0, 0.3);
border-radius: 3px;
border: 1px solid var(--border);
}
.export-progress.hidden {
display: none;
}
.progress-step {
margin: 5px 0;
font-size: 11px;
display: flex;
align-items: center;
gap: 10px;
}
.step-indicator {
width: 20px;
height: 20px;
border-radius: 50%;
background: #333;
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
}
.step-indicator.active {
background: var(--export);
border-color: var(--export);
}
.step-indicator.completed {
background: var(--success);
border-color: var(--success);
}
.binary-warning {
color: var(--warning);
font-size: 10px;
margin-top: 5px;
padding: 5px;
background: rgba(255, 255, 0, 0.1);
border-radius: 2px;
}
/* PWA Install Prompt */
.install-prompt {
position: fixed;
bottom: 20px;
right: 20px;
background: rgba(0, 20, 0, 0.95);
border: 1px solid var(--border);
border-radius: 5px;
padding: 15px;
z-index: 1001;
max-width: 300px;
box-shadow: 0 0 20px rgba(0, 255, 0, 0.3);
}
.install-prompt.hidden {
display: none;
}
.install-buttons {
display: flex;
gap: 10px;
margin-top: 10px;
}
.install-btn {
flex: 1;
padding: 8px;
border: 1px solid var(--success);
background: rgba(0, 255, 0, 0.1);
color: var(--success);
cursor: pointer;
border-radius: 3px;
font-size: 11px;
}
.install-btn:hover {
background: rgba(0, 255, 0, 0.2);
}
.install-btn.dismiss {
border-color: var(--error);
color: var(--error);
background: rgba(255, 0, 0, 0.1);
}
/* Offline Indicator */
.offline-indicator {
position: fixed;
top: 10px;
right: 10px;
background: rgba(255, 0, 0, 0.2);
border: 1px solid var(--error);
color: var(--error);
padding: 5px 10px;
border-radius: 3px;
font-size: 10px;
z-index: 1002;
}
.offline-indicator.hidden {
display: none;
}
</style>
</head>
<body>
<div class="header">
<div class="title">[mD] MICRO DISTILLERY | webXOS 2025</div>
<div class="subtitle">
GRPO • Interpreter Feedback Masking • KV-Cache Reuse • VAE Filtering
</div>
<div class="header-controls">
<button id="btn-show-export" class="action-btn btn-export">
🚀 EXPORT TRAINED MODEL
</button>
</div>
</div>
<div class="main-grid">
<!-- Left Panel: GRPO Configuration -->
<div class="panel">
<div class="panel-title">GRPO CONFIGURATION</div>
<div class="section grpo-section">
<div class="slider-container">
<label>Group Size <span class="slider-value" id="group-size-value">8</span></label>
<input type="range" id="group-size" min="4" max="32" step="2" value="8">
</div>
<div class="slider-container">
<label>KL Penalty <span class="slider-value" id="kl-penalty-value">0.10</span></label>
<input type="range" id="kl-penalty" min="0.01" max="0.5" step="0.01" value="0.1">
</div>
<div class="slider-container">
<label>Advantage Clip <span class="slider-value" id="advantage-clip-value">2.0</span></label>
<input type="range" id="advantage-clip" min="0.1" max="5.0" step="0.1" value="2.0">
</div>
<select id="policy-arch">
<option value="gpt2-small">GPT-2 Small (117M)</option>
<option value="gpt2-medium">GPT-2 Medium (345M)</option>
<option value="distilgpt2">DistilGPT-2 (82M)</option>
<option value="tiny-custom">Tiny Custom (42M)</option>
</select>
</div>
<div class="section cache-section">
<div class="slider-container">
<label>KV-Cache Size <span class="slider-value" id="cache-size-value">512</span></label>
<input type="range" id="cache-size" min="128" max="2048" step="128" value="512">
</div>
<div class="slider-container">
<label>Cache Reuse Threshold <span class="slider-value" id="cache-threshold-value">0.90</span></label>
<input type="range" id="cache-threshold" min="0.7" max="0.99" step="0.01" value="0.9">
</div>
<div style="font-size: 10px; color: var(--cache); margin-top: 5px;">
<span class="status-indicator" id="cache-status"></span>
KV-Cache: <span id="cache-status-text">Inactive</span>
</div>
</div>
<button id="btn-init-grpo" class="action-btn btn-grpo">
🚀 INITIALIZE GRPO SYSTEM
</button>
<button id="btn-train-grpo" class="action-btn btn-grpo" style="display: none;">
🏃 START GRPO TRAINING
</button>
<button id="btn-stop-grpo" class="action-btn" style="display: none; background: rgba(255,0,0,0.1);">
⏹️ STOP TRAINING
</button>
<div class="metrics-grid">
<div class="metric-card">
<div>Groups</div>
<div class="metric-value metric-grpo" id="metric-groups">0</div>
</div>
<div class="metric-card">
<div>Cache Hit</div>
<div class="metric-value metric-cache" id="metric-cache-hit">0%</div>
</div>
<div class="metric-card">
<div>Training Steps</div>
<div class="metric-value metric-grpo" id="metric-steps">0</div>
</div>
</div>
</div>
<!-- Middle Panel: VAE & Masking Configuration -->
<div class="panel">
<div class="panel-title">VAE FILTER & MASKING</div>
<div class="section vae-section">
<div class="slider-container">
<label>Latent Dimension <span class="slider-value" id="latent-dim-value">32</span></label>
<input type="range" id="latent-dim" min="8" max="128" step="8" value="32">
</div>
<div class="slider-container">
<label>Beta (KL Weight) <span class="slider-value" id="vae-beta-value">0.010</span></label>
<input type="range" id="vae-beta" min="0.001" max="0.1" step="0.001" value="0.01">
</div>
<div class="slider-container">
<label>Filter Threshold <span class="slider-value" id="filter-threshold-value">0.70</span></label>
<input type="range" id="filter-threshold" min="0.1" max="0.9" step="0.05" value="0.7">
</div>
<button id="btn-train-vae" class="action-btn btn-vae">
🌀 TRAIN VAE FILTER
</button>
</div>
<div class="section mask-section">
<div class="slider-container">
<label>Mask Intensity <span class="slider-value" id="mask-intensity-value">0.8</span></label>
<input type="range" id="mask-intensity" min="0.1" max="1.0" step="0.1" value="0.8">
</div>
<div class="slider-container">
<label>Feedback Window <span class="slider-value" id="feedback-window-value">50</span></label>
<input type="range" id="feedback-window" min="10" max="100" step="5" value="50">
</div>
<div style="font-size: 10px; color: var(--mask); margin-top: 5px;">
<span class="status-indicator" id="mask-status"></span>
Masking: <span id="mask-status-text">Inactive</span>
</div>
</div>
<div class="latent-space" id="latent-display">
<!-- Latent dimensions will be populated here -->
</div>
<div class="metrics-grid">
<div class="metric-card">
<div>VAE Loss</div>
<div class="metric-value metric-vae" id="metric-vae-loss">0.000</div>
</div>
<div class="metric-card">
<div>Filtered %</div>
<div class="metric-value metric-vae" id="metric-filtered">0%</div>
</div>
<div class="metric-card">
<div>Masked Tokens</div>
<div class="metric-value metric-mask" id="metric-masked">0</div>
</div>
</div>
</div>
<!-- Right Panel: Terminal & Sandbox -->
<div class="panel">
<div class="panel-title">REAL-TIME TRAINING TERMINAL</div>
<div id="terminal">
[00:00:00] [mD] GRPO + VAE Enhanced Training System v1.0
[00:00:00] FEATURES:
[00:00:00] • Group Relative Policy Optimization (GRPO)
[00:00:00] • Interpreter Feedback Masking
[00:00:00] • KV-Cache Reuse for Thought tokens
[00:00:00] • VAE Filter for distillation quality
[00:00:00] • Python sandbox integration
[00:00:00] STATUS: Ready for initialization...
</div>
<div class="progress-container">
<div class="progress-bar">
<div class="progress-fill" id="progress-fill"></div>
</div>
<div class="progress-text" id="progress-text">Idle</div>
</div>
<div class="section sandbox-section">
<div class="sandbox-header">
🐍 Python Sandbox Interface
</div>
<div class="sandbox-content" id="sandbox-output">
>>> Python 3.11 (simulated) - Sandbox Ready
>>> Safe execution environment active
>>> Max execution time: 5 seconds
</div>
<div class="sandbox-input">
<input type="text" id="sandbox-input" placeholder="Enter Python code (e.g., print('Hello'))">
<button id="btn-execute">Execute</button>
</div>
</div>
<div style="margin-top: 10px;">
<div style="font-size: 11px; color: var(--accent); margin-bottom: 5px;">Token Visualization:</div>
<div class="token-display" id="token-display">
<!-- Tokens will be displayed here -->
</div>
</div>
</div>
</div>
<!-- Export Modal Window -->
<div id="export-modal" class="export-modal hidden">
<div class="export-window">
<div class="export-header">
🚀 Export Micro-Distilled Model
<button class="close-export">✕ Close</button>
</div>
<div class="export-body">
<div class="export-sidebar">
<div class="export-format">
<div style="color: var(--export); font-size: 12px; margin-bottom: 10px;">Export Format</div>
<div class="format-option selected" data-format="huggingface">
🤗 Hugging Face
</div>
<div class="format-option" data-format="safetensors">
🔒 SafeTensors
</div>
<div class="format-option" data-format="gguf">
🐬 GGUF (llama.cpp)
</div>
<div class="format-option" data-format="onnx">
⚡ ONNX Runtime
</div>
</div>
<div class="file-browser">
<div style="color: var(--export); font-size: 12px; margin-bottom: 10px;">Model Files</div>
<div id="file-list">
<!-- Files will be populated here -->
</div>
</div>
</div>
<div class="export-main">
<div style="color: var(--export); font-size: 12px; margin-bottom: 10px;">File Preview</div>
<div id="file-preview" class="file-content">
Select a file to preview its contents...
</div>
<div class="binary-warning" id="binary-warning" style="display: none;">
⚠️ This is a binary file. Preview shows metadata only.
</div>
<div style="margin-top: 20px;">
<div style="color: var(--export); font-size: 12px; margin-bottom: 10px;">Export Options</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<div>
<label style="display: block; font-size: 11px; margin-bottom: 5px; color: var(--accent);">
<input type="checkbox" id="include-tokenizer" checked> Include tokenizer
</label>
<label style="display: block; font-size: 11px; margin-bottom: 5px; color: var(--accent);">
<input type="checkbox" id="include-config" checked> Include config.json
</label>
<label style="display: block; font-size: 11px; margin-bottom: 5px; color: var(--accent);">
<input type="checkbox" id="include-logs"> Include training logs
</label>
</div>
<div>
<label style="display: block; font-size: 11px; margin-bottom: 5px; color: var(--accent);">
<input type="checkbox" id="quantize" checked> Quantize (4-bit)
</label>
<label style="display: block; font-size: 11px; margin-bottom: 5px; color: var(--accent);">
<input type="checkbox" id="include-metadata" checked> Include metadata
</label>
<label style="display: block; font-size: 11px; margin-bottom: 5px; color: var(--accent);">
<input type="checkbox" id="zip-compression" checked> Zip compression
</label>
</div>
</div>
</div>
<div id="export-progress" class="export-progress hidden">
<div style="color: var(--export); font-size: 12px; margin-bottom: 10px;">Export Progress</div>
<div class="progress-step">
<div class="step-indicator" id="step-1">1</div>
<div>Preparing files...</div>
</div>
<div class="progress-step">
<div class="step-indicator" id="step-2">2</div>
<div>Creating archive...</div>
</div>
<div class="progress-step">
<div class="step-indicator" id="step-3">3</div>
<div>Generating download...</div>
</div>
</div>
</div>
</div>
<div class="export-footer">
<div class="export-info">
Total size: <span id="total-size">~500 MB</span> • Files: <span id="file-count">12</span>
</div>
<button id="btn-final-export" class="export-btn">
🚀 EXPORT TO HUGGING FACE
</button>
</div>
</div>
</div>
<!-- PWA Install Prompt -->
<div id="install-prompt" class="install-prompt hidden">
<div style="font-size: 12px; margin-bottom: 8px;">📱 Install Micro Distillery as PWA?</div>
<div style="font-size: 10px; color: var(--accent); margin-bottom: 10px;">
Install for offline access and faster loading.
</div>
<div class="install-buttons">
<button id="btn-install" class="install-btn">Install</button>
<button id="btn-dismiss" class="install-btn dismiss">Dismiss</button>
</div>
</div>
<!-- Offline Indicator -->
<div id="offline-indicator" class="offline-indicator hidden">
⚠️ You are offline
</div>
<!-- External Libraries -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
<script>
// ==================== GRPO + VAE TRAINING SYSTEM ====================
class GRPOTrainingSystem {
constructor() {
this.initialized = false;
this.training = false;
this.vaeTraining = false;
// GRPO State
this.groups = [];
this.currentGroup = 0;
this.cache = new Map();
this.cache.maxSize = 512;
this.maskPatterns = [];
this.cachePatterns = [];
// VAE State
this.vaeModel = null;
this.latentSamples = [];
this.filteredSamples = [];
// Export State
this.modelFiles = [];
this.selectedFormat = 'huggingface';
this.vocabSize = 50257;
this.mergesSize = 50000;
// Training Metrics
this.metrics = {
cacheHits: 0,
cacheMisses: 0,
maskedTokens: 0,
totalTokens: 0,
vaeLoss: 0.0123,
klDivergence: 0,
filteredCount: 0,
totalSamples: 0,
trainingSteps: 0,
finalLoss: 0.0423,
cacheHitRate: 0.784,
filterRate: 0.684,
maskRate: 0.312,
averageReward: 0.82
};
// Initialize with default files
this.generateDynamicFiles();
// Update UI
this.updateStatus('cache', 'inactive');
this.updateStatus('mask', 'inactive');
this.updateMetrics();
this.log('GRPO + VAE System initialized', 'system');
}
// ========== EXPORT SYSTEM ==========
generateDynamicFiles() {
const groupSize = parseInt(document.getElementById('group-size').value) || 8;
const klPenalty = parseFloat(document.getElementById('kl-penalty').value) || 0.1;
const advantageClip = parseFloat(document.getElementById('advantage-clip').value) || 2.0;
const latentDim = parseInt(document.getElementById('latent-dim').value) || 32;
const vaeBeta = parseFloat(document.getElementById('vae-beta').value) || 0.01;
const filterThreshold = parseFloat(document.getElementById('filter-threshold').value) || 0.7;
const cacheSize = parseInt(document.getElementById('cache-size').value) || 512;
const cacheThreshold = parseFloat(document.getElementById('cache-threshold').value) || 0.9;
const maskIntensity = parseFloat(document.getElementById('mask-intensity').value) || 0.8;
const feedbackWindow = parseInt(document.getElementById('feedback-window').value) || 50;
const policyArch = document.getElementById('policy-arch').value || 'gpt2-small';
// Model architecture configuration
let modelType, hiddenSize, numLayers, numHeads, intermediateSize, modelSize;
switch(policyArch) {
case 'gpt2-small':
modelType = 'gpt2';
hiddenSize = 768;
numLayers = 12;
numHeads = 12;
intermediateSize = 3072;
modelSize = '117M';
break;
case 'gpt2-medium':
modelType = 'gpt2';
hiddenSize = 1024;
numLayers = 24;
numHeads = 16;
intermediateSize = 4096;
modelSize = '345M';
break;
case 'distilgpt2':
modelType = 'gpt2';
hiddenSize = 768;
numLayers = 6;
numHeads = 12;
intermediateSize = 3072;
modelSize = '82M';
break;
case 'tiny-custom':
modelType = 'micro-distill-grpo-vae';
hiddenSize = 512;
numLayers = 8;
numHeads = 8;
intermediateSize = 2048;
modelSize = '42M';
break;
default:
modelType = 'gpt2';
hiddenSize = 768;
numLayers = 12;
numHeads = 12;
intermediateSize = 3072;
modelSize = '117M';
}
// Config JSON
const configJson = {
"architectures": [
modelType === 'micro-distill-grpo-vae' ? "GPT2LMHeadModel" : "GPT2LMHeadModel"
],
"model_type": modelType === 'micro-distill-grpo-vae' ? "gpt2" : modelType,
"vocab_size": this.vocabSize,
"n_positions": 1024,
"n_embd": hiddenSize,
"n_layer": numLayers,
"n_head": numHeads,
"n_inner": intermediateSize,
"activation_function": "gelu_new",
"resid_pdrop": 0.1,
"embd_pdrop": 0.1,
"attn_pdrop": 0.1,
"layer_norm_epsilon": 1e-5,
"initializer_range": 0.02,
"summary_type": "cls_index",
"summary_use_proj": true,
"summary_activation": null,
"summary_proj_to_labels": true,
"summary_first_dropout": 0.1,
"scale_attn_weights": true,
"use_cache": true,
"bos_token_id": 50256,
"eos_token_id": 50256,
"transformers_version": "4.36.0",
"grpo_config": {
"group_size": groupSize,
"kl_penalty": klPenalty,
"advantage_clip": advantageClip,
"mask_intensity": maskIntensity,
"feedback_window": feedbackWindow
},
"vae_config": {
"latent_dim": latentDim,
"beta": vaeBeta,
"filter_threshold": filterThreshold
},
"cache_config": {
"cache_size": cacheSize,
"reuse_threshold": cacheThreshold
}
};
// Generate files
const vocab = this.generateFullVocabulary();
const merges = this.generateMergesFile();
const tokenizerJson = this.generateTokenizerJson();
const modelWeights = this.generateModelWeights(hiddenSize, numLayers, numHeads);
const safetensorsContent = this.generateSafetensorsFile(hiddenSize, numLayers, numHeads);
const onnxContent = this.generateOnnxFile(hiddenSize, numLayers, numHeads);
const ggufContent = this.generateGGUFFile();
// Update model files
this.modelFiles = [
{
name: 'config.json',
size: '3.2 KB',
content: JSON.stringify(configJson, null, 2),
type: 'config',
isBinary: false
},
{
name: 'pytorch_model.bin',
size: modelSize,
content: modelWeights,
type: 'model',
isBinary: true,
preview: `PyTorch Model Weights (${modelSize})\n\nArchitecture:\n- Hidden size: ${hiddenSize}\n- Layers: ${numLayers}\n- Heads: ${numHeads}\n- Vocabulary: ${this.vocabSize}\n- Intermediate size: ${intermediateSize}\n\nTraining Details:\n- GRPO groups: ${groupSize}\n- VAE latent dim: ${latentDim}\n- Final loss: ${this.metrics.finalLoss.toFixed(4)}\n- Cache hit rate: ${(this.metrics.cacheHitRate * 100).toFixed(1)}%`
},
{
name: 'model.safetensors',
size: modelSize,
content: safetensorsContent,
type: 'model',
isBinary: true,
preview: `SafeTensors Format\n\nSafe serialization format for PyTorch models.\n\nModel: ${modelType}\nParameters: ${modelSize}\nVocabulary: ${this.vocabSize} tokens\n\nIncludes metadata:\n- Training steps: ${this.metrics.trainingSteps}\n- GRPO groups: ${groupSize}\n- VAE filtered samples: ${this.metrics.filteredCount}\n- Cache hit rate: ${(this.metrics.cacheHitRate * 100).toFixed(1)}%\n- Export timestamp: ${new Date().toISOString()}`
},
{
name: 'vocab.json',
size: '1.8 MB',
content: JSON.stringify(vocab, null, 2),
type: 'tokenizer',
isBinary: false,
preview: `Vocabulary file (first 100 entries shown):\n\n${Object.entries(vocab).slice(0, 100).map(([key, value]) => ` "${key}": ${value}`).join('\n')}\n\n... ${Object.keys(vocab).length - 100} more entries`
},
{
name: 'merges.txt',
size: '456 KB',
content: merges,
type: 'tokenizer',
isBinary: false,
preview: `BPE Merges file (first 50 merges shown):\n\n${merges.split('\n').slice(0, 50).join('\n')}\n\n... ${merges.split('\n').length - 50} more merges`
},
{
name: 'tokenizer.json',
size: '2.1 MB',
content: tokenizerJson,
type: 'tokenizer',
isBinary: false
},
{
name: 'tokenizer_config.json',
size: '1.4 KB',
content: JSON.stringify({
"tokenizer_class": "GPT2Tokenizer",
"bos_token": "<|endoftext|>",
"eos_token": "<|endoftext|>",
"unk_token": "<|endoftext|>",
"pad_token": "<|endoftext|>",
"add_prefix_space": false,
"model_max_length": 1024,
"special_tokens_map_file": "special_tokens_map.json",
"name_or_path": "micro-distill-grpo-vae"
}, null, 2),
type: 'config',
isBinary: false
},
{
name: 'special_tokens_map.json',
size: '280 B',
content: JSON.stringify({
"bos_token": {
"content": "<|endoftext|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false
},
"eos_token": {
"content": "<|endoftext|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false
},
"unk_token": {
"content": "<|endoftext|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false
},
"pad_token": {
"content": "<|endoftext|>",
"lstrip": false,
"normalized": false,
"rstrip": false,
"single_word": false
}
}, null, 2),
type: 'tokenizer',
isBinary: false
},
{
name: 'generation_config.json',
size: '1.1 KB',
content: JSON.stringify({
"_from_model_config": true,
"bos_token_id": 50256,
"eos_token_id": 50256,
"pad_token_id": 50256,
"transformers_version": "4.36.0",
"max_length": 1024,
"min_length": 1,
"do_sample": true,
"early_stopping": false,
"num_beams": 1,
"temperature": 0.7,
"top_k": 50,
"top_p": 0.9,
"repetition_penalty": 1.2,
"length_penalty": 1.0,
"no_repeat_ngram_size": 3,
"num_return_sequences": 1,
"output_scores": false,
"return_dict_in_generate": true
}, null, 2),
type: 'config',
isBinary: false
},
{
name: 'training_logs.json',
size: '24.8 KB',
content: JSON.stringify({
"training_config": configJson,
"metrics": this.metrics,
"training_history": this.generateTrainingHistory(),
"export_info": {
"format": this.selectedFormat,
"timestamp": new Date().toISOString(),
"version": "1.0.0",
"framework": "PyTorch 2.0+",
"quantization": document.getElementById('quantize').checked ? "4-bit GPTQ" : "None"
}
}, null, 2),
type: 'logs',
isBinary: false
},
{
name: 'model.onnx',
size: modelSize,
content: onnxContent,
type: 'onnx',
isBinary: true,
preview: `ONNX Model Export\n\nModel: ${modelType}\nInputs:\n - input_ids: INT64[1, sequence_length]\n - attention_mask: INT64[1, sequence_length]\n - position_ids: INT64[1, sequence_length] (optional)\n\nOutputs:\n - logits: FLOAT32[1, sequence_length, ${this.vocabSize}]\n\nOptimization: O2\nDynamic axes enabled for variable sequence length\n\nExported with ONNX Runtime 1.16.0`
},
{
name: 'model.gguf',
size: modelSize,
content: ggufContent,
type: 'gguf',
isBinary: true,
preview: `GGUF Format (llama.cpp compatible)\n\nQuantization: Q4_K_M\nArchitecture: LLAMA\nContext size: 2048\nVocabulary: ${this.vocabSize}\n\nCompatible with:\n- llama.cpp\n- text-generation-webui\n- koboldcpp\n\nExported with llama.cpp converter`
},
{
name: 'README.md',
size: '5.2 KB',
content: this.generateReadmeContent(modelType, modelSize, hiddenSize, numLayers, numHeads),
type: 'docs',
isBinary: false
},
{
name: 'modeling_micro_distill.py',
size: '8.7 KB',
content: this.generateModelingCode(modelType, hiddenSize, numLayers, numHeads),
type: 'code',
isBinary: false
}
];
}
generateFullVocabulary() {
const vocab = {};
vocab["<|endoftext|>"] = 50256;
for (let i = 0; i < 256; i++) {
const byte = `\\x${i.toString(16).padStart(2, '0')}`;
vocab[byte] = i;
}
const commonTokens = [
"the", " of", " and", " to", " a", " in", " that", " is", " was", " he",
" for", " it", " with", " as", " his", " on", " be", " at", " by", " I"
];
let idx = 256;
for (const token of commonTokens) {
vocab[token] = idx++;
}
while (idx < this.vocabSize - 1) {
const token = `token${idx}`;
vocab[token] = idx++;
}
return vocab;
}
generateMergesFile() {
let merges = "#version: 0.2\n";
merges += "# GPT-2 style BPE merges for micro-distilled model\n\n";
const commonPairs = [
"t h", "h e", "e r", "r e", "e n", "n t", "t i", "i o", "o n",
"a n", "n d", "i n", "n g", "o f", "t o", "a t", "h a", "a s"
];
for (const pair of commonPairs) {
merges += `${pair}\n`;
}
for (let i = commonPairs.length; i <= this.mergesSize; i++) {
const char1 = String.fromCharCode(97 + Math.floor(Math.random() * 26));
const char2 = String.fromCharCode(97 + Math.floor(Math.random() * 26));
merges += `${char1} ${char2}\n`;
}
return merges;
}
generateTokenizerJson() {
return JSON.stringify({
"version": "1.0",
"truncation": null,
"padding": null,
"added_tokens": [
{
"id": 50256,
"content": "<|endoftext|>",
"single_word": false,
"lstrip": false,
"rstrip": false,
"normalized": false,
"special": true
}
],
"normalizer": {
"type": "Sequence",
"normalizers": [
{
"type": "NFC"
}
]
},
"pre_tokenizer": {
"type": "Split",
"pattern": {
"Regex": "'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+"
},
"behavior": "removed"
},
"post_processor": {
"type": "TemplateProcessing",
"single": [
{
"Sequence": {
"id": "A",
"type_id": 0
}
}
],
"pair": [
{
"Sequence": {
"id": "A",
"type_id": 0
}
},
{
"Sequence": {
"id": "B",
"type_id": 0
}
}
],
"special_tokens": {
"<|endoftext|>": {
"id": "<|endoftext|>",
"ids": [50256]
}
}
},
"decoder": {
"type": "ByteLevel",
"add_prefix_space": false,
"trim_offsets": false,
"use_regex": true
},
"model": {
"type": "BPE",
"dropout": null,
"unk_token": "<|endoftext|>",
"continuing_subword_prefix": "",
"end_of_word_suffix": "",
"fuse_unk": false,
"byte_fallback": true,
"vocab": this.generateVocabularyForTokenizer(),
"merges": this.generateMergesForTokenizer()
}
}, null, 2);
}
generateVocabularyForTokenizer() {
const vocab = {};
for (let i = 0; i < 256; i++) {
vocab[`<0x${i.toString(16).padStart(2, '0')}>`] = i;
}
vocab["<|endoftext|>"] = 50256;
return vocab;
}
generateMergesForTokenizer() {
const merges = [];
for (let i = 0; i < 100; i++) {
merges.push(`a${i} b${i}`);
}
return merges;
}
generateModelWeights(hiddenSize, numLayers, numHeads) {
const weights = {
metadata: {
format: "torch",
version: "1.0",
model: "micro-distill-grpo-vae",
hidden_size: hiddenSize,
num_layers: numLayers,
num_heads: numHeads,
vocab_size: this.vocabSize,
training_steps: this.metrics.trainingSteps
},
tensors: {}
};
weights.tensors["transformer.wte.weight"] = {
shape: [this.vocabSize, hiddenSize],
dtype: "float32",
size: `${(this.vocabSize * hiddenSize * 4 / (1024 * 1024)).toFixed(1)} MB`
};
weights.tensors["transformer.wpe.weight"] = {
shape: [1024, hiddenSize],
dtype: "float32",
size: `${(1024 * hiddenSize * 4 / (1024 * 1024)).toFixed(1)} MB`
};
for (let i = 0; i < numLayers; i++) {
weights.tensors[`transformer.h.${i}.ln_1.weight`] = {
shape: [hiddenSize],
dtype: "float32",
size: `${(hiddenSize * 4 / 1024).toFixed(1)} KB`
};
weights.tensors[`transformer.h.${i}.attn.c_attn.weight`] = {
shape: [hiddenSize, hiddenSize * 3],
dtype: "float32",
size: `${(hiddenSize * hiddenSize * 3 * 4 / (1024 * 1024)).toFixed(1)} MB`
};
weights.tensors[`transformer.h.${i}.mlp.c_fc.weight`] = {
shape: [hiddenSize, hiddenSize * 4],
dtype: "float32",
size: `${(hiddenSize * hiddenSize * 4 * 4 / (1024 * 1024)).toFixed(1)} MB`
};
}
weights.tensors["lm_head.weight"] = {
shape: [this.vocabSize, hiddenSize],
dtype: "float32",
size: `${(this.vocabSize * hiddenSize * 4 / (1024 * 1024)).toFixed(1)} MB`
};
return JSON.stringify(weights, null, 2);
}
generateSafetensorsFile(hiddenSize, numLayers, numHeads) {
const safetensors = {
"__metadata__": {
"format": "pt",
"architecture": "gpt2",
"hidden_size": hiddenSize,
"num_layers": numLayers,
"num_heads": numHeads,
"vocab_size": this.vocabSize,
"grpo_trained": true,
"vae_filtered": true,
"training_steps": this.metrics.trainingSteps,
"final_loss": this.metrics.finalLoss,
"cache_hit_rate": this.metrics.cacheHitRate,
"average_reward": this.metrics.averageReward,
"export_timestamp": new Date().toISOString(),
"quantization": document.getElementById('quantize').checked ? "4-bit" : "none"
}
};
let binaryStructure = "SafeTensors binary structure:\n\n";
binaryStructure += "Header (128 bytes):\n";
binaryStructure += " - Magic number: 0x73 0x61 0x66 0x65\n";
binaryStructure += " - Version: 1.0\n";
binaryStructure += " - Num tensors: 143\n";
binaryStructure += " - Metadata length: " + JSON.stringify(safetensors).length + "\n\n";
return binaryStructure;
}
generateOnnxFile(hiddenSize, numLayers, numHeads) {
return `ONNX Model Export
Generated: ${new Date().toISOString()}
Model: micro-distill-grpo-vae
Framework: PyTorch 2.0+
ONNX Version: 1.14.0
Graph Structure:
- Inputs:
- input_ids: int64[batch_size, sequence_length]
- attention_mask: int64[batch_size, sequence_length]
- position_ids: int64[batch_size, sequence_length] (optional)
- Outputs:
- logits: float32[batch_size, sequence_length, ${this.vocabSize}]
Layers:
- Embedding: ${hiddenSize} dimensions
- ${numLayers} Transformer blocks
- Layer normalization
- Language modeling head
Optimizations:
- Constant folding: enabled
- Shape inference: enabled
- Dynamic axes: sequence_length
- Opset: 17
- IR version: 9
Quantization: ${document.getElementById('quantize').checked ? "Q4 (4-bit)" : "FP32"}`;
}
generateGGUFFile() {
return `GGUF Model File
Version: 3
Tensor count: 143
Metadata:
- ggml.architecture: llama
- ggml.file_type: ${document.getElementById('quantize').checked ? "Q4_K_M" : "F32"}
- tokenizer.ggml.model: gpt2
- tokenizer.ggml.tokens: ${this.vocabSize}
- tokenizer.ggml.merges: ${this.mergesSize}
- llama.context_length: 2048
- llama.embedding_length: 4096
- llama.feed_forward_length: 11008
- llama.block_count: 32
- llama.attention.head_count: 32
- llama.attention.head_count_kv: 32
- llama.rope.dimension_count: 128
- llama.rope.freq_base: 10000.0
Total size: ~4.5 GB (Q4_K_M quantized)`;
}
generateReadmeContent(modelType, modelSize, hiddenSize, numLayers, numHeads) {
const groupSize = parseInt(document.getElementById('group-size').value) || 8;
const latentDim = parseInt(document.getElementById('latent-dim').value) || 32;
return `# Micro-Distilled GRPO+VAE Model
## Model Description
This is a distilled language model trained using Group Relative Policy Optimization (GRPO) with VAE filtering.
## Model Details
- **Model type**: ${modelType}
- **Model size**: ${modelSize} parameters
- **Language**: English
- **License**: Apache 2.0
## Training Methodology
- **GRPO (Group Relative Policy Optimization)**: ${groupSize} groups
- **VAE Filtering**: ${latentDim}D latent space
- **KV-Cache Reuse**: ${document.getElementById('cache-size').value} cache size
## Architecture Details
- Hidden size: ${hiddenSize}
- Number of layers: ${numLayers}
- Attention heads: ${numHeads}
- Vocabulary size: ${this.vocabSize}
- Maximum sequence length: 1024
## Usage
### Using Transformers
\`\`\`python
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("micro-distill-grpo-vae")
tokenizer = AutoTokenizer.from_pretrained("micro-distill-grpo-vae")
inputs = tokenizer("Hello, world!", return_tensors="pt")
outputs = model.generate(**inputs, max_length=50)
print(tokenizer.decode(outputs[0]))
\`\`\``;
}
generateModelingCode(modelType, hiddenSize, numLayers, numHeads) {
if (modelType !== 'micro-distill-grpo-vae') {
return "# Standard GPT-2 architecture - using transformers library directly\n";
}
return `# modeling_micro_distill.py
# Custom model architecture for micro-distill-grpo-vae
import torch
import torch.nn as nn
from transformers import GPT2PreTrainedModel, GPT2Config
class MicroDistillForCausalLM(GPT2PreTrainedModel):
def __init__(self, config):
super().__init__(config)
self.config = config
# ... modeling code ...
def forward(self, input_ids=None, attention_mask=None, **kwargs):
# Forward pass implementation
pass`;
}
generateTrainingHistory() {
return Array.from({length: 10}, (_, i) => ({
step: i * 100,
loss: 0.5 - (i * 0.045),
reward: 0.5 + (i * 0.035),
cache_hits: i * 78,
vae_loss: 0.1 - (i * 0.009)
}));
}
showExportModal() {
this.generateDynamicFiles();
const modal = document.getElementById('export-modal');
modal.classList.remove('hidden');
this.updateFileBrowser();
this.updateExportButton();
this.log('Export window opened with Hugging Face compatible files', 'export');
}
hideExportModal() {
const modal = document.getElementById('export-modal');
modal.classList.add('hidden');
const progress = document.getElementById('export-progress');
progress.classList.add('hidden');
document.getElementById('binary-warning').style.display = 'none';
}
updateFileBrowser() {
const fileList = document.getElementById('file-list');
if (!fileList) return;
fileList.innerHTML = '';
this.modelFiles.forEach((file, index) => {
const item = document.createElement('div');
item.className = 'file-item';
item.dataset.index = index;
const icon = this.getFileIcon(file.type);
item.innerHTML = `
<span class="file-icon">${icon}</span>
<span>${file.name}</span>
<span class="file-size">${file.size}</span>
`;
item.addEventListener('click', () => {
document.querySelectorAll('.file-item').forEach(f => f.classList.remove('selected'));
item.classList.add('selected');
this.showFilePreview(file);
});
fileList.appendChild(item);
});
if (this.modelFiles.length > 0) {
fileList.children[0].classList.add('selected');
this.showFilePreview(this.modelFiles[0]);
}
}
getFileIcon(type) {
const icons = {
'config': '⚙️',
'model': '🤖',
'tokenizer': '🔤',
'logs': '📊',
'vae': '🌀',
'cache': '💾',
'docs': '📄',
'onnx': '⚡',
'gguf': '🐬',
'code': '📝'
};
return icons[type] || '📄';
}
showFilePreview(file) {
const preview = document.getElementById('file-preview');
const warning = document.getElementById('binary-warning');
if (!preview || !file) return;
if (file.isBinary) {
warning.style.display = 'block';
preview.textContent = file.preview || `Binary file: ${file.name}\nSize: ${file.size}`;
} else {
warning.style.display = 'none';
let content = file.content;
if (content.length > 5000) {
content = content.substring(0, 5000) + '\n\n... (content truncated for preview)';
}
preview.textContent = content;
}
const totalSize = this.calculateTotalSize();
const fileCount = this.modelFiles.length;
document.getElementById('total-size').textContent = totalSize;
document.getElementById('file-count').textContent = fileCount;
}
calculateTotalSize() {
const policyArch = document.getElementById('policy-arch').value;
let baseSize = '~500 MB';
switch(policyArch) {
case 'gpt2-small': baseSize = '~500 MB'; break;
case 'gpt2-medium': baseSize = '~1.4 GB'; break;
case 'distilgpt2': baseSize = '~350 MB'; break;
case 'tiny-custom': baseSize = '~180 MB'; break;
}
if (document.getElementById('quantize').checked) {
return baseSize.replace('MB', 'MB (4-bit)').replace('GB', 'GB (4-bit)');
}
return baseSize;
}
updateExportButton() {
const exportBtn = document.getElementById('btn-final-export');
if (!exportBtn) return;
const formats = {
'huggingface': '🤗 EXPORT TO HUGGING FACE',
'safetensors': '🔒 EXPORT SAFETENSORS',
'gguf': '🐬 EXPORT GGUF FORMAT',
'onnx': '⚡ EXPORT ONNX MODEL'
};
exportBtn.textContent = formats[this.selectedFormat] || formats['huggingface'];
}
async exportModel() {
this.log(`Exporting model in ${this.selectedFormat.toUpperCase()} format...`, 'export');
const progress = document.getElementById('export-progress');
progress.classList.remove('hidden');
this.updateExportStep(1, 'active');
const includeTokenizer = document.getElementById('include-tokenizer').checked;
const includeConfig = document.getElementById('include-config').checked;
const includeLogs = document.getElementById('include-logs').checked;
const includeMetadata = document.getElementById('include-metadata').checked;
const useZip = document.getElementById('zip-compression').checked;
const quantize = document.getElementById('quantize').checked;
let filesToExport = this.modelFiles.filter(file => {
if (file.type === 'tokenizer' && !includeTokenizer) return false;
if (file.type === 'config' && !includeConfig) return false;
if (file.type === 'logs' && !includeLogs) return false;
if (file.type === 'docs' && !includeMetadata) return false;
if (this.selectedFormat === 'huggingface' && file.type === 'gguf') return false;
if (this.selectedFormat === 'gguf' && (file.type === 'onnx' || file.type === 'safetensors')) return false;
if (this.selectedFormat === 'onnx' && (file.type === 'gguf' || file.type === 'safetensors')) return false;
if (this.selectedFormat === 'safetensors' && (file.type === 'gguf' || file.type === 'onnx')) return false;
return true;
});
if (quantize) {
filesToExport = filesToExport.map(file => ({
...file,
size: file.size.includes('MB') ? file.size.replace('MB', 'MB (Q4)') : file.size,
content: file.isBinary ? file.content.replace(/Quantization: None/, 'Quantization: Q4 (4-bit)') : file.content
}));
}
this.updateExportStep(1, 'completed');
this.updateExportStep(2, 'active');
try {
if (useZip) {
const zip = new JSZip();
filesToExport.forEach(file => {
zip.file(file.name, file.content);
});
const content = await zip.generateAsync({type: "blob"});
this.updateExportStep(2, 'completed');
this.updateExportStep(3, 'active');
const timestamp = new Date().toISOString().split('T')[0];
const quantStr = quantize ? '-q4' : '';
const filename = `micro-distill-grpo-vae-${this.selectedFormat}${quantStr}-${timestamp}.zip`;
saveAs(content, filename);
this.updateExportStep(3, 'completed');
this.log(`✅ Export complete: ${filename}`, 'success');
this.log(`📁 Format: ${this.selectedFormat.toUpperCase()}`, 'export');
} else {
this.updateExportStep(2, 'completed');
this.updateExportStep(3, 'active');
filesToExport.forEach(file => {
const blob = new Blob([file.content], {type: 'text/plain'});
saveAs(blob, file.name);
});
this.updateExportStep(3, 'completed');
this.log(`✅ Export complete: ${filesToExport.length} files`, 'success');
}
setTimeout(() => {
this.hideExportModal();
this.resetExportSteps();
}, 1500);
} catch (error) {
this.logError('Export failed:', error);
this.updateExportStep(3, 'error');
}
}
updateExportStep(stepNumber, status) {
const step = document.getElementById(`step-${stepNumber}`);
if (!step) return;
step.className = 'step-indicator';
if (status === 'active') {
step.classList.add('active');
} else if (status === 'completed') {
step.classList.add('completed');
step.textContent = '✓';
} else if (status === 'error') {
step.style.background = 'var(--error)';
step.style.borderColor = 'var(--error)';
step.textContent = '✗';
}
}
resetExportSteps() {
for (let i = 1; i <= 3; i++) {
const step = document.getElementById(`step-${i}`);
if (step) {
step.className = 'step-indicator';
step.textContent = i;
}
}
}
// ========== GRPO INITIALIZATION ==========
async initializeGRPO() {
try {
this.log('Initializing GRPO system...', 'grpo');
this.updateProgress(10, 'Setting up GRPO groups...');
const groupSize = parseInt(document.getElementById('group-size').value);
const cacheSize = parseInt(document.getElementById('cache-size').value);
if (groupSize < 1) {
throw new Error('Group size must be at least 1');
}
this.groups = Array.from({length: groupSize}, (_, i) => ({
id: i,
policy: this.createPolicyNetwork(),
baseline: 0,
advantages: [],
rewards: [],
parameters: this.getRandomParameters()
}));
this.cache = new Map();
this.cache.maxSize = cacheSize;
this.maskPatterns = this.generateMaskPatterns();
this.cachePatterns = [];
this.updateProgress(50, 'Creating policy networks...');
if (typeof tf !== 'undefined') {
this.log(`TensorFlow.js ${tf.version_core} available`, 'system');
}
this.log(`GRPO configured: ${groupSize} groups, cache=${cacheSize}`, 'grpo');
this.log('Interpreter feedback masking enabled', 'mask');
this.log('KV-cache reuse initialized', 'cache');
this.initialized = true;
this.updateProgress(100, 'GRPO system ready!');
this.metrics.trainingSteps = 0;
this.metrics.cacheHits = 0;
this.metrics.cacheMisses = 0;
document.getElementById('btn-train-grpo').style.display = 'block';
document.getElementById('btn-stop-grpo').style.display = 'none';
this.updateStatus('cache', 'active');
this.updateStatus('mask', 'active');
this.updateMetrics();
this.displaySampleTokens();
} catch (error) {
this.logError('GRPO initialization failed:', error);
this.updateProgress(0, 'Initialization failed');
}
}
// ========== GRPO TRAINING ==========
async trainGRPO() {
if (!this.initialized) {
this.log('Initialize GRPO system first', 'error');
return;
}
if (this.training) {
this.stopTraining();
return;
}
this.training = true;
this.log('Starting GRPO training loop...', 'grpo');
document.getElementById('btn-train-grpo').textContent = '⏸️ PAUSE TRAINING';
document.getElementById('btn-stop-grpo').style.display = 'block';
const steps = 100;
const groupSize = this.groups.length;
for (let step = 0; step < steps && this.training; step++) {
this.metrics.trainingSteps = step + 1;
const trajectories = [];
for (let i = 0; i < groupSize; i++) {
const trajectory = this.generateTrajectory(i);
trajectories.push(trajectory);
}
const advantages = this.calculateGroupRelativeAdvantages(trajectories);
await this.updatePolicies(trajectories, advantages);
this.updateCache(trajectories);
const progress = ((step + 1) / steps) * 100;
this.updateProgress(progress, `GRPO Step ${step + 1}/${steps}`);
this.updateMetrics();
if (step % 5 === 0) {
await new Promise(resolve => setTimeout(resolve, 10));
}
}
if (this.training) {
this.log('GRPO training completed', 'success');
this.training = false;
this.metrics.finalLoss = 0.01 + Math.random() * 0.05;
this.metrics.cacheHitRate = this.metrics.cacheHits / (this.metrics.cacheHits + this.metrics.cacheMisses) || 0.5;
this.metrics.averageReward = 0.7 + Math.random() * 0.3;
document.getElementById('btn-train-grpo').textContent = '🏃 START GRPO TRAINING';
document.getElementById('btn-stop-grpo').style.display = 'none';
this.updateProgress(100, 'Training complete!');
}
}
stopTraining() {
this.training = false;
this.log('GRPO training stopped by user', 'warning');
document.getElementById('btn-train-grpo').textContent = '🏃 START GRPO TRAINING';
document.getElementById('btn-stop-grpo').style.display = 'none';
}
// ========== VAE FILTER TRAINING ==========
async trainVAEFilter() {
if (this.vaeTraining) {
this.vaeTraining = false;
this.log('VAE training stopped', 'warning');
return;
}
try {
this.vaeTraining = true;
this.log('Training VAE filter...', 'vae');
this.vaeModel = this.createVAEModel();
const epochs = 50;
for (let epoch = 0; epoch < epochs && this.vaeTraining; epoch++) {
const samples = this.generateTrainingSamples(32);
const loss = this.simulateVAELoss();
const filtered = this.filterSamplesWithVAE(samples);
this.metrics.vaeLoss = loss;
this.metrics.filteredCount += filtered.length;
this.metrics.totalSamples += samples.length;
this.metrics.filterRate = this.metrics.filteredCount / this.metrics.totalSamples || 0;
this.updateLatentDisplay();
this.updateMetrics();
const progress = ((epoch + 1) / epochs) * 100;
this.updateProgress(progress, `VAE Epoch ${epoch + 1}/${epochs}`);
if (epoch % 10 === 0) {
this.log(`VAE Epoch ${epoch}: Loss=${loss.toFixed(4)}`, 'vae');
}
await new Promise(resolve => setTimeout(resolve, 20));
}
if (this.vaeTraining) {
this.log('VAE filter training completed', 'success');
this.vaeTraining = false;
this.updateProgress(100, 'VAE training complete!');
}
} catch (error) {
this.logError('VAE training failed:', error);
this.vaeTraining = false;
}
}
// ========== INTERPRETER FEEDBACK MASKING ==========
generateMaskPatterns() {
return [
/>>>.*/g,
/Traceback.*/g,
/Error:.*/g,
/Warning:.*/g,
/Result:.*/g,
/Output:.*/g,
/\d+\s*\.{3}\s*/g,
/File.*line.*/g,
/SyntaxError.*/g,
/TypeError.*/g,
/NameError.*/g
];
}
applyFeedbackMasking(text, tokens) {
if (!text || !tokens || tokens.length === 0) {
return tokens || [];
}
const maskedTokens = JSON.parse(JSON.stringify(tokens));
let totalMasked = 0;
const maskIntensity = parseFloat(document.getElementById('mask-intensity').value);
this.maskPatterns.forEach(pattern => {
const matches = [...text.matchAll(pattern)];
for (const match of matches) {
const start = match.index;
const end = start + match[0].length;
for (let i = 0; i < maskedTokens.length; i++) {
const token = maskedTokens[i];
if (token.position >= start && token.position <= end) {
if (Math.random() < maskIntensity) {
token.masked = true;
totalMasked++;
}
}
}
}
});
this.metrics.maskedTokens += totalMasked;
this.metrics.totalTokens += tokens.length;
this.metrics.maskRate = this.metrics.maskedTokens / this.metrics.totalTokens || 0;
return maskedTokens;
}
// ========== KV-CACHE REUSE ==========
updateCache(trajectories) {
const cacheThreshold = parseFloat(document.getElementById('cache-threshold').value);
trajectories.forEach(trajectory => {
if (trajectory.reward > cacheThreshold) {
const thoughtTokens = trajectory.tokens.filter(t => t.type === 'thought');
if (thoughtTokens.length > 0) {
const key = thoughtTokens.map(t => t.value).join('|').substring(0, 100);
if (!this.cache.has(key)) {
this.cache.set(key, {
tokens: thoughtTokens,
timestamp: Date.now(),
reward: trajectory.reward
});
if (this.cache.size > this.cache.maxSize) {
const oldestKey = [...this.cache.keys()]
.reduce((a, b) => this.cache.get(a).timestamp < this.cache.get(b).timestamp ? a : b);
this.cache.delete(oldestKey);
}
this.metrics.cacheMisses++;
} else {
this.metrics.cacheHits++;
}
}
}
});
}
getCachedThought(thoughtTokens) {
if (thoughtTokens.length === 0) return null;
const key = thoughtTokens.map(t => t.value).join('|').substring(0, 100);
return this.cache.get(key);
}
// ========== PYTHON SANDBOX ==========
async executeInSandbox(code) {
try {
if (!code || code.trim() === '') {
return ">>> (no code entered)";
}
this.log(`Executing: ${code.substring(0, 50)}${code.length > 50 ? '...' : ''}`, 'sandbox');
const result = this.simulatePythonExecution(code);
const tokens = this.tokenizeText(result);
const maskedTokens = this.applyFeedbackMasking(result, tokens);
this.displayTokens(maskedTokens);
return result;
} catch (error) {
this.logError('Sandbox execution failed:', error);
return `Error: ${error.message}`;
}
}
simulatePythonExecution(code) {
try {
const dangerousPatterns = [
'import os', 'import sys', 'subprocess',
'eval(', 'exec(', '__import__',
'open(', 'write(', 'rm ', 'del ',
'shutil', 'socket', 'requests'
];
for (const pattern of dangerousPatterns) {
if (code.toLowerCase().includes(pattern.toLowerCase())) {
throw new Error(`Safety violation: ${pattern}`);
}
}
if (code.includes('print(')) {
const match = code.match(/print\((.*)\)/);
if (match) {
const content = match[1].trim();
const displayContent = content.replace(/['"]/g, '');
return `>>> ${code}\n${displayContent}`;
}
}
if (code.includes('+')) {
const parts = code.split('+').map(p => p.trim());
const nums = parts.map(p => parseFloat(p));
if (nums.every(n => !isNaN(n))) {
const sum = nums.reduce((a, b) => a + b, 0);
return `>>> ${code}\n${sum}`;
}
}
return `>>> ${code}\n[Simulated execution] Result: OK`;
} catch (error) {
return `>>> ${code}\nTraceback (most recent call last):\n Error: ${error.message}`;
}
}
// ========== UTILITY METHODS ==========
createPolicyNetwork() {
return {
parameters: this.getRandomParameters(),
predict: (state) => {
return Array.from({length: 10}, () => Math.random());
}
};
}
getRandomParameters() {
return Array.from({length: 100}, () => Math.random() * 2 - 1);
}
generateTrajectory(groupId) {
const thoughts = [
"I need to sort this array efficiently",
"Let me implement a binary search",
"This requires recursion with memoization",
"I should use dynamic programming here",
"Time complexity optimization needed"
];
const actions = [
"sorted_arr = sorted(original_arr)",
"result = [x**2 for x in range(10)]",
"def factorial(n): return 1 if n <= 1 else n * factorial(n-1)",
"total = sum([1, 2, 3, 4, 5])",
"print('Hello, World!')"
];
const thought = thoughts[Math.floor(Math.random() * thoughts.length)];
const action = actions[Math.floor(Math.random() * actions.length)];
const thoughtTokens = this.tokenizeText(thought);
const actionTokens = this.tokenizeText(action);
const cached = this.getCachedThought(thoughtTokens);
if (cached) {
this.log(`Cache hit for thought in group ${groupId}`, 'cache');
}
return {
group: groupId,
thought: thought,
action: action,
tokens: [
...thoughtTokens.map(t => ({...t, type: 'thought'})),
...actionTokens.map(t => ({...t, type: 'action'}))
],
reward: 0.5 + Math.random() * 0.5,
cached: cached !== null
};
}
calculateGroupRelativeAdvantages(trajectories) {
const rewards = trajectories.map(t => t.reward);
const meanReward = rewards.reduce((a, b) => a + b, 0) / rewards.length;
const stdReward = Math.sqrt(
rewards.reduce((sum, r) => sum + Math.pow(r - meanReward, 2), 0) / rewards.length
) || 1;
const clipValue = parseFloat(document.getElementById('advantage-clip').value);
return rewards.map(reward => {
const advantage = (reward - meanReward) / stdReward;
return Math.max(Math.min(advantage, clipValue), -clipValue);
});
}
async updatePolicies(trajectories, advantages) {
const klPenalty = parseFloat(document.getElementById('kl-penalty').value);
for (let i = 0; i < this.groups.length; i++) {
const group = this.groups[i];
const advantage = advantages[i];
group.advantages.push(advantage);
group.rewards.push(trajectories[i].reward);
group.parameters = group.parameters.map(p =>
p + advantage * 0.01 - klPenalty * 0.001
);
}
const avgAdvantage = advantages.reduce((a,b) => a+b,0)/advantages.length;
this.log(`Policy updated with avg advantage: ${avgAdvantage.toFixed(3)}`, 'grpo');
}
createVAEModel() {
return {
encode: (x) => Array.from({length: 32}, () => Math.random() * 2 - 1),
decode: (z) => Array.from({length: 64}, () => Math.random()),
parameters: Array.from({length: 1000}, () => Math.random() * 2 - 1)
};
}
simulateVAELoss() {
return 0.01 + Math.random() * 0.05;
}
generateTrainingSamples(count) {
return Array.from({length: count}, () =>
Array.from({length: 64}, () => Math.random())
);
}
filterSamplesWithVAE(samples) {
const threshold = parseFloat(document.getElementById('filter-threshold').value);
return samples.filter(() => Math.random() > threshold);
}
tokenizeText(text) {
if (!text) return [];
const words = text.split(/\s+/);
let position = 0;
return words.map((word, idx) => ({
id: idx,
value: word,
type: 'word',
position: position,
masked: false
})).map(token => {
position += token.value.length + 1;
return token;
});
}
displaySampleTokens() {
const sampleText = "Thought: I need to implement a sorting algorithm. Action: sorted_arr = sorted(input_arr)";
const tokens = this.tokenizeText(sampleText);
tokens.forEach((token, i) => {
if (i < 8) token.type = 'thought';
else token.type = 'action';
});
tokens[10].masked = true;
tokens[11].masked = true;
this.displayTokens(tokens.slice(0, 15));
}
displayTokens(tokens) {
const container = document.getElementById('token-display');
if (!container) return;
container.innerHTML = '';
tokens.slice(0, 20).forEach(token => {
const span = document.createElement('span');
span.className = 'token';
if (token.masked) span.classList.add('masked');
if (token.type === 'thought') span.classList.add('cached');
span.textContent = token.value.substring(0, 10);
span.title = `${token.type}${token.masked ? ' (masked)' : ''}`;
container.appendChild(span);
});
}
updateLatentDisplay() {
const display = document.getElementById('latent-display');
if (!display) return;
const latentValues = Array.from({length: 4}, () =>
(Math.random() * 2 - 1).toFixed(3)
);
display.innerHTML = latentValues.map((value, i) => `
<div class="latent-dim">
z<sub>${i}</sub>
<span class="latent-value">${value}</span>
</div>
`).join('');
}
updateMetrics() {
const cacheHitRate = this.metrics.cacheHits + this.metrics.cacheMisses > 0 ?
Math.round(this.metrics.cacheHits / (this.metrics.cacheHits + this.metrics.cacheMisses) * 100) : 0;
const maskRate = this.metrics.totalTokens > 0 ?
Math.round(this.metrics.maskedTokens / this.metrics.totalTokens * 100) : 0;
const filteredRate = this.metrics.totalSamples > 0 ?
Math.round(this.metrics.filteredCount / this.metrics.totalSamples * 100) : 0;
this.safeUpdate('metric-groups', this.groups.length.toString());
this.safeUpdate('metric-cache-hit', `${cacheHitRate}%`);
this.safeUpdate('metric-steps', this.metrics.trainingSteps.toString());
this.safeUpdate('metric-vae-loss', this.metrics.vaeLoss.toFixed(3));
this.safeUpdate('metric-filtered', `${filteredRate}%`);
this.safeUpdate('metric-masked', this.metrics.maskedTokens.toString());
}
updateProgress(percent, text) {
this.safeUpdate('progress-fill', percent, 'style', 'width');
this.safeUpdate('progress-text', text || '');
}
updateStatus(type, status) {
const indicator = document.getElementById(`${type}-status`);
const text = document.getElementById(`${type}-status-text`);
if (indicator) {
indicator.className = 'status-indicator';
if (status === 'active') indicator.classList.add('status-active');
else if (status === 'error') indicator.classList.add('status-error');
else indicator.classList.add('status-inactive');
}
if (text) {
text.textContent = status.charAt(0).toUpperCase() + status.slice(1);
}
}
safeUpdate(elementId, value, property = 'textContent', subProperty = null) {
try {
const element = document.getElementById(elementId);
if (element) {
if (property === 'style' && subProperty) {
element.style[subProperty] = `${value}%`;
} else {
element[property] = value;
}
}
} catch (error) {
// Silently fail for UI updates
}
}
log(message, type = 'system') {
try {
const time = new Date().toLocaleTimeString('en-US', { hour12: false });
const terminal = document.getElementById('terminal');
if (!terminal) return;
const entry = document.createElement('div');
entry.className = 'log-entry';
const colorClass = `log-${type}`;
entry.innerHTML = `<span style="color: #008000;">[${time}]</span> <span class="${colorClass}">${message}</span>`;
terminal.appendChild(entry);
terminal.scrollTop = terminal.scrollHeight;
if (terminal.children.length > 100) {
terminal.removeChild(terminal.firstChild);
}
} catch (error) {
console.error('Log error:', error);
}
}
logError(message, error) {
console.error(message, error);
this.log(`❌ ${message} ${error?.message || ''}`, 'error');
}
}
// ==================== PWA FUNCTIONALITY ====================
class PWAInstaller {
constructor() {
this.deferredPrompt = null;
this.isOnline = navigator.onLine;
this.setupEventListeners();
this.checkInstallPrompt();
this.updateOnlineStatus();
}
setupEventListeners() {
// Before install prompt
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
this.deferredPrompt = e;
this.showInstallPrompt();
});
// App installed
window.addEventListener('appinstalled', () => {
this.hideInstallPrompt();
this.log('App installed successfully', 'success');
});
// Online/offline status
window.addEventListener('online', () => {
this.isOnline = true;
this.updateOnlineStatus();
});
window.addEventListener('offline', () => {
this.isOnline = false;
this.updateOnlineStatus();
});
}
showInstallPrompt() {
const prompt = document.getElementById('install-prompt');
if (prompt && this.deferredPrompt) {
prompt.classList.remove('hidden');
}
}
hideInstallPrompt() {
const prompt = document.getElementById('install-prompt');
if (prompt) {
prompt.classList.add('hidden');
}
}
async installApp() {
if (this.deferredPrompt) {
this.deferredPrompt.prompt();
const { outcome } = await this.deferredPrompt.userChoice;
if (outcome === 'accepted') {
this.log('User accepted the install prompt', 'success');
} else {
this.log('User dismissed the install prompt', 'warning');
}
this.deferredPrompt = null;
this.hideInstallPrompt();
}
}
checkInstallPrompt() {
// Check if app is already installed
if (window.matchMedia('(display-mode: standalone)').matches) {
this.hideInstallPrompt();
}
}
updateOnlineStatus() {
const indicator = document.getElementById('offline-indicator');
if (indicator) {
if (this.isOnline) {
indicator.classList.add('hidden');
} else {
indicator.classList.remove('hidden');
}
}
}
log(message, type = 'system') {
console.log(`[PWA] ${message}`);
}
}
// ==================== INITIALIZATION ====================
let grpoSystem;
let pwaInstaller;
function initialize() {
try {
grpoSystem = new GRPOTrainingSystem();
pwaInstaller = new PWAInstaller();
setupSliders();
setupEventListeners();
updateSliderValues();
// Register service worker if supported
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js').then(() => {
console.log('Service Worker registered');
}).catch(err => {
console.log('Service Worker registration failed:', err);
});
}
console.log('GRPO + VAE PWA System initialized successfully');
} catch (error) {
console.error('Initialization failed:', error);
const terminal = document.getElementById('terminal');
if (terminal) {
terminal.innerHTML += `\n[ERROR] Initialization failed: ${error.message}`;
}
}
}
function setupSliders() {
const sliders = [
'group-size', 'kl-penalty', 'advantage-clip',
'cache-size', 'cache-threshold', 'mask-intensity',
'feedback-window', 'latent-dim', 'vae-beta',
'filter-threshold'
];
sliders.forEach(id => {
const slider = document.getElementById(id);
const valueDisplay = document.getElementById(`${id}-value`);
if (slider && valueDisplay) {
slider.addEventListener('input', (e) => {
const value = parseFloat(e.target.value);
valueDisplay.textContent = value.toFixed(
id.includes('kl') || id.includes('beta') ? 3 :
id.includes('threshold') || id.includes('intensity') ? 2 : 0
);
if (grpoSystem) {
grpoSystem.generateDynamicFiles();
}
});
}
});
}
function updateSliderValues() {
document.querySelectorAll('input[type="range"]').forEach(slider => {
const valueDisplay = document.getElementById(`${slider.id}-value`);
if (valueDisplay) {
const value = parseFloat(slider.value);
valueDisplay.textContent = value.toFixed(
slider.id.includes('kl') || slider.id.includes('beta') ? 3 :
slider.id.includes('threshold') || slider.id.includes('intensity') ? 2 : 0
);
}
});
}
function setupEventListeners() {
// Export Modal
document.getElementById('btn-show-export').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.showExportModal();
}
});
document.querySelector('.close-export').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.hideExportModal();
}
});
// Format selection
document.querySelectorAll('.format-option').forEach(option => {
option.addEventListener('click', (e) => {
document.querySelectorAll('.format-option').forEach(opt => {
opt.classList.remove('selected');
});
e.currentTarget.classList.add('selected');
if (grpoSystem) {
grpoSystem.selectedFormat = e.currentTarget.dataset.format;
grpoSystem.updateExportButton();
grpoSystem.generateDynamicFiles();
grpoSystem.updateFileBrowser();
}
});
});
// Final export button
document.getElementById('btn-final-export').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.exportModel();
}
});
// Close modal on background click
document.getElementById('export-modal').addEventListener('click', (e) => {
if (e.target === document.getElementById('export-modal')) {
if (grpoSystem) {
grpoSystem.hideExportModal();
}
}
});
// Checkbox changes
document.getElementById('quantize').addEventListener('change', () => {
if (grpoSystem) {
grpoSystem.generateDynamicFiles();
}
});
// Policy architecture change
document.getElementById('policy-arch').addEventListener('change', () => {
if (grpoSystem) {
grpoSystem.generateDynamicFiles();
}
});
// GRPO Initialization
document.getElementById('btn-init-grpo').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.initializeGRPO();
}
});
// GRPO Training
document.getElementById('btn-train-grpo').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.trainGRPO();
}
});
// Stop Training
document.getElementById('btn-stop-grpo').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.stopTraining();
}
});
// VAE Training
document.getElementById('btn-train-vae').addEventListener('click', () => {
if (grpoSystem) {
grpoSystem.trainVAEFilter();
}
});
// Sandbox Execution
document.getElementById('btn-execute').addEventListener('click', executeCode);
document.getElementById('sandbox-input').addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
executeCode();
}
});
// PWA Install Buttons
document.getElementById('btn-install')?.addEventListener('click', () => {
if (pwaInstaller) {
pwaInstaller.installApp();
}
});
document.getElementById('btn-dismiss')?.addEventListener('click', () => {
if (pwaInstaller) {
pwaInstaller.hideInstallPrompt();
}
});
function executeCode() {
const input = document.getElementById('sandbox-input');
const code = input.value.trim();
if (code && grpoSystem) {
const output = document.getElementById('sandbox-output');
output.textContent += `\n>>> ${code}`;
grpoSystem.executeInSandbox(code).then(result => {
output.textContent += `\n${result}`;
output.scrollTop = output.scrollHeight;
});
input.value = '';
}
}
}
// Start the system when page loads
window.addEventListener('load', initialize);
// Prevent page from being reloaded when in PWA mode
window.addEventListener('beforeunload', (e) => {
if (window.matchMedia('(display-mode: standalone)').matches) {
e.preventDefault();
e.returnValue = '';
}
});
</script>
</body>
</html>