Files
wevia-brain/wv-llm-helper.php
2026-04-12 23:01:36 +02:00

59 lines
2.6 KiB
PHP

<?php
/**
* wv_llm() — Sovereign LLM cascade for WEVIA Master intents
* Cascade: Groq → Cerebras → Mistral → Ollama local (0€)
*/
function wv_llm($prompt, $system = "Tu es WEVIA, IA souveraine de WEVAL Consulting.") {
static $keys = null;
if (!$keys) {
$env = @file_get_contents("/etc/weval/secrets.env");
$keys = [];
if (preg_match("/GROQ_KEY=(.+)/", $env, $m)) $keys["groq"] = trim($m[1]);
if (preg_match("/CEREBRAS_API_KEY=(.+)/", $env, $m)) $keys["cerebras"] = trim($m[1]);
if (preg_match("/MISTRAL_KEY=(.+)/", $env, $m)) $keys["mistral"] = trim($m[1]);
}
$msgs = [["role" => "system", "content" => $system], ["role" => "user", "content" => $prompt]];
// CASCADE: try each provider
$providers = [
["url" => "https://api.groq.com/openai/v1/chat/completions", "key" => $keys["groq"] ?? "", "model" => "llama-3.3-70b-versatile", "name" => "groq"],
["url" => "https://api.cerebras.ai/v1/chat/completions", "key" => $keys["cerebras"] ?? "", "model" => "llama3.1-8b", "name" => "cerebras"],
["url" => "https://api.mistral.ai/v1/chat/completions", "key" => $keys["mistral"] ?? "", "model" => "open-mistral-7b", "name" => "mistral"],
["url" => "http://127.0.0.1:11435/api/chat", "key" => "", "model" => "qwen3:4b", "name" => "ollama"]
];
foreach ($providers as $p) {
if (!$p["key"] && $p["name"] !== "ollama") continue;
if ($p["name"] === "ollama") {
// Ollama uses different format
$data = json_encode(["model" => $p["model"], "messages" => $msgs, "stream" => false]);
$headers = ["Content-Type: application/json"];
} else {
$data = json_encode(["model" => $p["model"], "messages" => $msgs, "max_tokens" => 1500]);
$headers = ["Content-Type: application/json", "Authorization: Bearer " . $p["key"]];
}
$ch = curl_init($p["url"]);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 20,
CURLOPT_SSL_VERIFYPEER => false
]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code === 200) {
$d = @json_decode($r, true);
$content = $d["choices"][0]["message"]["content"] ?? ($d["message"]["content"] ?? null);
if ($content) return $content;
}
// 429 or error → try next provider
}
return "LLM cascade: tous les providers occupes";
}