'WEVIA Multi-AI', 'providers' => [ 'ollama_qwen3' => ['status' => 'UP', 'model' => 'weval-brain-v3', 'speed' => 'fast', 'cost' => '0€'], 'ollama_gemma4' => ['status' => 'UP', 'model' => 'gemma4:e4b', 'speed' => 'fast', 'cost' => '0€'], 'deepseek_web' => ['status' => 'pending', 'model' => 'DeepSeek-V3', 'cost' => '0€', 'unlimited' => true], 'claude' => ['status' => 'key_needed', 'model' => 'claude-sonnet-4'], 'mistral' => ['status' => 'key_needed', 'model' => 'mistral-small'], ], 'modes' => ['auto','local','creative','deep','code'], ], JSON_PRETTY_PRINT); exit; } $secrets = []; foreach (file('/etc/weval/secrets.env', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES) as $l) { if (empty(trim($l)) || $l[0] === '#') continue; $p = strpos($l, '='); if ($p) $secrets[trim(substr($l, 0, $p))] = trim(substr($l, $p+1), " \t\"'"); } // Model selection by mode $models = [ 'auto' => 'weval-brain-v3', 'creative' => 'gemma4:e4b', 'deep' => 'weval-brain-v3', 'code' => 'weval-brain-v3', 'local' => 'weval-brain-v3', ]; $system_prompts = [ 'auto' => 'Tu es WEVIA Engine, IA souveraine de WEVAL Consulting. Réponds de façon précise et utile.', 'creative' => 'Tu es WEVIA Creative Engine. Écris avec style, créativité et profondeur. Français soutenu.', 'deep' => 'Tu es WEVIA DeepThink. Raisonne étape par étape. Analyse. Synthétise. Conclus.', 'code' => 'Tu es WEVCODE. Code COMPLET et FONCTIONNEL. Python/PHP/JS/SQL/Bash. Tests inclus.', ]; $selected_model = $model !== 'auto' ? $model : ($models[$mode] ?? 'weval-brain-v3'); $system = $system_prompts[$mode] ?? $system_prompts['auto']; // Try providers in order $providers = [ ['name' => 'Ollama', 'url' => 'http://127.0.0.1:11434/v1/chat/completions', 'key' => 'ollama', 'model' => $selected_model], ]; // Add external providers if keys exist if (!empty($secrets['ANTHROPIC_KEY'])) { $providers[] = ['name' => 'Claude', 'url' => 'https://api.anthropic.com/v1/messages', 'key' => $secrets['ANTHROPIC_KEY'], 'model' => 'claude-sonnet-4-20250514', 'format' => 'anthropic']; } if (!empty($secrets['MISTRAL_KEY'])) { $providers[] = ['name' => 'Mistral', 'url' => 'https://api.mistral.ai/v1/chat/completions', 'key' => $secrets['MISTRAL_KEY'], 'model' => 'mistral-small-latest']; } $t0 = microtime(true); foreach ($providers as $prov) { $ch = curl_init($prov['url']); $headers = ['Content-Type: application/json']; if (($prov['format'] ?? '') === 'anthropic') { $headers[] = 'x-api-key: ' . $prov['key']; $headers[] = 'anthropic-version: 2023-06-01'; $body = json_encode(['model' => $prov['model'], 'max_tokens' => 2000, 'system' => $system, 'messages' => [['role' => 'user', 'content' => $message]]]); } else { if ($prov['key'] !== 'ollama') $headers[] = 'Authorization: Bearer ' . $prov['key']; $body = json_encode(['model' => $prov['model'], 'messages' => [['role' => 'system', 'content' => $system], ['role' => 'user', 'content' => $message]], 'max_tokens' => 2000, 'temperature' => 0.7]); } curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_HTTPHEADER => $headers, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => false]); $resp = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($code === 200 && $resp) { $data = json_decode($resp, true); $content = ''; if (($prov['format'] ?? '') === 'anthropic') { $content = $data['content'][0]['text'] ?? ''; } else { $content = $data['choices'][0]['message']['content'] ?? ''; } if (!empty($content)) { echo json_encode([ 'content' => $content, 'provider' => $prov['name'], 'model' => $prov['model'], 'mode' => $mode, 'latency_ms' => round((microtime(true) - $t0) * 1000), 'cost' => 0, ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); exit; } } } echo json_encode(['error' => 'All providers failed', 'tried' => count($providers)]);