cpu-optimization-dashboard / dashboard_simple.py
Himasree's picture
Upload 14 files
2524181 verified
Raw History Blame Contribute Delete
32.9 kB
"""
CPU Optimization ML Dashboard - Simplified Version
Lightweight, dependency-minimal dashboard for model visualization
"""
import json
import joblib
import os
import numpy as np
from pathlib import Path
# ============================================================================
# CONFIGURATION
# ============================================================================
MODELS_DIR = "models"
METRICS_DIR = "metrics"
EVAL_METRICS_DIR = f"{METRICS_DIR}/eval"
DATA_DIR = "data/processed"
# ============================================================================
# UTILITY FUNCTIONS
# ============================================================================
def load_metrics():
"""Load training and evaluation metrics"""
metrics_data = {}
# Load training metrics
train_metrics_file = f"{METRICS_DIR}/train_metrics.json"
if os.path.exists(train_metrics_file):
with open(train_metrics_file, 'r') as f:
metrics_data['train'] = json.load(f)
# Load evaluation metrics
lr_metrics_file = f"{EVAL_METRICS_DIR}/LinearRegression_metrics.json"
rf_metrics_file = f"{EVAL_METRICS_DIR}/RandomForest_metrics.json"
if os.path.exists(lr_metrics_file):
with open(lr_metrics_file, 'r') as f:
metrics_data['lr_eval'] = json.load(f)
if os.path.exists(rf_metrics_file):
with open(rf_metrics_file, 'r') as f:
metrics_data['rf_eval'] = json.load(f)
return metrics_data
def load_model(model_name):
"""Load a model from disk"""
model_path = os.path.join(MODELS_DIR, f"{model_name}.pkl")
if os.path.exists(model_path):
try:
return joblib.load(model_path)
except:
return None
return None
def get_model_info():
"""Get available models and their info"""
models = {}
try:
model_files = [f for f in os.listdir(MODELS_DIR) if f.endswith('.pkl')]
for model_file in model_files:
model_name = model_file.replace('.pkl', '')
file_path = os.path.join(MODELS_DIR, model_file)
models[model_name] = {
'path': file_path,
'file_size': os.path.getsize(file_path) / 1024 # KB
}
except:
pass
return models
def get_artifacts_info():
"""Get artifact information as formatted text"""
artifacts_text = "### Available Model Artifacts\n\n"
try:
models = get_model_info()
for model_name, info in models.items():
artifacts_text += f"**{model_name.upper()}**\n"
artifacts_text += f"- Size: {info['file_size']:.2f} KB\n"
artifacts_text += f"- Path: {info['path']}\n"
artifacts_text += f"- Status: ✓ Available\n\n"
except Exception as e:
artifacts_text += f"Error loading artifacts: {e}\n"
return artifacts_text
def format_metrics_text(metrics, model_filter=None):
"""Format metrics as text with optional model filtering"""
text = "### Model Metrics Summary\n\n"
if 'train' in metrics:
train = metrics['train']
text += "#### Training Metrics\n"
if model_filter is None or model_filter == 'Random Forest':
text += f"- Random Forest R² Score: {train.get('r2_rf', 'N/A')}\n"
text += f"- Random Forest RMSE: {train.get('rmse_rf', 'N/A')}\n"
if model_filter is None or model_filter == 'Linear Regression':
text += f"- Linear Regression R² Score: {train.get('r2_lr', 'N/A')}\n"
text += f"- Linear Regression RMSE: {train.get('rmse_lr', 'N/A')}\n"
text += "\n"
if model_filter is None or model_filter == 'Random Forest':
if 'rf_eval' in metrics:
rf = metrics['rf_eval']
text += "#### Random Forest Evaluation\n"
text += f"- R² Score: {rf.get('r2', 'N/A')}\n"
text += f"- RMSE: {rf.get('rmse', 'N/A')}\n\n"
if model_filter is None or model_filter == 'Linear Regression':
if 'lr_eval' in metrics:
lr = metrics['lr_eval']
text += "#### Linear Regression Evaluation\n"
text += f"- R² Score: {lr.get('r2', 'N/A')}\n"
text += f"- RMSE: {lr.get('rmse', 'N/A')}\n\n"
return text
def create_comparison_charts(metrics):
"""Create SVG comparison charts for R2 and RMSE"""
if not metrics:
return "", ""
# Extract values
rf_r2_train = metrics.get('train', {}).get('r2_rf', 0)
lr_r2_train = metrics.get('train', {}).get('r2_lr', 0)
rf_rmse_train = metrics.get('train', {}).get('rmse_rf', 0)
lr_rmse_train = metrics.get('train', {}).get('rmse_lr', 0)
# R² Chart (normalized to 0-1)
r2_chart = f"""
<svg width="100%" height="300" viewBox="0 0 500 300" style="background: #f5f5f5; border-radius: 8px; margin: 10px 0;">
<text x="250" y="25" font-size="18" font-weight="bold" text-anchor="middle">R² Score Comparison</text>
<!-- Y-axis labels -->
<text x="30" y="265" font-size="12">0.0</text>
<text x="30" y="185" font-size="12">0.5</text>
<text x="30" y="105" font-size="12">1.0</text>
<!-- Y-axis line -->
<line x1="40" y1="50" x2="40" y2="270" stroke="#999" stroke-width="2"/>
<!-- X-axis line -->
<line x1="40" y1="270" x2="480" y2="270" stroke="#999" stroke-width="2"/>
<!-- Random Forest bar -->
<rect x="120" y="{270 - rf_r2_train * 220}" width="80" height="{rf_r2_train * 220}" fill="#667eea" rx="5"/>
<text x="160" y="290" font-size="12" text-anchor="middle" font-weight="bold">Random Forest</text>
<text x="160" y="{270 - rf_r2_train * 220 - 10}" font-size="14" text-anchor="middle" font-weight="bold" fill="#667eea">{rf_r2_train:.4f}</text>
<!-- Linear Regression bar -->
<rect x="280" y="{270 - lr_r2_train * 220}" width="80" height="{lr_r2_train * 220}" fill="#764ba2" rx="5"/>
<text x="320" y="290" font-size="12" text-anchor="middle" font-weight="bold">Linear Regression</text>
<text x="320" y="{270 - lr_r2_train * 220 - 10}" font-size="14" text-anchor="middle" font-weight="bold" fill="#764ba2">{lr_r2_train:.4f}</text>
</svg>
"""
# RMSE Chart (inverse - lower is better, so we show as bars)
# Scale RMSE to reasonable display height (multiply by 100 for visibility)
rmse_scale = 500 if max(rf_rmse_train, lr_rmse_train) > 0 else 1
rmse_chart = f"""
<svg width="100%" height="300" viewBox="0 0 500 300" style="background: #f5f5f5; border-radius: 8px; margin: 10px 0;">
<text x="250" y="25" font-size="18" font-weight="bold" text-anchor="middle">RMSE Comparison (Lower is Better)</text>
<!-- Y-axis labels -->
<text x="25" y="265" font-size="12">0.00</text>
<text x="15" y="185" font-size="12">0.03</text>
<text x="15" y="105" font-size="12">0.06</text>
<!-- Y-axis line -->
<line x1="40" y1="50" x2="40" y2="270" stroke="#999" stroke-width="2"/>
<!-- X-axis line -->
<line x1="40" y1="270" x2="480" y2="270" stroke="#999" stroke-width="2"/>
<!-- Random Forest bar -->
<rect x="120" y="{270 - min(rf_rmse_train * rmse_scale, 220)}" width="80" height="{min(rf_rmse_train * rmse_scale, 220)}" fill="#667eea" rx="5"/>
<text x="160" y="290" font-size="12" text-anchor="middle" font-weight="bold">Random Forest</text>
<text x="160" y="{270 - min(rf_rmse_train * rmse_scale, 220) - 10}" font-size="14" text-anchor="middle" font-weight="bold" fill="#667eea">{rf_rmse_train:.4f}</text>
<!-- Linear Regression bar -->
<rect x="280" y="{270 - min(lr_rmse_train * rmse_scale, 220)}" width="80" height="{min(lr_rmse_train * rmse_scale, 220)}" fill="#764ba2" rx="5"/>
<text x="320" y="290" font-size="12" text-anchor="middle" font-weight="bold">Linear Regression</text>
<text x="320" y="{270 - min(lr_rmse_train * rmse_scale, 220) - 10}" font-size="14" text-anchor="middle" font-weight="bold" fill="#764ba2">{lr_rmse_train:.4f}</text>
</svg>
"""
return r2_chart, rmse_chart
def get_summary_info():
"""Get summary information"""
metrics = load_metrics()
summary = """
# 🚀 CPU Optimization ML Dashboard
## Overview
Real-time visualization of machine learning models for CPU usage prediction.
## Key Metrics
"""
if 'train' in metrics:
train = metrics['train']
summary += f"- **Best Model**: Random Forest\n"
summary += f"- **Best R² Score**: {train.get('r2_rf', 'N/A')} (Training)\n"
summary += f"- **Best RMSE**: {train.get('rmse_rf', 'N/A')} (Training)\n\n"
summary += """
## Available Features
### 📦 Models & Artifacts
- View loaded models and their metadata
- Monitor model file sizes
- Check artifact availability
### 📊 Metrics & Performance
- Real-time metric comparison
- R² Score analysis
- RMSE comparison
### 🔮 Make Predictions
- Test models with custom inputs
- Instant predictions
- Model selection
### ℹ️ System Information
- Dashboard configuration
- Model information
- Performance overview
## Models Available
1. **Random Forest** - Advanced ensemble method
2. **Linear Regression** - Linear baseline model
## Quick Start
```python
# Load metrics
metrics = load_metrics()
# Load a model
model = load_model('rf_model')
# Make prediction
prediction = model.predict([[0.5, 0.6, 0.7]])
```
"""
return summary
# ============================================================================
# MAIN APPLICATION
# ============================================================================
def create_html_dashboard():
"""Create an HTML-based dashboard (no Gradio)"""
metrics = load_metrics()
artifacts = get_artifacts_info()
summary = get_summary_info()
metrics_text = format_metrics_text(metrics)
r2_chart, rmse_chart = create_comparison_charts(metrics)
html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CPU Optimization Dashboard</title>
<style>
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #333;
line-height: 1.6;
}}
.container {{
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}}
header {{
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
margin-bottom: 30px;
}}
h1 {{
color: #667eea;
margin-bottom: 10px;
}}
.model-selector {{
display: flex;
gap: 15px;
margin: 20px 0;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
align-items: center;
}}
.model-selector label {{
font-weight: 600;
color: #333;
}}
.model-selector select {{
padding: 10px 15px;
border: 2px solid #667eea;
border-radius: 5px;
font-size: 14px;
cursor: pointer;
background: white;
}}
.model-selector select:hover {{
border-color: #764ba2;
}}
.tabs {{
display: flex;
gap: 10px;
margin: 20px 0;
flex-wrap: wrap;
}}
.tab-btn {{
padding: 12px 24px;
background: #667eea;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;
}}
.tab-btn:hover {{
background: #764ba2;
transform: translateY(-2px);
}}
.tab-btn.active {{
background: #764ba2;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}}
.tab-content {{
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
display: none;
}}
.tab-content.active {{
display: block;
}}
.card {{
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin: 15px 0;
border-left: 4px solid #667eea;
}}
.card h3 {{
color: #667eea;
margin-bottom: 10px;
}}
.metric {{
display: inline-block;
background: white;
padding: 20px;
margin: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
min-width: 200px;
}}
.metric-value {{
font-size: 24px;
font-weight: bold;
color: #667eea;
}}
.metric-label {{
font-size: 14px;
color: #666;
margin-top: 5px;
}}
.model-badge {{
display: inline-block;
padding: 8px 16px;
border-radius: 20px;
font-weight: 600;
font-size: 14px;
margin: 5px 0;
}}
.model-badge.rf {{
background: #667eea;
color: white;
}}
.model-badge.lr {{
background: #764ba2;
color: white;
}}
.comparison-container {{
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin: 20px 0;
}}
@media (max-width: 768px) {{
.comparison-container {{
grid-template-columns: 1fr;
}}
}}
.chart-container {{
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}}
.model-details {{
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin: 15px 0;
border-left: 4px solid #667eea;
}}
.model-details h3 {{
color: #667eea;
margin-bottom: 15px;
}}
.metric-row {{
display: flex;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid #e0e0e0;
}}
.metric-row:last-child {{
border-bottom: none;
}}
.metric-name {{
font-weight: 600;
color: #333;
}}
.metric-value-text {{
color: #667eea;
font-weight: 600;
}}
footer {{
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
margin-top: 30px;
text-align: center;
color: #666;
}}
pre {{
background: #f5f5f5;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}}
code {{
font-family: 'Courier New', monospace;
color: #d63384;
}}
.alert {{
padding: 15px;
background: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 5px;
color: #155724;
margin: 10px 0;
}}
</style>
</head>
<body>
<div class="container">
<header>
<h1>🚀 CPU Optimization ML Dashboard</h1>
<p>Real-time visualization of machine learning models for CPU usage prediction</p>
</header>
<!-- Model Selector -->
<div class="model-selector">
<label for="modelSelect">📊 Select Model to Analyze:</label>
<select id="modelSelect" onchange="updateModelView()">
<option value="">All Models (Comparison)</option>
<option value="rf">Random Forest</option>
<option value="lr">Linear Regression</option>
</select>
</div>
<div class="tabs">
<button class="tab-btn active" onclick="switchTab('overview')">📋 Overview</button>
<button class="tab-btn" onclick="switchTab('comparison')">📈 Comparison</button>
<button class="tab-btn" onclick="switchTab('metrics')">📊 Metrics</button>
<button class="tab-btn" onclick="switchTab('artifacts')">📦 Artifacts</button>
<button class="tab-btn" onclick="switchTab('info')">ℹ️ Information</button>
</div>
<!-- Overview Tab -->
<div id="overview" class="tab-content active">
<h2>Dashboard Overview</h2>
<div class="alert">✓ Dashboard is running and all models are loaded successfully</div>
<h3>Key Metrics</h3>
<div style="display: flex; flex-wrap: wrap;">
<div class="metric">
<div class="metric-label">Best Model</div>
<div class="metric-value">Random Forest</div>
</div>
<div class="metric">
<div class="metric-label">Best R² Score</div>
<div class="metric-value">0.9372</div>
</div>
<div class="metric">
<div class="metric-label">Best RMSE</div>
<div class="metric-value">0.0171</div>
</div>
<div class="metric">
<div class="metric-label">Models Available</div>
<div class="metric-value">2</div>
</div>
</div>
<div class="card">
<h3>📊 Quick Stats</h3>
<ul style="list-style: none; padding: 0;">
<li>✓ Random Forest Model: Loaded</li>
<li>✓ Linear Regression Model: Loaded</li>
<li>✓ Training Metrics: Available</li>
<li>✓ Evaluation Metrics: Available</li>
</ul>
</div>
</div>
<!-- Comparison Tab -->
<div id="comparison" class="tab-content">
<h2>Model Performance Comparison</h2>
<div class="comparison-container">
<div class="chart-container">
{r2_chart}
</div>
<div class="chart-container">
{rmse_chart}
</div>
</div>
<div class="card">
<h3>📈 Performance Analysis</h3>
<div class="metric-row">
<span class="metric-name"><span class="model-badge rf">Random Forest</span> R² Score</span>
<span class="metric-value-text">0.9372 (Training)</span>
</div>
<div class="metric-row">
<span class="metric-name"><span class="model-badge lr">Linear Regression</span> R² Score</span>
<span class="metric-value-text">0.1560 (Training)</span>
</div>
<div class="metric-row">
<span class="metric-name"><span class="model-badge rf">Random Forest</span> RMSE</span>
<span class="metric-value-text">0.0171 (Training)</span>
</div>
<div class="metric-row">
<span class="metric-name"><span class="model-badge lr">Linear Regression</span> RMSE</span>
<span class="metric-value-text">0.0626 (Training)</span>
</div>
</div>
<div class="card">
<h3>🎯 Winner Analysis</h3>
<p><strong>🏆 Best Model: Random Forest</strong></p>
<p>Random Forest outperforms Linear Regression by:</p>
<ul style="list-style: none; padding: 0; margin-top: 10px;">
<li>✓ R² Score: <strong>6x better</strong> (0.9372 vs 0.1560)</li>
<li>✓ RMSE: <strong>3.6x lower</strong> (0.0171 vs 0.0626)</li>
<li>✓ Better handles non-linear relationships</li>
<li>✓ More robust for CPU usage prediction</li>
</ul>
</div>
</div>
<!-- Metrics Tab -->
<div id="metrics" class="tab-content">
<h2>Model Metrics Detail</h2>
<div id="metricsContent">
{metrics_text.replace(chr(10), '<br>')}
</div>
<!-- Random Forest Details -->
<div id="rfDetails" class="model-details" style="display: none;">
<h3><span class="model-badge rf">Random Forest</span> Metrics</h3>
<div class="metric-row">
<span class="metric-name">Training R² Score:</span>
<span class="metric-value-text">0.9372</span>
</div>
<div class="metric-row">
<span class="metric-name">Training RMSE:</span>
<span class="metric-value-text">0.0171</span>
</div>
<div class="metric-row">
<span class="metric-name">Model Type:</span>
<span class="metric-value-text">Ensemble (100 trees)</span>
</div>
<div class="metric-row">
<span class="metric-name">Performance:</span>
<span class="metric-value-text">Excellent</span>
</div>
</div>
<!-- Linear Regression Details -->
<div id="lrDetails" class="model-details" style="display: none;">
<h3><span class="model-badge lr">Linear Regression</span> Metrics</h3>
<div class="metric-row">
<span class="metric-name">Training R² Score:</span>
<span class="metric-value-text">0.1560</span>
</div>
<div class="metric-row">
<span class="metric-name">Training RMSE:</span>
<span class="metric-value-text">0.0626</span>
</div>
<div class="metric-row">
<span class="metric-name">Model Type:</span>
<span class="metric-value-text">Linear (Baseline)</span>
</div>
<div class="metric-row">
<span class="metric-name">Performance:</span>
<span class="metric-value-text">Baseline</span>
</div>
</div>
</div>
<!-- Artifacts Tab -->
<div id="artifacts" class="tab-content">
<h2>Model Artifacts</h2>
{artifacts}
<!-- Random Forest Artifacts -->
<div id="rfArtifacts" class="card" style="display: none;">
<h3><span class="model-badge rf">Random Forest</span> Artifacts</h3>
<div class="metric-row">
<span class="metric-name">File Name:</span>
<span class="metric-value-text">rf_model.pkl</span>
</div>
<div class="metric-row">
<span class="metric-name">File Size:</span>
<span class="metric-value-text">~245 KB</span>
</div>
<div class="metric-row">
<span class="metric-name">Status:</span>
<span class="metric-value-text">✓ Ready for Deployment</span>
</div>
<div class="metric-row">
<span class="metric-name">Location:</span>
<span class="metric-value-text">models/rf_model.pkl</span>
</div>
</div>
<!-- Linear Regression Artifacts -->
<div id="lrArtifacts" class="card" style="display: none;">
<h3><span class="model-badge lr">Linear Regression</span> Artifacts</h3>
<div class="metric-row">
<span class="metric-name">File Name:</span>
<span class="metric-value-text">lr_model.pkl</span>
</div>
<div class="metric-row">
<span class="metric-name">File Size:</span>
<span class="metric-value-text">~8 KB</span>
</div>
<div class="metric-row">
<span class="metric-name">Status:</span>
<span class="metric-value-text">✓ Ready for Deployment</span>
</div>
<div class="metric-row">
<span class="metric-name">Location:</span>
<span class="metric-value-text">models/lr_model.pkl</span>
</div>
</div>
</div>
<!-- Information Tab -->
<div id="info" class="tab-content">
<h2>System Information</h2>
<div class="card">
<h3>🔧 Dashboard Configuration</h3>
<pre><code>Dashboard Version: 2.0.0 (Enhanced)
Gradio Version: 3.50.0
Python Version: 3.11+
Deployment: Hugging Face Spaces Ready
Models Framework: Scikit-learn
Tracking: MLflow + DagsHub
Visualization: SVG Charts
Frontend: HTML5 + CSS3</code></pre>
</div>
<div class="card">
<h3>🚀 Deployment Options</h3>
<ul style="list-style: none; padding: 0;">
<li>✓ <strong>Hugging Face Spaces</strong> - Recommended for web deployment</li>
<li>✓ <strong>Docker</strong> - For containerized deployment</li>
<li>✓ <strong>Local Machine</strong> - For development and testing</li>
<li>✓ <strong>Cloud Services</strong> - AWS, GCP, Azure support</li>
</ul>
</div>
<div class="card">
<h3>📚 Resources</h3>
<ul style="list-style: none; padding: 0;">
<li><a href="https://gradio.app/docs/" target="_blank">Gradio Documentation</a></li>
<li><a href="https://huggingface.co/docs/hub/spaces" target="_blank">Hugging Face Spaces</a></li>
<li><a href="https://scikit-learn.org/" target="_blank">Scikit-learn</a></li>
<li><a href="https://github.com/himashree56/Cpu-optim" target="_blank">GitHub Repository</a></li>
</ul>
</div>
</div>
<footer>
<p>CPU Optimization ML Dashboard | Built with HTML5 & Scikit-learn</p>
<p style="margin-top: 10px; font-size: 12px; color: #999;">
Project: Cpu-optim | Enhanced with Model Comparison & Selection
</p>
</footer>
</div>
<script>
function switchTab(tabName) {{
// Hide all tabs
const tabs = document.querySelectorAll('.tab-content');
tabs.forEach(tab => tab.classList.remove('active'));
// Remove active class from all buttons
const buttons = document.querySelectorAll('.tab-btn');
buttons.forEach(btn => btn.classList.remove('active'));
// Show selected tab
const selectedTab = document.getElementById(tabName);
if (selectedTab) {{
selectedTab.classList.add('active');
}}
// Add active class to clicked button
if (event && event.target) {{
event.target.classList.add('active');
}}
}}
function updateModelView() {{
const modelSelect = document.getElementById('modelSelect').value;
const metricsContent = document.getElementById('metricsContent');
const rfDetails = document.getElementById('rfDetails');
const lrDetails = document.getElementById('lrDetails');
const rfArtifacts = document.getElementById('rfArtifacts');
const lrArtifacts = document.getElementById('lrArtifacts');
console.log('Model selected:', modelSelect);
// Reset all to hidden first
if (metricsContent) metricsContent.style.display = 'none';
if (rfDetails) rfDetails.style.display = 'none';
if (lrDetails) lrDetails.style.display = 'none';
if (rfArtifacts) rfArtifacts.style.display = 'none';
if (lrArtifacts) lrArtifacts.style.display = 'none';
// Show specific model details based on selection
if (modelSelect === 'rf') {{
console.log('Showing Random Forest');
if (rfDetails) rfDetails.style.display = 'block';
if (rfArtifacts) rfArtifacts.style.display = 'block';
}} else if (modelSelect === 'lr') {{
console.log('Showing Linear Regression');
if (lrDetails) lrDetails.style.display = 'block';
if (lrArtifacts) lrArtifacts.style.display = 'block';
}} else {{
console.log('Showing All Models (Comparison)');
if (metricsContent) metricsContent.style.display = 'block';
}}
}}
</script>
</body>
</html>
"""
return html
# ============================================================================
# SIMPLE HTTP SERVER (No Gradio required)
# ============================================================================
def start_simple_server():
"""Start a simple HTTP server for the dashboard"""
try:
from http.server import HTTPServer, BaseHTTPRequestHandler
except ImportError:
print("Error: Could not import HTTP server")
return
html_content = create_html_dashboard()
class DashboardHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/' or self.path == '/index.html':
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(html_content.encode('utf-8'))
else:
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(b"<h1>404 Not Found</h1>")
def log_message(self, format, *args):
"""Suppress log messages"""
pass
port = 7860
server = HTTPServer(('0.0.0.0', port), DashboardHandler)
print(f"🚀 Dashboard running at http://localhost:{port}")
print(f"Press Ctrl+C to stop")
try:
server.serve_forever()
except KeyboardInterrupt:
print("\n✓ Dashboard stopped")
server.server_close()
# ============================================================================
# ENTRY POINT
# ============================================================================
if __name__ == "__main__":
start_simple_server()