['host' => 'localhost', 'name' => 'adx_system', 'user' => 'admin', 'pass' => 'admin123'], 'servers' => ['app' => '89.167.40.150', 'tracking' => '151.80.235.110', 'consulting' => '46.62.220.135'], 'max_tokens' => 4096, 'temperature' => 0.7, 'kb_enabled' => true, 'memory_enabled' => true ]; $PROVIDERS = [ 'cerebras' => ['name' => 'Cerebras', 'endpoint' => 'https://api.cerebras.ai/v1/chat/completions', 'model' => 'llama3.1-70b', 'priority' => 1, 'config_key' => 'cerebras_api_key'], 'groq' => ['name' => 'Groq', 'endpoint' => 'https://api.groq.com/openai/v1/chat/completions', 'model' => 'llama-3.3-70b-versatile', 'priority' => 2, 'config_key' => 'groq_api_key'], 'sambanova' => ['name' => 'SambaNova', 'endpoint' => 'https://api.sambanova.ai/v1/chat/completions', 'model' => 'Meta-Llama-3.1-70B-Instruct', 'priority' => 3, 'config_key' => 'sambanova_api_key'], 'deepseek' => ['name' => 'DeepSeek', 'endpoint' => 'https://api.deepseek.com/v1/chat/completions', 'model' => 'deepseek-chat', 'priority' => 4, 'config_key' => 'deepseek_api_key'], 'mistral' => ['name' => 'Mistral', 'endpoint' => 'https://api.mistral.ai/v1/chat/completions', 'model' => 'mistral-large-latest', 'priority' => 5, 'config_key' => 'mistral_api_key'], 'together' => ['name' => 'Together AI', 'endpoint' => 'https://api.together.xyz/v1/chat/completions', 'model' => 'meta-llama/Llama-3-70b-chat-hf', 'priority' => 6, 'config_key' => 'together_api_key'], 'openrouter' => ['name' => 'OpenRouter', 'endpoint' => 'https://openrouter.ai/api/v1/chat/completions', 'model' => 'meta-llama/llama-3.1-70b-instruct', 'priority' => 7, 'config_key' => 'openrouter_api_key'] ]; $SYSTEM_PROMPT = << PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]); } catch (Exception $e) { return null; } } return $pdo; } function getApiKey($configKey) { $pdo = getDB(); if (!$pdo) return null; try { $stmt = $pdo->prepare("SELECT config_value FROM admin.hamid_config WHERE config_key = ? AND status = 'active' LIMIT 1"); $stmt->execute([$configKey]); $result = $stmt->fetch(); if ($result) return $result['config_value']; $stmt = $pdo->prepare("SELECT config_value FROM admin.commonia_config WHERE config_key = ? LIMIT 1"); $stmt->execute([$configKey]); $result = $stmt->fetch(); return $result ? $result['config_value'] : null; } catch (Exception $e) { return null; } } function searchKB($query, $limit = 5) { $pdo = getDB(); if (!$pdo) return []; try { $stmt = $pdo->prepare("SELECT title, content, category FROM admin.knowledge_base WHERE content ILIKE ? OR title ILIKE ? LIMIT ?"); $searchTerm = "%{$query}%"; $stmt->execute([$searchTerm, $searchTerm, $limit]); return $stmt->fetchAll(); } catch (Exception $e) { return []; } } function saveToMemory($sessionId, $role, $content) { global $CONFIG; if (!$CONFIG['memory_enabled']) return; $pdo = getDB(); if (!$pdo) return; try { $stmt = $pdo->prepare("INSERT INTO admin.weval_mind_conversations (session_id, role, content, created_at) VALUES (?, ?, ?, NOW())"); $stmt->execute([$sessionId, $role, $content]); } catch (Exception $e) {} } function getConversationHistory($sessionId, $limit = 10) { global $CONFIG; if (!$CONFIG['memory_enabled']) return []; $pdo = getDB(); if (!$pdo) return []; try { $stmt = $pdo->prepare("SELECT role, content FROM admin.weval_mind_conversations WHERE session_id = ? ORDER BY created_at DESC LIMIT ?"); $stmt->execute([$sessionId, $limit]); return array_reverse($stmt->fetchAll()); } catch (Exception $e) { return []; } } function callProvider($providerKey, $messages, $options = []) { global $PROVIDERS, $CONFIG; $provider = $PROVIDERS[$providerKey] ?? null; if (!$provider) return ['success' => false, 'error' => 'Provider not found']; $apiKey = getApiKey($provider['config_key']); if (!$apiKey) return ['success' => false, 'error' => 'API key not configured']; $payload = [ 'model' => $options['model'] ?? $provider['model'], 'messages' => $messages, 'max_tokens' => $options['max_tokens'] ?? $CONFIG['max_tokens'], 'temperature' => $options['temperature'] ?? $CONFIG['temperature'], 'stream' => false ]; $headers = ['Content-Type: application/json', 'Authorization: Bearer ' . $apiKey]; if ($providerKey === 'openrouter') { $headers[] = 'HTTP-Referer: https://weval-consulting.com'; $headers[] = 'X-Title: WEVAL MIND'; } $ch = curl_init($provider['endpoint']); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_TIMEOUT => 60, CURLOPT_CONNECTTIMEOUT => 10 ]); $startTime = microtime(true); $response = curl_exec($ch); $duration = round((microtime(true) - $startTime) * 1000); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($error) return ['success' => false, 'error' => "cURL: $error", 'provider' => $providerKey]; if ($httpCode !== 200) return ['success' => false, 'error' => "HTTP $httpCode", 'provider' => $providerKey]; $data = json_decode($response, true); if (!$data || !isset($data['choices'][0]['message']['content'])) { return ['success' => false, 'error' => 'Invalid response', 'provider' => $providerKey]; } return [ 'success' => true, 'content' => $data['choices'][0]['message']['content'], 'provider' => $providerKey, 'provider_name' => $provider['name'], 'model' => $payload['model'], 'duration_ms' => $duration ]; } function callWithFailover($messages, $options = []) { global $PROVIDERS; $sorted = $PROVIDERS; uasort($sorted, fn($a, $b) => $a['priority'] <=> $b['priority']); $preferredProvider = $options['provider'] ?? null; $errors = []; if ($preferredProvider && isset($PROVIDERS[$preferredProvider])) { $result = callProvider($preferredProvider, $messages, $options); if ($result['success']) return $result; $errors[$preferredProvider] = $result['error']; } foreach ($sorted as $key => $provider) { if ($key === $preferredProvider) continue; $result = callProvider($key, $messages, $options); if ($result['success']) return $result; $errors[$key] = $result['error']; } return ['success' => false, 'error' => 'All providers failed', 'details' => $errors]; } if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success' => false, 'error' => 'POST method required']); exit; } $input = json_decode(file_get_contents('php://input'), true); if (!$input) $input = $_POST; $action = $input['action'] ?? 'chat'; switch ($action) { case 'chat': $message = trim($input['message'] ?? ''); $sessionId = $input['session_id'] ?? session_id(); $provider = $input['provider'] ?? null; $includeKB = $input['include_kb'] ?? true; if (empty($message)) { echo json_encode(['success' => false, 'error' => 'Message required']); exit; } $messages = [['role' => 'system', 'content' => $SYSTEM_PROMPT]]; if ($includeKB && $CONFIG['kb_enabled']) { $kbResults = searchKB($message, 3); if (!empty($kbResults)) { $kbContext = "\n\n📚 Contexte KB:\n"; foreach ($kbResults as $doc) { $kbContext .= "- [{$doc['category']}] {$doc['title']}: " . substr($doc['content'], 0, 500) . "...\n"; } $messages[0]['content'] .= $kbContext; } } $history = getConversationHistory($sessionId, 10); foreach ($history as $h) { $messages[] = ['role' => $h['role'], 'content' => $h['content']]; } $messages[] = ['role' => 'user', 'content' => $message]; $result = callWithFailover($messages, ['provider' => $provider]); if ($result['success']) { saveToMemory($sessionId, 'user', $message); saveToMemory($sessionId, 'assistant', $result['content']); echo json_encode([ 'success' => true, 'response' => $result['content'], 'provider' => $result['provider_name'], 'model' => $result['model'], 'duration_ms' => $result['duration_ms'], 'session_id' => $sessionId ]); } else { echo json_encode($result); } break; case 'providers': $providers = []; foreach ($PROVIDERS as $key => $p) { $hasKey = getApiKey($p['config_key']) !== null; $providers[$key] = ['name' => $p['name'], 'model' => $p['model'], 'priority' => $p['priority'], 'available' => $hasKey]; } echo json_encode(['success' => true, 'providers' => $providers]); break; case 'kb_search': $query = trim($input['query'] ?? ''); $limit = min(20, max(1, intval($input['limit'] ?? 5))); if (empty($query)) { echo json_encode(['success' => false, 'error' => 'Query required']); exit; } $results = searchKB($query, $limit); echo json_encode(['success' => true, 'results' => $results, 'count' => count($results)]); break; case 'stats': $pdo = getDB(); $stats = []; if ($pdo) { try { $stats['mta_servers'] = $pdo->query("SELECT COUNT(*) FROM admin.mta_servers WHERE status = 'active'")->fetchColumn(); $stats['smtp_accounts'] = $pdo->query("SELECT COUNT(*) FROM admin.smtp_accounts WHERE status = 'active'")->fetchColumn(); $stats['domains'] = $pdo->query("SELECT COUNT(*) FROM admin.domains WHERE status = 'active'")->fetchColumn(); $stats['kb_docs'] = $pdo->query("SELECT COUNT(*) FROM admin.knowledge_base")->fetchColumn(); } catch (Exception $e) {} } echo json_encode(['success' => true, 'stats' => $stats]); break; case 'clear_history': $sessionId = $input['session_id'] ?? session_id(); $pdo = getDB(); if ($pdo) { try { $stmt = $pdo->prepare("DELETE FROM admin.weval_mind_conversations WHERE session_id = ?"); $stmt->execute([$sessionId]); echo json_encode(['success' => true]); } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); } } break; default: echo json_encode(['success' => false, 'error' => 'Unknown action']); }