285 lines
11 KiB
PHP
Executable File
285 lines
11 KiB
PHP
Executable File
|
|
<?php
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }
|
|
|
|
// Charger le cerveau
|
|
$brainPath = __DIR__ . '/../commonia/commonia-brain.php';
|
|
if (file_exists($brainPath)) require_once $brainPath;
|
|
|
|
// Charger les tools
|
|
$toolsAvailable = false;
|
|
$toolsPath = __DIR__ . '/../commonia/tools/ia-tools.php';
|
|
if (file_exists($toolsPath)) { require_once $toolsPath; $toolsAvailable = true; }
|
|
|
|
// DB
|
|
try {
|
|
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
} catch (Exception $e) {
|
|
echo json_encode(['success' => false, 'error' => 'DB Error']); exit;
|
|
}
|
|
|
|
// Config
|
|
$config = [];
|
|
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) {}
|
|
|
|
// Input - supporter JSON et FormData
|
|
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
|
|
if (strpos($contentType, 'application/json') !== false) {
|
|
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
|
} else {
|
|
$input = $_POST;
|
|
}
|
|
|
|
$message = trim($input['message'] ?? '');
|
|
$provider = $input['provider'] ?? $config['default_provider'] ?? 'cerebras';
|
|
|
|
if (empty($message)) {
|
|
echo json_encode(['success' => false, 'error' => 'Message vide']);
|
|
exit;
|
|
}
|
|
|
|
$startTime = microtime(true);
|
|
$msgLower = mb_strtolower($message);
|
|
$artifacts = [];
|
|
$aiResponse = '';
|
|
$autoGenerated = false;
|
|
$kbUsed = false;
|
|
$kbContext = '';
|
|
|
|
// ===== KNOWLEDGE BASE =====
|
|
// Ne pas utiliser KB pour ollama_mini (trop lent)
|
|
if (true) {
|
|
try {
|
|
$kbStmt = $pdo->query("SELECT content, title FROM admin.commonia_knowledge ORDER BY created_at DESC LIMIT 10");
|
|
$kbDocs = $kbStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
if (!empty($kbDocs)) {
|
|
$kbContext = "\n\n[KNOWLEDGE BASE WEVAL]:\n";
|
|
foreach ($kbDocs as $doc) {
|
|
$kbContext .= "- " . ($doc['title'] ?? 'Doc') . ": " . substr($doc['content'], 0, 500) . "\n";
|
|
}
|
|
$kbUsed = true;
|
|
}
|
|
} catch (Exception $e) {
|
|
// KB pas disponible, continuer sans
|
|
}
|
|
}
|
|
|
|
// ===== DETECTION GENERATION DOCUMENTS =====
|
|
if ($toolsAvailable && class_exists('IATools')) {
|
|
|
|
// PDF / Document / Architecture / Schema - AVEC KB COMPLÈTE (Articles + QA)
|
|
if (preg_match('/(pdf|pd|schema|schéma|architecture|architec|document|doc|rapport)/iu', $msgLower) &&
|
|
preg_match('/(génère|genere|générer|generer|créer|creer|créé|cree|fais|faire|veux|veu|veut|envoi|envoie|donne|détail|detail)/iu', $msgLower)) {
|
|
|
|
// 1. Récupérer le contexte KB COMPLET (Articles + QA)
|
|
$kbContext = '';
|
|
try {
|
|
// Articles pertinents
|
|
$searchTerms = preg_split('/\s+/', $message);
|
|
$searchPattern = '%' . implode('%', $searchTerms) . '%';
|
|
|
|
$stmtArticles = $pdo->prepare("
|
|
SELECT title, description, content, category
|
|
FROM admin.commonia_articles
|
|
WHERE title ILIKE ? OR description ILIKE ? OR content ILIKE ? OR category ILIKE ?
|
|
LIMIT 5
|
|
");
|
|
$stmtArticles->execute([$searchPattern, $searchPattern, $searchPattern, $searchPattern]);
|
|
$articles = $stmtArticles->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
if (!empty($articles)) {
|
|
$kbContext .= "\n=== ARTICLES KB ===\n";
|
|
foreach ($articles as $art) {
|
|
$kbContext .= "📄 {$art['title']} [{$art['category']}]\n";
|
|
$kbContext .= substr($art['content'] ?? $art['description'] ?? '', 0, 800) . "\n\n";
|
|
}
|
|
}
|
|
|
|
// QA pertinents
|
|
$stmtQA = $pdo->prepare("
|
|
SELECT question, answer, category
|
|
FROM admin.commonia_knowledge
|
|
WHERE question ILIKE ? OR answer ILIKE ? OR category ILIKE ?
|
|
LIMIT 10
|
|
");
|
|
$stmtQA->execute([$searchPattern, $searchPattern, $searchPattern]);
|
|
$qas = $stmtQA->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
if (!empty($qas)) {
|
|
$kbContext .= "\n=== QA KB ===\n";
|
|
foreach ($qas as $qa) {
|
|
$kbContext .= "❓ {$qa['question']}\n✅ " . substr($qa['answer'], 0, 500) . "\n\n";
|
|
}
|
|
}
|
|
|
|
$kbUsed = !empty($articles) || !empty($qas);
|
|
} catch (Exception $e) {
|
|
$kbContext = '';
|
|
}
|
|
|
|
// 2. Demander à l'IA de RÉFLÉCHIR puis GÉNÉRER avec KB
|
|
$brain = new HamidBrain();
|
|
$contentPrompt = "Tu dois créer un document HTML professionnel et TRÈS DÉTAILLÉ sur: '$message'
|
|
|
|
=== PROCESSUS DE RÉFLEXION ===
|
|
Avant de générer, réfléchis:
|
|
1. ANALYSE: Que demande exactement l'utilisateur?
|
|
2. CONTEXTE: Utilise les informations de la Knowledge Base ci-dessous
|
|
3. STRUCTURE: Quelles sections sont nécessaires?
|
|
4. CONTENU: Minimum 5000 mots, au moins 15 pages, données concrètes
|
|
|
|
$kbContext
|
|
|
|
=== DONNÉES WEVAL À INCLURE ===
|
|
- Serveur: 89.167.40.150 (Hetzner Cloud, Ubuntu 24.04, 16GB RAM)
|
|
- WEVAL: port 5821, FMGAPP: port 5822, BCGAPP: port 5823
|
|
- Base: PostgreSQL (adx_system, adx_clients)
|
|
- Email: PowerMTA, Office 365 automation
|
|
- IA: WEVAL MIND avec 11 providers (Cerebras, Groq, DeepSeek, etc.)
|
|
|
|
=== FORMAT HTML REQUIS ===
|
|
- Structure: <h1>, <h2>, <h3> pour titres
|
|
- Tableaux: <table><tr><th>/<td> pour données
|
|
- Listes: <ul><li> pour énumérations
|
|
- Sections: Introduction, Architecture, Composants, Configuration, Sécurité, Conclusion
|
|
- CSS inline pour style professionnel
|
|
|
|
Retourne UNIQUEMENT le HTML (pas de markdown, pas de ```).";
|
|
|
|
$aiResult = $brain->callWithFallback($contentPrompt, $kbContext, $provider);
|
|
|
|
if ($aiResult['success'] && !empty($aiResult['response'])) {
|
|
$richContent = $aiResult['response'];
|
|
$richContent = preg_replace('/^```html?\s*/i', '', $richContent);
|
|
$richContent = preg_replace('/```\s*$/', '', $richContent);
|
|
} else {
|
|
$richContent = method_exists('IATools', 'getArchitectureContent') ? IATools::getArchitectureContent() : '<h1>Architecture WEVAL</h1><p>Système email marketing</p>';
|
|
}
|
|
|
|
// 3. Générer le PDF
|
|
$result = IATools::generate_pdf($richContent, 'Architecture_WEVAL_' . date('Ymd_His'));
|
|
if ($result['success']) {
|
|
$result['type'] = 'pdf';
|
|
$result['title'] = 'Architecture WEVAL';
|
|
$artifacts[] = $result;
|
|
$aiResponse = "✅ Voici votre document PDF.\n\n📄 **Fichier:** [{$result['file']}]({$result['url']})";
|
|
$autoGenerated = true;
|
|
}
|
|
}
|
|
// POWERPOINT
|
|
elseif (preg_match('/(ppt|powerpoint|présentation|presentation|diapo)/iu', $msgLower) &&
|
|
preg_match('/(génère|genere|créer|creer|fais|faire|veux|envoi|donne)/iu', $msgLower)) {
|
|
$result = IATools::generate_pptx(null, 'Presentation_WEVAL_' . date('Ymd_His'));
|
|
if ($result['success']) {
|
|
$result['type'] = 'presentation';
|
|
$result['title'] = 'Présentation WEVAL';
|
|
$artifacts[] = $result;
|
|
$aiResponse = "✅ Voici votre présentation PowerPoint.\n\n📊 **Fichier:** [{$result['file']}]({$result['url']})";
|
|
$autoGenerated = true;
|
|
}
|
|
}
|
|
|
|
// EXCEL
|
|
elseif (preg_match('/(excel|xlsx|tableur|feuille.*calcul)/iu', $msgLower) &&
|
|
preg_match('/(génère|genere|créer|creer|fais|faire|veux|envoi|donne)/iu', $msgLower)) {
|
|
$result = IATools::generate_xlsx(null, 'Rapport_WEVAL_' . date('Ymd_His'));
|
|
if ($result['success']) {
|
|
$result['type'] = 'spreadsheet';
|
|
$result['title'] = 'Rapport Excel';
|
|
$artifacts[] = $result;
|
|
$aiResponse = "✅ Voici votre fichier Excel.\n\n📈 **Fichier:** [{$result['file']}]({$result['url']})";
|
|
$autoGenerated = true;
|
|
}
|
|
}
|
|
|
|
// WORD
|
|
elseif (preg_match('/(word|docx|doc\b)/iu', $msgLower) &&
|
|
preg_match('/(génère|genere|créer|creer|fais|faire|veux|envoi|donne)/iu', $msgLower)) {
|
|
$result = IATools::generate_docx('', 'Document_WEVAL_' . date('Ymd_His'));
|
|
if ($result['success']) {
|
|
$result['type'] = 'document';
|
|
$result['title'] = 'Document Word';
|
|
$artifacts[] = $result;
|
|
$aiResponse = "✅ Voici votre document Word.\n\n📝 **Fichier:** [{$result['file']}]({$result['url']})";
|
|
$autoGenerated = true;
|
|
}
|
|
}
|
|
|
|
// QR CODE
|
|
elseif (preg_match('/(qr|qrcode)/iu', $msgLower)) {
|
|
$url = 'https://wevads.com';
|
|
if (preg_match('/https?:\/\/[^\s]+/', $message, $m)) $url = $m[0];
|
|
$result = IATools::generate_qrcode($url);
|
|
if ($result['success']) {
|
|
$result['type'] = 'image';
|
|
$result['title'] = 'QR Code';
|
|
$artifacts[] = $result;
|
|
$aiResponse = "✅ QR Code généré pour: $url\n\n🔲 **Fichier:** [{$result['file']}]({$result['url']})";
|
|
$autoGenerated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ===== APPEL IA =====
|
|
if (!$autoGenerated) {
|
|
if (class_exists('HamidBrain')) {
|
|
try {
|
|
$brain = new HamidBrain();
|
|
// Ajouter le contexte KB au message
|
|
$fullMessage = $message;
|
|
if ($kbUsed && !empty($kbContext)) {
|
|
$fullMessage = $message . $kbContext;
|
|
}
|
|
$response = $brain->callProvider($provider, $fullMessage, '');
|
|
if ($response['success']) {
|
|
$aiResponse = $response['response'];
|
|
} else {
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => $response['error'] ?? 'Erreur provider',
|
|
'provider' => strtoupper($provider)
|
|
]);
|
|
exit;
|
|
}
|
|
} catch (Exception $e) {
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => $e->getMessage(),
|
|
'provider' => strtoupper($provider)
|
|
]);
|
|
exit;
|
|
}
|
|
} else {
|
|
$aiResponse = "⚠️ Cerveau IA non chargé. Vérifiez /commonia/commonia-brain.php";
|
|
}
|
|
}
|
|
|
|
// === PARSING THINKING ===
|
|
$thinking = null;
|
|
if (preg_match("/<thinking>(.*?)<\/thinking>/s", $aiResponse, $thinkMatch)) {
|
|
$thinking = trim($thinkMatch[1]);
|
|
$aiResponse = trim(preg_replace("/<thinking>.*?<\/thinking>/s", "", $aiResponse));
|
|
}
|
|
// === FIN PARSING ===
|
|
$duration = round((microtime(true) - $startTime) * 1000);
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'response' => trim($aiResponse),
|
|
'thinking' => $thinking,
|
|
'provider' => strtoupper($provider),
|
|
'duration_ms' => $duration,
|
|
'kb_used' => $kbUsed,
|
|
'artifacts' => $artifacts,
|
|
'tools_used' => $autoGenerated
|
|
]);
|
|
|