208 lines
7.7 KiB
PHP
Executable File
208 lines
7.7 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* HAMID Providers Config — Auto-loads from DB
|
|
* Required by: hamid.php, hamid-api.php
|
|
*/
|
|
|
|
function getHamidDB() {
|
|
static $pdo = null;
|
|
if (!$pdo) {
|
|
$pdo = new PDO("pgsql:host=localhost;port=5432;dbname=adx_system", "admin", "admin123");
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
}
|
|
return $pdo;
|
|
}
|
|
|
|
function getProviders() {
|
|
$pdo = getHamidDB();
|
|
return $pdo->query("SELECT * FROM admin.hamid_providers WHERE is_active = true AND api_key != '' AND api_key IS NOT NULL ORDER BY priority")->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
function getProvider($name) {
|
|
$pdo = getHamidDB();
|
|
$stmt = $pdo->prepare("SELECT * FROM admin.hamid_providers WHERE LOWER(provider_name) = LOWER(?) AND is_active = true");
|
|
$stmt->execute([$name]);
|
|
return $stmt->fetch(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
function getBrainWinners($isp = null) {
|
|
$pdo = getHamidDB();
|
|
$sql = "SELECT bw.*, bc.* FROM admin.brain_winners bw LEFT JOIN admin.brain_configs bc ON bw.config_id = bc.id WHERE bw.is_active = true";
|
|
if ($isp) {
|
|
$stmt = $pdo->prepare($sql . " AND LOWER(bw.isp_target) = LOWER(?) ORDER BY bw.inbox_rate DESC LIMIT 5");
|
|
$stmt->execute([$isp]);
|
|
} else {
|
|
$stmt = $pdo->query($sql . " ORDER BY bw.inbox_rate DESC LIMIT 10");
|
|
}
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
function getBrainConfigs() {
|
|
$pdo = getHamidDB();
|
|
return $pdo->query("SELECT * FROM admin.brain_configs ORDER BY id")->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
function callProvider($provider, $message, $systemPrompt = '') {
|
|
$name = strtolower($provider['provider_name']);
|
|
$apiKey = $provider['api_key'];
|
|
$model = $provider['model'];
|
|
$url = $provider['api_url'];
|
|
|
|
if (empty($apiKey) && !in_array($name, ['ollama', 'hamid engine'])) return ['error' => 'No API key'];
|
|
|
|
$timeout = 15;
|
|
|
|
// Build system prompt with Brain knowledge
|
|
if (empty($systemPrompt)) {
|
|
$brainWinners = getBrainWinners();
|
|
$brainSummary = '';
|
|
foreach ($brainWinners as $w) {
|
|
$brainSummary .= "- ISP: {$w['isp_target']}, Inbox: {$w['inbox_rate']}%, Config #{$w['config_id']}, Confidence: {$w['confidence_level']}\n";
|
|
}
|
|
$systemPrompt = "Tu es HAMID, assistant IA spécialisé DELIVERADS (envoi email, delivrabilité, configurations Brain).
|
|
Tu connais les configurations winning actuelles du Brain Engine:
|
|
$brainSummary
|
|
Tu donnes des conseils concrets sur les configurations, ISPs, headers, et stratégies d'envoi.";
|
|
}
|
|
|
|
// Gemini has different API format
|
|
if ($name === 'gemini') {
|
|
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
|
|
$payload = json_encode([
|
|
'contents' => [
|
|
['parts' => [['text' => $systemPrompt . "\n\nUser: " . $message]]]
|
|
]
|
|
]);
|
|
$headers = ['Content-Type: application/json'];
|
|
}
|
|
// Ollama / HAMID Engine (local)
|
|
elseif (in_array($name, ['ollama', 'hamid engine'])) {
|
|
$url = 'http://127.0.0.1:11434/api/chat';
|
|
$payload = json_encode([
|
|
'model' => $model,
|
|
'messages' => [
|
|
['role' => 'system', 'content' => $systemPrompt],
|
|
['role' => 'user', 'content' => $message]
|
|
],
|
|
'stream' => false
|
|
]);
|
|
$headers = ['Content-Type: application/json'];
|
|
$timeout = 30;
|
|
}
|
|
// Claude has different format
|
|
elseif ($name === 'claude') {
|
|
$payload = json_encode([
|
|
'model' => $model,
|
|
'max_tokens' => 1024,
|
|
'system' => $systemPrompt,
|
|
'messages' => [['role' => 'user', 'content' => $message]]
|
|
]);
|
|
$headers = [
|
|
'Content-Type: application/json',
|
|
'x-api-key: ' . $apiKey,
|
|
'anthropic-version: 2023-06-01'
|
|
];
|
|
}
|
|
// Standard OpenAI-compatible
|
|
else {
|
|
$payload = json_encode([
|
|
'model' => $model,
|
|
'messages' => [
|
|
['role' => 'system', 'content' => $systemPrompt],
|
|
['role' => 'user', 'content' => $message]
|
|
],
|
|
'max_tokens' => 1024,
|
|
'temperature' => 0.7
|
|
]);
|
|
$headers = [
|
|
'Content-Type: application/json',
|
|
'Authorization: Bearer ' . $apiKey
|
|
];
|
|
}
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => $payload,
|
|
CURLOPT_HTTPHEADER => $headers,
|
|
CURLOPT_TIMEOUT => $timeout,
|
|
CURLOPT_CONNECTTIMEOUT => 5,
|
|
CURLOPT_SSL_VERIFYPEER => false
|
|
]);
|
|
|
|
$start = microtime(true);
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$latency = round((microtime(true) - $start) * 1000);
|
|
curl_close($ch);
|
|
|
|
if (!$response || $httpCode >= 400) {
|
|
return ['error' => "HTTP $httpCode", 'latency' => $latency];
|
|
}
|
|
|
|
$data = json_decode($response, true);
|
|
|
|
// Extract text based on provider format
|
|
$text = '';
|
|
if ($name === 'gemini') {
|
|
$text = $data['candidates'][0]['content']['parts'][0]['text'] ?? '';
|
|
} elseif (in_array($name, ['ollama', 'hamid engine'])) {
|
|
$text = $data['message']['content'] ?? '';
|
|
} elseif ($name === 'claude') {
|
|
$text = $data['content'][0]['text'] ?? '';
|
|
} else {
|
|
$text = $data['choices'][0]['message']['content'] ?? '';
|
|
}
|
|
|
|
return [
|
|
'response' => $text,
|
|
'provider' => $provider['provider_name'],
|
|
'model' => $model,
|
|
'latency' => $latency,
|
|
'http_code' => $httpCode
|
|
];
|
|
}
|
|
|
|
function callWithFailover($message, $preferredProvider = null, $systemPrompt = '') {
|
|
$providers = getProviders();
|
|
|
|
// Put preferred first
|
|
if ($preferredProvider) {
|
|
usort($providers, function($a, $b) use ($preferredProvider) {
|
|
if (strtolower($a['provider_name']) === strtolower($preferredProvider)) return -1;
|
|
if (strtolower($b['provider_name']) === strtolower($preferredProvider)) return 1;
|
|
return $a['priority'] - $b['priority'];
|
|
});
|
|
}
|
|
|
|
$errors = [];
|
|
foreach ($providers as $p) {
|
|
$result = callProvider($p, $message, $systemPrompt);
|
|
if (!isset($result['error']) && !empty($result['response'])) {
|
|
logTokenUsage($p["provider_name"], $result); return $result;
|
|
}
|
|
$errors[] = $p['provider_name'] . ': ' . ($result['error'] ?? 'empty response');
|
|
}
|
|
|
|
$extras = getFactoryAccounts(); foreach($extras as $ex) { $r2=callProvider(['provider_name'=>$ex['provider_name'],'api_key'=>$ex['api_key'],'model'=>$ex['model'],'api_url'=>$ex['api_url']], $message, $systemPrompt); if(!isset($r2['error'])&&!empty($r2['response'])){logTokenUsage($ex['provider_name'],$r2);return $r2;} } return ['error'=>'All providers failed','details'=>$errors];
|
|
}
|
|
|
|
function logTokenUsage($provider, $result) {
|
|
try {
|
|
$pdo = getHamidDB();
|
|
$tok = (int)(strlen($result['response'] ?? '')/4);
|
|
$lat = (int)($result['latency'] ?? 0);
|
|
$stmt = $pdo->prepare("INSERT INTO admin.ia_token_usage_log(provider_name,tokens_total,latency_ms,success) VALUES(?,?,?,true)");
|
|
$stmt->execute([$provider, $tok, $lat]);
|
|
} catch (Exception $e) {}
|
|
}
|
|
|
|
function getFactoryAccounts() {
|
|
try {
|
|
$pdo = getHamidDB();
|
|
return $pdo->query("SELECT id,provider_name,api_key,model,api_url FROM admin.ia_provider_accounts WHERE status='active' AND api_key IS NOT NULL AND LENGTH(api_key)>5 AND (cooldown_until IS NULL OR cooldown_until<NOW()) AND requests_today<requests_limit_daily ORDER BY priority,success_rate DESC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
|
|
} catch (Exception $e) { return []; }
|
|
}
|
|
?>
|