219 lines
9.6 KiB
PHP
Executable File
219 lines
9.6 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* WEVAL BRAIN - AI Provider Discovery & Management
|
|
* 26+ providers avec rotation intelligente
|
|
*/
|
|
|
|
$WEVAL_AI_PROVIDERS = [
|
|
// 🟢 GRATUITS ILLIMITÉS (Priorité 1-5)
|
|
'cerebras' => [
|
|
'name' => 'Cerebras', 'url' => 'https://api.cerebras.ai/v1/chat/completions',
|
|
'model' => 'llama3.1-8b', 'type' => 'FREE_UNLIMITED', 'priority' => 1,
|
|
'speed_ms' => 500, 'quality' => 8, 'context' => 8192, 'active' => true
|
|
],
|
|
'groq' => [
|
|
'name' => 'Groq', 'url' => 'https://api.groq.com/openai/v1/chat/completions',
|
|
'model' => 'llama-3.1-70b-versatile', 'type' => 'FREE_QUOTA', 'priority' => 2,
|
|
'speed_ms' => 800, 'quality' => 9, 'context' => 131072, 'limit' => '100k/day', 'active' => true
|
|
],
|
|
'deepseek' => [
|
|
'name' => 'DeepSeek', 'url' => 'https://api.deepseek.com/v1/chat/completions',
|
|
'model' => 'deepseek-chat', 'type' => 'FREE_QUOTA', 'priority' => 3,
|
|
'speed_ms' => 2000, 'quality' => 9, 'context' => 64000, 'active' => true
|
|
],
|
|
'sambanova' => [
|
|
'name' => 'SambaNova', 'url' => 'https://api.sambanova.ai/v1/chat/completions',
|
|
'model' => 'Meta-Llama-3.1-8B-Instruct', 'type' => 'FREE_UNLIMITED', 'priority' => 4,
|
|
'speed_ms' => 2000, 'quality' => 7, 'context' => 8192, 'active' => true
|
|
],
|
|
'gemini' => [
|
|
'name' => 'Google Gemini', 'url' => 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent',
|
|
'model' => 'gemini-1.5-flash', 'type' => 'FREE_QUOTA', 'priority' => 5,
|
|
'speed_ms' => 1500, 'quality' => 9, 'context' => 1000000, 'limit' => '60/min', 'active' => true
|
|
],
|
|
// 🟡 GRATUITS LIMITÉS (Priorité 6-15)
|
|
'cloudflare' => [
|
|
'name' => 'Cloudflare AI', 'url' => 'https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/run/@cf/meta/llama-3.1-8b-instruct',
|
|
'model' => 'llama-3.1-8b', 'type' => 'FREE_QUOTA', 'priority' => 6,
|
|
'speed_ms' => 700, 'quality' => 7, 'limit' => '10k/day', 'active' => true
|
|
],
|
|
'mistral' => [
|
|
'name' => 'Mistral', 'url' => 'https://api.mistral.ai/v1/chat/completions',
|
|
'model' => 'mistral-small-latest', 'type' => 'FREE_TRIAL', 'priority' => 7,
|
|
'speed_ms' => 2000, 'quality' => 8, 'active' => true
|
|
],
|
|
'cohere' => [
|
|
'name' => 'Cohere', 'url' => 'https://api.cohere.ai/v1/chat',
|
|
'model' => 'command-r', 'type' => 'FREE_QUOTA', 'priority' => 8,
|
|
'speed_ms' => 2000, 'quality' => 8, 'limit' => '1000/month', 'active' => true
|
|
],
|
|
'together' => [
|
|
'name' => 'Together AI', 'url' => 'https://api.together.xyz/v1/chat/completions',
|
|
'model' => 'meta-llama/Llama-3.3-70B-Instruct-Turbo', 'type' => 'FREE_CREDITS', 'priority' => 9,
|
|
'speed_ms' => 2000, 'quality' => 9, 'active' => true
|
|
],
|
|
'fireworks' => [
|
|
'name' => 'Fireworks', 'url' => 'https://api.fireworks.ai/inference/v1/chat/completions',
|
|
'model' => 'accounts/fireworks/models/llama-v3p1-70b-instruct', 'type' => 'FREE_CREDITS', 'priority' => 10,
|
|
'speed_ms' => 1500, 'quality' => 8, 'active' => true
|
|
],
|
|
'openrouter' => [
|
|
'name' => 'OpenRouter', 'url' => 'https://openrouter.ai/api/v1/chat/completions',
|
|
'model' => 'meta-llama/llama-3.1-8b-instruct:free', 'type' => 'FREE_MODELS', 'priority' => 11,
|
|
'speed_ms' => 2000, 'quality' => 7, 'active' => true
|
|
],
|
|
'huggingface' => [
|
|
'name' => 'HuggingFace', 'url' => 'https://api-inference.huggingface.co/models/meta-llama/Llama-3.2-3B-Instruct',
|
|
'model' => 'Llama-3.2-3B', 'type' => 'FREE_QUOTA', 'priority' => 12,
|
|
'speed_ms' => 3000, 'quality' => 6, 'active' => true
|
|
],
|
|
'novita' => [
|
|
'name' => 'Novita AI', 'url' => 'https://api.novita.ai/v3/openai/chat/completions',
|
|
'model' => 'llama-3.1-8b', 'type' => 'FREE_CREDITS', 'priority' => 13,
|
|
'speed_ms' => 2000, 'quality' => 7, 'active' => true
|
|
],
|
|
'hyperbolic' => [
|
|
'name' => 'Hyperbolic', 'url' => 'https://api.hyperbolic.xyz/v1/chat/completions',
|
|
'model' => 'meta-llama/Llama-3.3-70B-Instruct', 'type' => 'FREE_QUOTA', 'priority' => 14,
|
|
'speed_ms' => 2000, 'quality' => 8, 'active' => true
|
|
],
|
|
// 🔴 PAYANTS (Priorité 20+)
|
|
'openai' => [
|
|
'name' => 'OpenAI', 'url' => 'https://api.openai.com/v1/chat/completions',
|
|
'model' => 'gpt-4o-mini', 'type' => 'PAID', 'priority' => 20,
|
|
'speed_ms' => 2000, 'quality' => 10, 'active' => false
|
|
],
|
|
'anthropic' => [
|
|
'name' => 'Claude', 'url' => 'https://api.anthropic.com/v1/messages',
|
|
'model' => 'claude-3-5-sonnet', 'type' => 'PAID', 'priority' => 21,
|
|
'speed_ms' => 3000, 'quality' => 10, 'active' => false
|
|
],
|
|
// 🖥️ LOCAL
|
|
'ollama' => [
|
|
'name' => 'Ollama', 'url' => 'http://localhost:11434/api/chat',
|
|
'model' => 'llama3.2', 'type' => 'LOCAL', 'priority' => 30,
|
|
'speed_ms' => 5000, 'quality' => 7, 'active' => false
|
|
],
|
|
];
|
|
|
|
// Clés API depuis DB ou env
|
|
function getApiKeys() {
|
|
try {
|
|
$pdo = new PDO("pgsql:host=localhost;dbname=adx_system", "admin", "admin123");
|
|
$stmt = $pdo->query("SELECT config_key, config_value FROM admin.commonia_config WHERE config_key LIKE '%_api_key'");
|
|
$keys = [];
|
|
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
$keys[str_replace('_api_key', '', $row['config_key'])] = $row['config_value'];
|
|
}
|
|
return $keys;
|
|
} catch (Exception $e) {
|
|
return [
|
|
'cerebras' => 'csk-4wrrhkpr568ry9xx49k9mcynwdx483nx53dd62yh5xedfckh',
|
|
'groq' => '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',
|
|
'deepseek' => 'sk-a296c24f77a1405d8f80105982991203',
|
|
'gemini' => 'AIzaSyBt-qfLETGALpibigmgW-o4vlxQZWaxwcE',
|
|
];
|
|
}
|
|
}
|
|
|
|
class WevalBrain {
|
|
private $providers, $keys, $statusFile = '/tmp/weval_provider_status.json';
|
|
|
|
public function __construct() {
|
|
global $WEVAL_AI_PROVIDERS;
|
|
$this->providers = $WEVAL_AI_PROVIDERS;
|
|
$this->keys = getApiKeys();
|
|
}
|
|
|
|
public function callWithFailover($message, $system = '') {
|
|
foreach ($this->providers as $id => $p) {
|
|
if (!$p['active'] || empty($this->keys[$id])) continue;
|
|
$result = $this->call($id, $message, $system);
|
|
if ($result['success']) {
|
|
return array_merge($result, ['provider' => $id, 'model' => $p['model']]);
|
|
}
|
|
}
|
|
return ['success' => false, 'error' => 'All providers failed'];
|
|
}
|
|
|
|
public function call($id, $message, $system = '') {
|
|
$p = $this->providers[$id] ?? null;
|
|
if (!$p) return ['success' => false];
|
|
|
|
$key = $this->keys[$id] ?? '';
|
|
$start = microtime(true);
|
|
|
|
$payload = ['model' => $p['model'], 'messages' => [], 'max_tokens' => 2048];
|
|
if ($system) $payload['messages'][] = ['role' => 'system', 'content' => $system];
|
|
$payload['messages'][] = ['role' => 'user', 'content' => $message];
|
|
|
|
// Gemini format différent
|
|
if ($id === 'gemini') {
|
|
$url = $p['url'] . "?key=$key";
|
|
$payload = ['contents' => [['parts' => [['text' => ($system ? "$system\n\n" : "") . $message]]]]];
|
|
$headers = ['Content-Type: application/json'];
|
|
} else {
|
|
$url = $p['url'];
|
|
$headers = ['Content-Type: application/json', "Authorization: Bearer $key"];
|
|
}
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => $headers,
|
|
CURLOPT_TIMEOUT => 30
|
|
]);
|
|
$response = curl_exec($ch);
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
$duration = round((microtime(true) - $start) * 1000);
|
|
|
|
if ($code >= 200 && $code < 300) {
|
|
$data = json_decode($response, true);
|
|
$text = $id === 'gemini'
|
|
? ($data['candidates'][0]['content']['parts'][0]['text'] ?? null)
|
|
: ($data['choices'][0]['message']['content'] ?? null);
|
|
if ($text) return ['success' => true, 'response' => $text, 'duration_ms' => $duration];
|
|
}
|
|
return ['success' => false, 'error' => "HTTP $code", 'duration_ms' => $duration];
|
|
}
|
|
|
|
public function getList() {
|
|
$list = [];
|
|
foreach ($this->providers as $id => $p) {
|
|
$list[$id] = array_merge($p, ['has_key' => !empty($this->keys[$id])]);
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
public function testAll() {
|
|
$results = [];
|
|
foreach ($this->providers as $id => $p) {
|
|
if (!$p['active']) { $results[$id] = ['status' => 'inactive']; continue; }
|
|
$r = $this->call($id, 'Say OK');
|
|
$results[$id] = ['status' => $r['success'] ? 'ok' : 'error', 'ms' => $r['duration_ms'] ?? 0];
|
|
}
|
|
return $results;
|
|
}
|
|
}
|
|
|
|
// API Endpoint
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
|
$action = $_GET['action'] ?? $_POST['action'] ?? 'list';
|
|
$brain = new WevalBrain();
|
|
|
|
switch ($action) {
|
|
case 'list': echo json_encode(['success' => true, 'providers' => $brain->getList()]); break;
|
|
case 'test': echo json_encode(['success' => true, 'results' => $brain->testAll()]); break;
|
|
case 'chat':
|
|
$msg = $_POST['message'] ?? '';
|
|
$sys = $_POST['system_prompt'] ?? '';
|
|
echo json_encode($msg ? $brain->callWithFailover($msg, $sys) : ['error' => 'Message required']);
|
|
break;
|
|
default: echo json_encode(['error' => 'Unknown action']);
|
|
}
|
|
|