Files
wevads-platform/scripts/ia-index.php
2026-02-26 04:53:11 +01:00

689 lines
45 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// Connexion DB
try {
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) {
$pdo = null;
}
// Charger les configs
$config = [];
$providers = [];
if ($pdo) {
try {
$stmt = $pdo->query("SELECT config_key, config_value FROM admin.commonia_config");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$config[$row['config_key']] = $row['config_value'];
}
} catch (Exception $e) {}
// Compter KB
try {
$kbCount = $pdo->query("SELECT COUNT(*) FROM admin.commonia_knowledge")->fetchColumn();
} catch (Exception $e) { $kbCount = 0; }
}
// Liste des providers avec leur status
$providerList = [
'cerebras' => ['name' => 'Cerebras', 'icon' => '🧠', 'key' => 'cerebras_api_key', 'desc' => 'Llama 70B • Ultra rapide', 'type' => 'free'],
'groq' => ['name' => 'Groq', 'icon' => '🚀', 'key' => 'groq_api_key', 'desc' => 'Llama 70B • 100k/jour', 'type' => 'limited'],
'deepseek' => ['name' => 'DeepSeek', 'icon' => '🔮', 'key' => 'deepseek_api_key', 'desc' => 'DeepSeek-V3 • Intelligent', 'type' => 'free'],
'gemini' => ['name' => 'Gemini', 'icon' => '💎', 'key' => 'gemini_api_key', 'desc' => 'Google • 60 req/min', 'type' => 'limited'],
'mistral' => ['name' => 'Mistral', 'icon' => '🇫🇷', 'key' => 'mistral_api_key', 'desc' => 'Mistral Large • Français', 'type' => 'free'],
'cohere' => ['name' => 'Cohere', 'icon' => '🔶', 'key' => 'cohere_api_key', 'desc' => 'Command-R+ • RAG', 'type' => 'free'],
'hyperbolic' => ['name' => 'Hyperbolic', 'icon' => '🌀', 'key' => 'hyperbolic_api_key', 'desc' => 'Llama 70B • Gratuit', 'type' => 'free'],
'sambanova' => ['name' => 'SambaNova', 'icon' => '🚀', 'key' => 'sambanova_api_key', 'desc' => 'Llama 405B • Gratuit', 'type' => 'free'],
'claude' => ['name' => 'Claude', 'icon' => '🧠', 'key' => 'anthropic_api_key', 'desc' => 'Claude 3.5 • Premium', 'type' => 'paid'],
'chatgpt' => ['name' => 'ChatGPT', 'icon' => '🤖', 'key' => 'openai_api_key', 'desc' => 'OpenAI GPT-4', 'type' => 'paid', 'url' => 'https://platform.openai.com/api-keys'],
'copilot' => ['name' => 'Copilot', 'icon' => '🐙', 'key' => 'copilot_api_key', 'desc' => 'GitHub', 'type' => 'paid', 'url' => 'https://github.com/settings/copilot'],
'ollama' => ['name' => 'Ollama', 'icon' => '🦙', 'key' => '', 'desc' => 'Mistral 7B • Local', 'type' => 'local'],
'ollama_mini' => ['name' => 'Ollama Mini', 'icon' => '⚡', 'key' => '', 'desc' => 'Phi 3B • Local rapide', 'type' => 'local'],
];
// Compter providers actifs
$activeProviders = 0;
foreach ($providerList as $id => $p) {
if ($p['type'] === 'local' || !empty($config[$p['key']])) {
$activeProviders++;
}
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WEVAL MIND System - Monitoring</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<style>
:root { --bg: #0f172a; --card: #1e293b; --border: #334155; --text: #e2e8f0; --muted: #94a3b8; --accent: #06b6d4; --green: #10b981; --red: #ef4444; --yellow: #f59e0b; --purple: #8b5cf6; }
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; }
.header { background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 100%); padding: 1.5rem 2rem; border-bottom: 1px solid var(--border); }
.header-content { max-width: 1400px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; }
.header-left { display: flex; align-items: center; gap: 1rem; }
.logo { font-size: 2rem; }
.title { font-size: 1.5rem; font-weight: 700; color: var(--accent); }
.subtitle { color: var(--muted); font-size: 0.85rem; }
.header-stats { display: flex; gap: 1.5rem; }
.stat-box { text-align: center; padding: 0.5rem 1rem; background: rgba(255,255,255,0.05); border-radius: 8px; }
.stat-value { font-size: 1.5rem; font-weight: 700; color: var(--green); }
.stat-label { font-size: 0.7rem; color: var(--muted); text-transform: uppercase; }
.header-actions { display: flex; gap: 0.5rem; }
.btn { padding: 0.6rem 1rem; border-radius: 8px; border: none; cursor: pointer; font-size: 0.85rem; display: flex; align-items: center; gap: 0.5rem; transition: all 0.2s; }
.btn-primary { background: var(--accent); color: white; }
.btn-primary:hover { background: #0891b2; }
.btn-outline { background: transparent; border: 1px solid var(--border); color: var(--text); }
.btn-outline:hover { border-color: var(--accent); color: var(--accent); }
.btn-danger { background: var(--red); color: white; }
.btn-success { background: var(--green); color: white; }
.main { max-width: 1400px; margin: 0 auto; padding: 1.5rem; }
.grid { display: grid; gap: 1.5rem; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1200px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 768px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } }
.card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 1.25rem; }
.card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
.card-title { font-size: 1rem; font-weight: 600; display: flex; align-items: center; gap: 0.5rem; }
.card-badge { font-size: 0.7rem; padding: 0.25rem 0.5rem; border-radius: 4px; background: var(--accent); color: white; }
.status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.status-dot.green { background: var(--green); box-shadow: 0 0 8px var(--green); }
.status-dot.red { background: var(--red); box-shadow: 0 0 8px var(--red); }
.status-dot.yellow { background: var(--yellow); box-shadow: 0 0 8px var(--yellow); }
.service-list { display: flex; flex-direction: column; gap: 0.5rem; }
.service-item { display: flex; align-items: center; justify-content: space-between; padding: 0.6rem 0.75rem; background: rgba(255,255,255,0.03); border-radius: 6px; }
.service-name { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; }
.service-actions { display: flex; gap: 0.25rem; }
.service-btn { padding: 0.25rem 0.5rem; font-size: 0.7rem; border-radius: 4px; border: none; cursor: pointer; }
.service-btn.restart { background: var(--yellow); color: #000; }
.service-btn.stop { background: var(--red); color: #fff; }
.provider-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; }
.provider-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.6rem; background: rgba(255,255,255,0.03); border-radius: 8px; border: 1px solid transparent; cursor: pointer; transition: all 0.2s; }
.provider-item:hover { border-color: var(--accent); }
.provider-item.active { border-color: var(--green); background: rgba(16,185,129,0.1); }
.provider-item.inactive { opacity: 0.5; }
.provider-icon { font-size: 1.25rem; }
.provider-info { flex: 1; min-width: 0; }
.provider-name { font-size: 0.8rem; font-weight: 500; }
.provider-desc { font-size: 0.65rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.quick-links { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.75rem; }
.quick-link { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1rem; background: rgba(255,255,255,0.03); border-radius: 8px; text-decoration: none; color: var(--text); transition: all 0.2s; border: 1px solid transparent; }
.quick-link:hover { border-color: var(--accent); background: rgba(6,182,212,0.1); }
.quick-link i { font-size: 1.5rem; color: var(--accent); }
.quick-link span { font-size: 0.8rem; }
.architecture-diagram { background: rgba(0,0,0,0.3); border-radius: 8px; padding: 1rem; font-family: monospace; font-size: 0.75rem; line-height: 1.6; overflow-x: auto; }
.architecture-diagram .box { display: inline-block; padding: 0.25rem 0.5rem; border-radius: 4px; margin: 0.1rem; }
.architecture-diagram .user { background: var(--purple); }
.architecture-diagram .interface { background: var(--accent); }
.architecture-diagram .api { background: var(--green); }
.architecture-diagram .brain { background: var(--yellow); color: #000; }
.architecture-diagram .provider { background: var(--red); }
.architecture-diagram .arrow { color: var(--muted); }
.modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.9); z-index: 1000; padding: 2rem; overflow-y: auto; }
.modal.show { display: block; }
.modal-content { max-width: 1000px; margin: 0 auto; background: var(--card); border-radius: 16px; padding: 2rem; }
.modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; }
.modal-close { background: none; border: none; color: var(--muted); font-size: 2rem; cursor: pointer; }
.log-box { background: #000; border-radius: 8px; padding: 1rem; font-family: monospace; font-size: 0.75rem; max-height: 200px; overflow-y: auto; }
.log-line { margin-bottom: 0.25rem; }
.log-line.info { color: var(--accent); }
.log-line.error { color: var(--red); }
.log-line.success { color: var(--green); }
.progress-bar { height: 8px; background: var(--border); border-radius: 4px; overflow: hidden; }
.progress-fill { height: 100%; transition: width 0.3s; }
.progress-fill.green { background: var(--green); }
.progress-fill.yellow { background: var(--yellow); }
.progress-fill.red { background: var(--red); }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
.pulse { animation: pulse 2s infinite; }
</style>
</head>
<body>
<header class="header">
<div class="header-content">
<div class="header-left">
<div class="logo">🧞</div>
<div>
<div class="title">WEVAL MIND System</div>
<div class="subtitle">Monitoring & Administration • 89.167.40.150</div>
</div>
</div>
<div class="header-stats">
<div class="stat-box">
<div class="stat-value"><?= $activeProviders ?>/<?= count($providerList) ?></div>
<div class="stat-label">Providers</div>
</div>
<div class="stat-box">
<div class="stat-value"><?= $kbCount ?></div>
<div class="stat-label">KB Docs</div>
</div>
<div class="stat-box">
<div class="stat-value" id="cpuLoad">--</div>
<div class="stat-label">CPU %</div>
</div>
<div class="stat-box">
<div class="stat-value" id="memLoad">--</div>
<div class="stat-label">RAM %</div>
</div>
</div>
<div class="header-actions">
<button class="btn btn-outline" onclick="showArchitecture()"><i class="fas fa-sitemap"></i> Architecture</button>
<button class="btn btn-outline" onclick="showHelp()"><i class="fas fa-question-circle"></i> Aide</button>
<button class="btn btn-primary" onclick="runHealthCheck()"><i class="fas fa-heartbeat"></i> Health Check</button>
</div>
</div>
</header>
<main class="main">
<!-- Services System -->
<div class="grid grid-4" style="margin-bottom:1.5rem">
<div class="card">
<div class="card-header">
<div class="card-title"><i class="fas fa-server"></i> Services Système</div>
<button class="btn btn-outline" style="padding:0.25rem 0.5rem;font-size:0.7rem" onclick="refreshServices()"><i class="fas fa-sync"></i></button>
</div>
<div class="service-list" id="serviceList">
<div class="service-item"><span class="service-name"><span class="status-dot" id="dot-apache"></span> Apache</span><span class="service-actions"><button class="service-btn restart" onclick="restartService('apache2')">↻</button></span></div>
<div class="service-item"><span class="service-name"><span class="status-dot" id="dot-postgresql"></span> PostgreSQL</span><span class="service-actions"><button class="service-btn restart" onclick="restartService('postgresql')">↻</button></span></div>
<div class="service-item"><span class="service-name"><span class="status-dot" id="dot-redis"></span> Redis</span><span class="service-actions"><button class="service-btn restart" onclick="restartService('redis')">↻</button></span></div>
<div class="service-item"><span class="service-name"><span class="status-dot" id="dot-ollama"></span> Ollama</span><span class="service-actions"><button class="service-btn restart" onclick="restartService('ollama')">↻</button></span></div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="card-title"><i class="fas fa-globe"></i> Apps WEVAL</div>
</div>
<div class="service-list">
<div class="service-item"><span class="service-name"><span class="status-dot green"></span> WEVAL :5821</span><a href="/" class="service-btn" style="background:var(--accent);color:#fff">Ouvrir</a></div>
<div class="service-item"><span class="service-name"><span class="status-dot" id="dot-fmgapp"></span> FMGAPP :5822</span><a href="http://89.167.40.150:5822" class="service-btn" style="background:var(--accent);color:#fff">Ouvrir</a></div>
<div class="service-item"><span class="service-name"><span class="status-dot" id="dot-bcgapp"></span> BCGAPP :5823</span><a href="http://89.167.40.150:5823" class="service-btn" style="background:var(--accent);color:#fff">Ouvrir</a></div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="card-title"><i class="fas fa-chart-line"></i> Ressources</div>
</div>
<div style="display:flex;flex-direction:column;gap:0.75rem">
<div><div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem"><span>CPU</span><span id="cpuPercent">--%</span></div><div class="progress-bar"><div class="progress-fill green" id="cpuBar" style="width:0%"></div></div></div>
<div><div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem"><span>RAM</span><span id="memPercent">--%</span></div><div class="progress-bar"><div class="progress-fill green" id="memBar" style="width:0%"></div></div></div>
<div><div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem"><span>Disque</span><span id="diskPercent">--%</span></div><div class="progress-bar"><div class="progress-fill green" id="diskBar" style="width:0%"></div></div></div>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="card-title"><i class="fas fa-tools"></i> Actions Rapides</div>
</div>
<div style="display:flex;flex-direction:column;gap:0.5rem">
<button class="btn btn-outline" style="width:100%;justify-content:center" onclick="clearCache()"><i class="fas fa-broom"></i> Vider Cache</button>
<button class="btn btn-outline" style="width:100%;justify-content:center" onclick="testAllProviders()"><i class="fas fa-flask"></i> Tester Providers</button>
<button class="btn btn-outline" style="width:100%;justify-content:center" onclick="viewLogs()"><i class="fas fa-file-alt"></i> Voir Logs</button>
<button class="btn btn-danger" style="width:100%;justify-content:center" onclick="emergencyRestart()"><i class="fas fa-exclamation-triangle"></i> Restart Urgence</button>
</div>
</div>
</div>
<!-- Providers IA -->
<div class="card" style="margin-bottom:1.5rem">
<div class="card-header">
<div class="card-title"><i class="fas fa-brain"></i> Providers IA</div>
<div style="display:flex;gap:0.5rem">
<span class="card-badge" style="background:var(--green)"><?= $activeProviders ?> actifs</span>
<a href="/api-keys.php" class="btn btn-outline" style="padding:0.25rem 0.5rem;font-size:0.7rem"><i class="fas fa-key"></i> Clés API</a> <a href="/widget-admin.php" class="btn btn-outline" style="padding:0.25rem 0.5rem;font-size:0.7rem"><i class="fas fa-cog"></i> Config</a>
</div>
</div>
<div class="provider-grid">
<?php foreach ($providerList as $id => $p):
$isActive = ($p['type'] === 'local') || !empty($config[$p['key']]);
$statusClass = $isActive ? 'active' : 'inactive';
?>
<div class="provider-item <?= $statusClass ?>" onclick="testProvider('<?= $id ?>')">
<span class="status-dot <?= $isActive ? 'green' : 'red' ?>"></span>
<span class="provider-icon"><?= $p['icon'] ?></span>
<div class="provider-info">
<div class="provider-name"><?= $p['name'] ?></div>
<div class="provider-desc"><?= $p['desc'] ?></div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Interfaces & Liens -->
<div class="grid grid-2">
<div class="card">
<div class="card-header">
<div class="card-title"><i class="fas fa-desktop"></i> Interfaces WEVAL MIND</div>
</div>
<div class="quick-links">
<a href="/hamid-fullscreen.php" class="quick-link"><i class="fas fa-comments"></i><span>Chat</span></a>
<a href="/hamid-code/" class="quick-link"><i class="fas fa-code"></i><span>IDE Code</span></a>
<a href="/cli/" class="quick-link"><i class="fas fa-terminal"></i><span>CLI Agent</span></a>
<a href="/" class="quick-link"><i class="fas fa-robot"></i><span>Widget</span></a>
</div>
</div>
<div class="card">
<div class="card-header">
<div class="card-title"><i class="fas fa-cogs"></i> Administration</div>
</div>
<div class="quick-links">
<a href="/widget-admin.php" class="quick-link"><i class="fas fa-sliders-h"></i><span>Config IA</span></a>
<a href="/widget-admin.php#kb" class="quick-link"><i class="fas fa-book"></i><span>Knowledge Base</span></a>
<a href="/commonia/commonia-brain.php?providers" class="quick-link"><i class="fas fa-plug"></i><span>API Status</span></a>
<a href="/adminer.php" class="quick-link"><i class="fas fa-database"></i><span>Database</span></a>
</div>
</div>
</div>
</main>
<!-- Modal Architecture -->
<div class="modal" id="architectureModal">
<div class="modal-content" style="max-width:1100px">
<div class="modal-header">
<h2 style="color:var(--accent)"><i class="fas fa-sitemap"></i> Architecture WEVAL MIND System</h2>
<button class="modal-close" onclick="hideModal('architectureModal')">×</button>
</div>
<div class="architecture-diagram">
<pre style="color:var(--text);margin:0">
🧞 WEVAL MIND SYSTEM │
89.167.40.150 (Hetzner) │
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 💬 Chat │ │ 💻 IDE Code │ │ 🖥️ CLI Agent │ │ 🧞 Widget │
│ Fullscreen │ │ VS Code-like │ │ Terminal │ │ Dashboard │
│ :5821/ │ │ :5821/ │ │ :5821/cli/ │ │ :5821/ │
│ hamid-full.. │ │ hamid-code/ │ │ │ │ │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │ │
└────────────────────┴────────────────────┴────────────────────┘
┌─────────────────────────────┐
│ 📡 /hamid-api.php │
│ Point d'entrée unifié │
│ • Reçoit message+provider│
│ • Charge KB si activé │
│ • Détecte génération docs│
└─────────────┬───────────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ 📚 Knowledge Base │ │ 🧠 commonia-brain │ │ 🛠️ ia-tools.php │
│ PostgreSQL │ │ Cerveau Multi-IA │ │ Génération docs │
│ admin.commonia_ │ │ • System prompt │ │ • PDF, PPTX │
│ knowledge (141) │ │ • Auto-fallback │ │ • XLSX, DOCX │
└───────────────────┘ │ • Routing │ │ • QR Code │
└─────────┬─────────┘ └───────────────────┘
┌────────────────────────────────┼────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐
☁️ CLOUD APIs │ │ 🦙 LOCAL │ │ 💾 DATABASE │
├───────────────┤ ├───────────────┤
🧠 Cerebras │ │ Ollama:11434 │ │ PostgreSQL │
🚀 Groq │ │ • mistral:7b │ │ • adx_system │
🔮 DeepSeek │ │ • phi:latest │ │ • adx_clients │
🇫🇷 Mistral │ └───────────────┘ │ │
🌀 Hyperbolic │ │ Tables: │
🔶 Cohere │ │ • commonia_ │
💎 Gemini │ │ config │
🧠 Claude │ │ • commonia_ │
🚀 SambaNova │ │ knowledge │
└───────────────┘
🔄 FLUX DE DONNÉES │
1. User → Interface (Chat/Code/CLI/Widget) │
2. Interface → POST /hamid-api.php (message + provider) │
3. API → Charge Knowledge Base (141 docs) si provider != ollama_mini │
4. API → Détecte si génération document (PDF/PPTX/etc) → ia-tools.php │
5. API → Sinon appelle commonia-brain.php avec message + contexte KB │
6. Brain → Construit prompt avec CLAUDE_BRAIN (system prompt) │
7. Brain → Appelle provider sélectionné (ou fallback si erreur) │
8. Brain → Retourne réponse JSON {success, response, provider, duration_ms, kb_used} │
9. Interface → Affiche réponse avec tags [PROVIDER • XXXms • 📚 KB] │
</pre>
</div>
</div>
</div>
<!-- Modal Aide -->
<div class="modal" id="helpModal">
<div class="modal-content">
<div class="modal-header">
<h2 style="color:var(--accent)"><i class="fas fa-question-circle"></i> Guide Complet WEVAL MIND</h2>
<button class="modal-close" onclick="hideModal('helpModal')">×</button>
</div>
<div style="display:grid;gap:1.5rem">
<div>
<h3 style="color:var(--green);margin-bottom:0.75rem">✅ PROVIDERS GRATUITS ILLIMITÉS</h3>
<table style="width:100%;border-collapse:collapse;font-size:0.85rem">
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🧠 <b>Cerebras</b></td><td>Llama 3.3 70B</td><td style="color:var(--green)">⚡⚡⚡ 8000 tok/s</td><td>Le meilleur choix général</td></tr>
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🔮 <b>DeepSeek</b></td><td>DeepSeek-V3</td><td style="color:var(--accent)">⚡ Intelligent</td><td>Idéal pour le code</td></tr>
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🇫🇷 <b>Mistral</b></td><td>Mistral Large</td><td style="color:var(--accent)">⚡ Rapide</td><td>Excellent en français</td></tr>
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🌀 <b>Hyperbolic</b></td><td>Llama 70B</td><td style="color:var(--accent)">⚡ Rapide</td><td>Bon raisonnement</td></tr>
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🔶 <b>Cohere</b></td><td>Command-R+</td><td style="color:var(--accent)">⚡ Rapide</td><td>Spécialisé RAG/recherche</td></tr>
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🦙 <b>Ollama</b></td><td>Mistral 7B</td><td style="color:var(--yellow)">~10s Local</td><td>100% privé, hors-ligne</td></tr>
<tr><td style="padding:0.5rem">⚡ <b>Ollama Mini</b></td><td>Phi 3B</td><td style="color:var(--green)">~2s Local</td><td>Tests rapides</td></tr>
</table>
</div>
<div>
<h3 style="color:var(--yellow);margin-bottom:0.75rem">⚠️ PROVIDERS LIMITÉS</h3>
<table style="width:100%;border-collapse:collapse;font-size:0.85rem">
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem">🚀 <b>Groq</b></td><td>Llama 70B</td><td>100k tokens/jour</td></tr>
<tr><td style="padding:0.5rem">💎 <b>Gemini</b></td><td>Gemini 1.5</td><td>60 req/min</td></tr>
</table>
</div>
<div>
<h3 style="color:var(--red);margin-bottom:0.75rem">💰 PROVIDERS PAYANTS</h3>
<table style="width:100%;border-collapse:collapse;font-size:0.85rem">
<tr><td style="padding:0.5rem">🧠 <b>Claude</b></td><td>Claude Sonnet 4</td><td>Le plus intelligent</td></tr>
</table>
</div>
<div>
<h3 style="color:var(--accent);margin-bottom:0.75rem">🎯 RECOMMANDATIONS PAR INTERFACE</h3>
<ul style="margin:0;padding-left:1.5rem;line-height:2">
<li><b>Chat Fullscreen</b> → 🧠 Cerebras ou 🇫🇷 Mistral (conversation fluide)</li>
<li><b>IDE Code</b> → 🔮 DeepSeek ou 🧠 Claude (analyse de code)</li>
<li><b>CLI Agent</b> → 🧠 Cerebras ou 🔮 DeepSeek (commandes système)</li>
<li><b>Widget Dashboard</b> → ⚡ Ollama Mini (réponses rapides)</li>
<li><b>Documents longs</b> → 🧠 Claude ou 🔶 Cohere</li>
<li><strong>Vision</strong> → 🔴 Claude (analyse d'images)</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Modal Logs -->
<div class="modal" id="logsModal">
<div class="modal-content">
<div class="modal-header">
<h2 style="color:var(--accent)"><i class="fas fa-file-alt"></i> Logs Système</h2>
<button class="modal-close" onclick="hideModal('logsModal')">×</button>
</div>
<div class="log-box" id="logContent">Chargement...</div>
</div>
</div>
<!-- Modal Test Results -->
<div class="modal" id="testModal">
<div class="modal-content">
<div class="modal-header">
<h2 style="color:var(--accent)"><i class="fas fa-flask"></i> Test des Providers</h2>
<button class="modal-close" onclick="hideModal('testModal')">×</button>
</div>
<div id="testResults">Lancement des tests...</div>
</div>
</div>
<script>
// Refresh services status
async function refreshServices() {
try {
const res = await fetch('/cli/api.php?action=scan');
const data = await res.json();
if (data.success) {
const s = data.scan;
// Services
for (const [name, status] of Object.entries(s.services)) {
const dot = document.getElementById('dot-' + name);
if (dot) {
dot.className = 'status-dot ' + (status === 'active' ? 'green' : 'red');
}
}
// Resources
const cpu = Math.min(Math.round(s.load[0] * 25), 100);
document.getElementById('cpuLoad').textContent = cpu + '%';
document.getElementById('cpuPercent').textContent = cpu + '%';
document.getElementById('cpuBar').style.width = cpu + '%';
document.getElementById('cpuBar').className = 'progress-fill ' + (cpu > 80 ? 'red' : cpu > 60 ? 'yellow' : 'green');
if (s.memory.percent) {
document.getElementById('memLoad').textContent = s.memory.percent + '%';
document.getElementById('memPercent').textContent = s.memory.percent + '%';
document.getElementById('memBar').style.width = s.memory.percent + '%';
}
if (s.disk.percent) {
document.getElementById('diskPercent').textContent = s.disk.percent + '%';
document.getElementById('diskBar').style.width = s.disk.percent + '%';
}
}
} catch (e) { console.error(e); }
}
function showModal(id) { document.getElementById(id).classList.add('show'); }
function hideModal(id) { document.getElementById(id).classList.remove('show'); }
function showArchitecture() { showModal('architectureModal'); }
function showHelp() { showModal('helpModal'); }
async function testProvider(provider) {
showModal('testModal');
document.getElementById('testResults').innerHTML = '<div style="color:var(--accent)">Test de ' + provider + '...</div>';
try {
const fd = new FormData();
fd.append('message', 'Réponds juste "OK" en un mot');
fd.append('provider', provider);
const start = Date.now();
const res = await fetch('/hamid-api.php', { method: 'POST', body: fd });
const data = await res.json();
const duration = Date.now() - start;
if (data.success) {
document.getElementById('testResults').innerHTML = '<div class="log-line success">✅ ' + provider.toUpperCase() + ' fonctionne!</div><div>Réponse: ' + data.response.substring(0, 100) + '</div><div>Temps: ' + duration + 'ms</div>';
} else {
document.getElementById('testResults').innerHTML = '<div class="log-line error">❌ Erreur: ' + (data.error || 'Inconnu') + '</div>';
}
} catch (e) {
document.getElementById('testResults').innerHTML = '<div class="log-line error">❌ Erreur: ' + e.message + '</div>';
}
}
async function testAllProviders() {
showModal('testModal');
const providers = ['cerebras', 'groq', 'deepseek', 'gemini', 'mistral', 'cohere', 'hyperbolic', 'ollama', 'claude'];
let html = '<div style="display:grid;gap:0.5rem">';
document.getElementById('testResults').innerHTML = html + '<div>Test en cours...</div></div>';
for (const p of providers) {
try {
const fd = new FormData();
fd.append('message', 'OK');
fd.append('provider', p);
const start = Date.now();
const res = await fetch('/hamid-api.php', { method: 'POST', body: fd });
const data = await res.json();
const duration = Date.now() - start;
html += data.success
? '<div class="log-line success">✅ ' + p + ' - ' + duration + 'ms</div>'
: '<div class="log-line error">❌ ' + p + ' - ' + (data.error || 'Erreur').substring(0, 50) + '</div>';
} catch (e) {
html += '<div class="log-line error">❌ ' + p + ' - ' + e.message + '</div>';
}
document.getElementById('testResults').innerHTML = html + '</div>';
}
}
async function viewLogs() {
showModal('logsModal');
try {
const res = await fetch('/cli/api.php?action=logs&log=wevads&lines=50');
const data = await res.json();
if (data.success) {
document.getElementById('logContent').innerHTML = data.content.split('\n').map(l => '<div class="log-line">' + l + '</div>').join('');
}
} catch (e) {
document.getElementById('logContent').innerHTML = '<div class="log-line error">Erreur: ' + e.message + '</div>';
}
}
async function restartService(service) {
if (!confirm('Redémarrer ' + service + '?')) return;
try {
const res = await fetch('/cli/api.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'action=exec&command=systemctl restart ' + service
});
alert('Service ' + service + ' redémarré');
refreshServices();
} catch (e) { alert('Erreur: ' + e.message); }
}
function clearCache() {
alert('Cache vidé!');
}
function emergencyRestart() {
if (!confirm('⚠️ ATTENTION: Redémarrer tous les services IA?\n\nCela va interrompre toutes les requêtes en cours.')) return;
alert('Restart en cours...');
}
function runHealthCheck() {
testAllProviders();
}
// Init
refreshServices();
setInterval(refreshServices, 30000);
</script>
<div id="guideModal" class="modal" style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:1000;overflow-y:auto">
<div style="max-width:900px;margin:50px auto;background:#1a1a2e;border-radius:15px;padding:30px;color:#fff">
<button onclick="document.getElementById('guideModal').style.display='none'" style="float:right;background:#ff4757;border:none;color:#fff;padding:10px 15px;border-radius:5px;cursor:pointer">✕ Fermer</button>
<h2>🤖 Guide Complet WEVAL MIND</h2>
<h3>✅ PROVIDERS GRATUITS ILLIMITÉS</h3>
<table style="width:100%;border-collapse:collapse;margin:10px 0">
<tr style="background:#2d3436"><th style="padding:10px;text-align:left">Provider</th><th>Modèle</th><th>Vitesse</th><th>Force</th><th>KB Max</th></tr>
<tr style="background:#0a0a15"><td>🔶 <b>Cerebras</b></td><td>Llama 3.3 70B</td><td>⚡⚡⚡ 8000 tok/s</td><td>Meilleur choix général</td><td>12 × 1000</td></tr>
<tr style="background:#12121f"><td>🔮 <b>DeepSeek</b></td><td>DeepSeek-V3</td><td>⚡ Intelligent</td><td>Idéal pour le code</td><td>15 × 1200</td></tr>
<tr style="background:#0a0a15"><td>🇫🇷 <b>Mistral</b></td><td>Mistral Large</td><td>⚡ Rapide</td><td>Excellent en français</td><td>12 × 1000</td></tr>
<tr style="background:#12121f"><td>🔶 <b>Cohere</b></td><td>Command-R+</td><td>⚡ Rapide</td><td>Spécialisé RAG/recherche</td><td>10 × 800</td></tr>
<tr style="background:#0a0a15"><td>🦙 <b>Ollama</b></td><td>Mistral 7B</td><td>~15s Local</td><td>100% privé, hors-ligne</td><td>10 × 800</td></tr>
<tr style="background:#12121f"><td>⚡ <b>Ollama Mini</b></td><td>TinyLlama 1B</td><td>~3s Local</td><td>Tests rapides</td><td>3 × 300</td></tr>
</table>
<h3>⚠️ PROVIDERS LIMITÉS</h3>
<table style="width:100%;border-collapse:collapse;margin:10px 0">
<tr style="background:#2d3436"><th style="padding:10px;text-align:left">Provider</th><th>Limite</th><th>Reset</th></tr>
<tr style="background:#0a0a15"><td>⚡ Groq</td><td>100k tokens/jour</td><td>Minuit UTC</td></tr>
<tr style="background:#12121f"><td>💎 Gemini</td><td>60 req/min</td><td>Par minute</td></tr>
<tr style="background:#0a0a15"><td>🚀 SambaNova</td><td>Variable</td><td>Quotidien</td></tr>
</table>
<h3>💰 PROVIDERS PAYANTS</h3>
<table style="width:100%;border-collapse:collapse;margin:10px 0">
<tr style="background:#2d3436"><th style="padding:10px;text-align:left">Provider</th><th>Modèle</th><th>Force</th><th>KB Max</th></tr>
<tr style="background:#0a0a15"><td>🧠 <b>Claude</b></td><td>Claude Sonnet 4</td><td>Le plus intelligent + Vision 👁️</td><td>20 × 1500</td></tr>
<tr style="background:#12121f"><td>💚 ChatGPT</td><td>GPT-4</td><td>Polyvalent</td><td>15 × 1200</td></tr>
</table>
<h3>🎯 RECOMMANDATIONS PAR USAGE</h3>
<ul style="line-height:2">
<li><b>💬 Chat rapide</b> → 🔶 Cerebras (ultra-rapide)</li>
<li><b>💻 Analyse de code</b> → 🔮 DeepSeek ou 🧠 Claude</li>
<li><b>📝 Documents longs</b> → 🧠 Claude (20 KB, 8192 tokens)</li>
<li><b>🇫🇷 Français</b> → 🇫🇷 Mistral</li>
<li><b>👁️ Analyse d'images</b> → 🧠 Claude (seul avec vision)</li>
<li><b>🔒 Confidentialité</b> → 🦙 Ollama (100% local)</li>
<li><b>⚡ Tests rapides</b> → ⚡ Ollama Mini</li>
</ul>
<h3>⚙️ PARAMÈTRES KB DYNAMIQUES</h3>
<p>Le nombre de résultats KB s'adapte automatiquement au provider :</p>
<table style="width:100%;border-collapse:collapse;margin:10px 0">
<tr style="background:#2d3436"><th style="padding:10px">Provider</th><th>Résultats</th><th>Chars/résultat</th><th>Total max</th></tr>
<tr style="background:#0a0a15"><td>Claude</td><td>20</td><td>1500</td><td>30 000 chars</td></tr>
<tr style="background:#12121f"><td>DeepSeek/Gemini</td><td>15</td><td>1200</td><td>18 000 chars</td></tr>
<tr style="background:#0a0a15"><td>Cerebras/Mistral</td><td>12</td><td>1000</td><td>12 000 chars</td></tr>
<tr style="background:#12121f"><td>Groq</td><td>10</td><td>800</td><td>8 000 chars</td></tr>
<tr style="background:#0a0a15"><td>Ollama Mini</td><td>3</td><td>300</td><td>900 chars</td></tr>
</table>
<h3>🔧 DÉPANNAGE RAPIDE</h3>
<div style="display:flex;flex-wrap:wrap;gap:10px;margin:15px 0">
<button onclick="restartProvider('ollama')" style="background:#3498db;border:none;color:#fff;padding:10px 20px;border-radius:5px;cursor:pointer">🔄 Restart Ollama</button>
<button onclick="restartProvider('apache')" style="background:#e67e22;border:none;color:#fff;padding:10px 20px;border-radius:5px;cursor:pointer">🔄 Restart Apache</button>
<button onclick="testAllProviders()" style="background:#27ae60;border:none;color:#fff;padding:10px 20px;border-radius:5px;cursor:pointer">🧪 Tester Tous</button>
<button onclick="clearCache()" style="background:#9b59b6;border:none;color:#fff;padding:10px 20px;border-radius:5px;cursor:pointer">🗑️ Vider Cache</button>
</div>
<h3>❌ MESSAGES D'ERREUR</h3>
<table style="width:100%;border-collapse:collapse;margin:10px 0">
<tr style="background:#2d3436"><th style="padding:10px">Erreur</th><th>Signification</th><th>Solution</th></tr>
<tr style="background:#0a0a15"><td>❌ Plus de crédits</td><td>Quota épuisé</td><td>Changer de provider</td></tr>
<tr style="background:#12121f"><td>⏳ Limite atteinte</td><td>Rate limit</td><td>Attendre ou changer</td></tr>
<tr style="background:#0a0a15"><td>🔑 Clé invalide</td><td>API key incorrecte</td><td>Vérifier Config IA</td></tr>
<tr style="background:#12121f"><td>📦 Message trop long</td><td>Contexte KB trop grand</td><td>Utiliser Claude</td></tr>
<tr style="background:#0a0a15"><td>🔧 Indisponible</td><td>Serveur down</td><td>Réessayer plus tard</td></tr>
</table>
<h3>📊 STATUT ACTUEL</h3>
<div id="providerStatus" style="background:#0a0a15;padding:15px;border-radius:10px;margin:10px 0">
Cliquez sur "🧪 Tester Tous" pour voir le statut en temps réel.
</div>
</div>
</div>
<script>
function restartProvider(service) {
if(confirm("Redémarrer " + service + " ?")) {
fetch("ia-api.php?action=restart&service=" + service)
.then(r => r.json())
.then(d => alert(d.message || "Redémarré!"))
.catch(e => alert("Erreur: " + e));
}
}
function testAllProviders() {
document.getElementById("providerStatus").innerHTML = "⏳ Test en cours...";
fetch("ia-api.php?action=test_providers")
.then(r => r.json())
.then(d => {
let html = "<table style='width:100%'>";
for(let p in d) {
let status = d[p].ok ? "✅" : "❌";
let time = d[p].time ? d[p].time + "ms" : d[p].error;
html += "<tr><td>" + p + "</td><td>" + status + "</td><td>" + time + "</td></tr>";
}
html += "</table>";
document.getElementById("providerStatus").innerHTML = html;
})
.catch(e => document.getElementById("providerStatus").innerHTML = "Erreur: " + e);
}
function clearCache() {
fetch("ia-api.php?action=clear_cache")
.then(r => r.json())
.then(d => alert(d.message || "Cache vidé!"))
.catch(e => alert("Erreur: " + e));
}
</script>
</body>
</html>