'localhost','db'=>'adx_system','user'=>'admin','pass'=>'admin123']; try { $pdo = new PDO("pgsql:host={$DB['host']};dbname={$DB['db']}", $DB['user'], $DB['pass']); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (Exception $e) { die("❌ Connexion DB: " . $e->getMessage()); } // Upload image $uploadMsg = ''; if (isset($_FILES['robot_image']) && $_FILES['robot_image']['error'] == 0) { $uploadDir = '/opt/wevads/public/images/'; if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true); $ext = pathinfo($_FILES['robot_image']['name'], PATHINFO_EXTENSION); $filename = 'chatbot-avatar.' . $ext; if (move_uploaded_file($_FILES['robot_image']['tmp_name'], $uploadDir . $filename)) { $stmt = $pdo->prepare("INSERT INTO admin.chatbot_config (config_key, config_value) VALUES ('robot_image', ?) ON CONFLICT (config_key) DO UPDATE SET config_value = EXCLUDED.config_value"); $stmt->execute(['/images/' . $filename . '?v=' . time()]); $uploadMsg = '✅ Image uploadée!'; } } // Sauvegarder config $msg = ''; if ($_POST && isset($_POST['save_config'])) { $fields = [ 'bot_name', 'bubble_text', 'welcome_message', 'color1', 'color2', 'default_provider', 'widget_size', 'glow', 'opacity', 'border', 'groq_api_key', 'deepseek_api_key', 'claude_api_key', 'gemini_api_key', 'mistral_api_key', 'ollama_url', 'vllm_url', 'system_prompt', 'fallback_enabled' ]; foreach ($fields as $key) { $value = $_POST[$key] ?? ''; if ($key == 'fallback_enabled') $value = isset($_POST[$key]) ? '1' : '0'; $stmt = $pdo->prepare("INSERT INTO admin.chatbot_config (config_key, config_value) VALUES (?, ?) ON CONFLICT (config_key) DO UPDATE SET config_value = EXCLUDED.config_value"); $stmt->execute([$key, $value]); } $msg = '✅ Configuration sauvegardée!'; } // API Test endpoint if (isset($_GET['test_provider'])) { header('Content-Type: application/json'); $provider = $_GET['test_provider']; // Recharger config fraîche $config = []; $stmt = $pdo->query("SELECT config_key, config_value FROM admin.chatbot_config"); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) $config[$row['config_key']] = $row['config_value']; $result = ['provider' => $provider, 'status' => 'error', 'message' => 'Non testé', 'latency' => 0]; $start = microtime(true); try { switch ($provider) { case 'groq': $apiKey = $config['groq_api_key'] ?? ''; if (empty($apiKey)) { $result['message'] = 'API Key manquante'; break; } $ch = curl_init('https://api.groq.com/openai/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $apiKey], CURLOPT_POSTFIELDS => json_encode(['model' => 'llama-3.3-70b-versatile', 'messages' => [['role' => 'user', 'content' => 'Hi']], 'max_tokens' => 5]) ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $result['status'] = 'ok'; $result['message'] = 'Groq OK - LLama 3.3 70B'; } else { $result['message'] = "HTTP $httpCode"; } break; case 'deepseek': $apiKey = $config['deepseek_api_key'] ?? ''; if (empty($apiKey)) { $result['message'] = 'API Key manquante'; break; } $ch = curl_init('https://api.deepseek.com/chat/completions'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $apiKey], CURLOPT_POSTFIELDS => json_encode(['model' => 'deepseek-chat', 'messages' => [['role' => 'user', 'content' => 'Hi']], 'max_tokens' => 5]) ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $result['status'] = 'ok'; $result['message'] = 'DeepSeek OK'; } else { $result['message'] = "HTTP $httpCode"; } break; case 'claude': $apiKey = $config['claude_api_key'] ?? ''; if (empty($apiKey)) { $result['message'] = 'API Key manquante'; break; } $ch = curl_init('https://api.anthropic.com/v1/messages'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'x-api-key: ' . $apiKey, 'anthropic-version: 2023-06-01'], CURLOPT_POSTFIELDS => json_encode(['model' => 'claude-3-haiku-20240307', 'messages' => [['role' => 'user', 'content' => 'Hi']], 'max_tokens' => 5]) ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $result['status'] = 'ok'; $result['message'] = 'Claude OK'; } else { $result['message'] = "HTTP $httpCode"; } break; case 'gemini': $apiKey = $config['gemini_api_key'] ?? ''; if (empty($apiKey)) { $result['message'] = 'API Key manquante'; break; } $ch = curl_init('https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key=' . $apiKey); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode(['contents' => [['parts' => [['text' => 'Hi']]]]]) ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $result['status'] = 'ok'; $result['message'] = 'Gemini OK'; } else { $result['message'] = "HTTP $httpCode"; } break; case 'mistral': $apiKey = $config['mistral_api_key'] ?? ''; if (empty($apiKey)) { $result['message'] = 'API Key manquante'; break; } $ch = curl_init('https://api.mistral.ai/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $apiKey], CURLOPT_POSTFIELDS => json_encode(['model' => 'mistral-tiny', 'messages' => [['role' => 'user', 'content' => 'Hi']], 'max_tokens' => 5]) ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $result['status'] = 'ok'; $result['message'] = 'Mistral OK'; } else { $result['message'] = "HTTP $httpCode"; } break; case 'ollama': $url = $config['ollama_url'] ?? 'http://localhost:11434'; $ch = curl_init($url . '/api/tags'); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $data = json_decode($response, true); $models = isset($data['models']) ? count($data['models']) : 0; $result['status'] = 'ok'; $result['message'] = "Ollama OK - $models modèles"; } else { $result['message'] = "Non accessible"; } break; case 'vllm': $url = $config['vllm_url'] ?? 'http://localhost:8000'; $ch = curl_init($url . '/v1/models'); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { $result['status'] = 'ok'; $result['message'] = 'vLLM OK'; } else { $result['message'] = "Non accessible"; } break; } } catch (Exception $e) { $result['message'] = $e->getMessage(); } $result['latency'] = round((microtime(true) - $start) * 1000); echo json_encode($result); exit; } // Charger config $config = []; $stmt = $pdo->query("SELECT config_key, config_value FROM admin.chatbot_config"); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) $config[$row['config_key']] = $row['config_value']; // Defaults $d = [ 'bot_name' => 'Assistant WEVAL', 'bubble_text' => 'Salam !', 'welcome_message' => 'Bonjour! 👋 Je suis votre assistant WEVAL.', 'color1' => '#06b6d4', 'color2' => '#0891b2', 'default_provider' => 'groq', 'widget_size' => '80px', 'glow' => 'Moyen', 'opacity' => '100%', 'border' => 'Moyen', 'ollama_url' => 'http://localhost:11434', 'vllm_url' => 'http://localhost:8000', 'system_prompt' => 'Tu es Hamid Esmart, assistant IA expert WEVAL.', 'fallback_enabled' => '1', 'robot_image' => '/images/chatbot-avatar.png' ]; foreach ($d as $k => $v) if (!isset($config[$k]) || $config[$k] === '') $config[$k] = $v; $kbCount = $pdo->query("SELECT COUNT(*) FROM admin.chatbot_knowledge")->fetchColumn() ?: 0; ?> 🤖 Chatbot Admin

Chatbot Admin

Chat KB () Retour

Robot

Paramètres

Providers IA

LOCAL
🦙
Ollama LOCAL
vLLM LOCAL
CLOUD
🌊
DeepSeek CLOUD
🤖
Claude CLOUD
💎
Gemini CLOUD
🇫🇷
Mistral CLOUD

Comparatif

ProviderVitesseQualitéCoûtNotes
⚡ Groq★★★★★★★★★★GratuitUltra rapide
🤖 Claude★★★★☆★★★★★$15/MTrès intelligent
🌊 DeepSeek★★★★☆★★★★★$0.14/MGPT-4 level
💎 Gemini★★★★☆★★★★☆Gratuit+Multimodal
🦙 Ollama★★★☆☆★★★★☆LocalOffline, GPU

Aperçu

Pas de GPU local

Status Providers