Files
wevads-platform/scripts/weval-mind-api.php
2026-02-26 04:53:11 +01:00

300 lines
13 KiB
PHP
Executable File

<?php
/**
* =====================================================
* WEVAL MIND - INTERNAL AI API v2.0
* =====================================================
* 🧠 AI Assistant for WEVAL Marketing Platform
* ✅ FULL KB ACCESS (141+ documents)
* Server: 89.167.40.150:5821
* =====================================================
*/
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
$CONFIG = [
'db' => ['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 = <<<PROMPT
Tu es WEVAL MIND, l'assistant IA intelligent de la plateforme WEVAL Marketing.
- WEVAL Consulting (weval-consulting.com) - Conseil IT, Recrutement, Marketing Digital
- WEVAL Marketing (cette plateforme) - Infrastructure Email Marketing & Automation
- Serveur App Principal: 89.167.40.150:5821 (Hetzner, Ubuntu)
- Serveur Tracking: 151.80.235.110 (OVH)
- Serveur Consulting: 46.62.220.135 (Hetzner)
- Base de données: PostgreSQL adx_system (admin/admin123)
- Schémas DB: admin, clients, mta, automation, leads
- PowerMTA: Versions 4.0r8, 4.5r8, 5.0r1, 5.0r3
- Office 365: 1,352 comptes actifs, 1,182 domaines
- Brain Engine: 51,246 seeds pour auto-learning
- Offers actives: 32 offres affiliées, 344 créatives
WEVAL MIND (IA), WEVAL SEND (Delivery), WEVAL TRACK (Analytics), WEVAL CLOUD (Infrastructure), WEVAL DNS (Domaines), WEVAL CONNECT (O365), WEVAL STUDIO (Templates), WEVAL DATA (Listes), WEVAL ADS (Affiliés), WEVAL PULSE (Monitoring)
PROMPT;
function getDB() {
global $CONFIG;
static $pdo = null;
if ($pdo === null) {
try {
$pdo = new PDO("pgsql:host={$CONFIG['db']['host']};dbname={$CONFIG['db']['name']}",
$CONFIG['db']['user'], $CONFIG['db']['pass'],
[PDO::ATTR_ERRMODE => 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']);
}