99 lines
3.6 KiB
PHP
99 lines
3.6 KiB
PHP
<?php
|
|
require_once __DIR__.'/weval-brand-guard.php';
|
|
header('Content-Type: text/event-stream');
|
|
header('Cache-Control: no-cache');
|
|
header('X-Accel-Buffering: no');
|
|
header('Access-Control-Allow-Origin: *');
|
|
if(ob_get_level())ob_end_clean();
|
|
|
|
$token=$_GET['token']??'';
|
|
if($token!=='L99CHAT2026'){echo "data: ".json_encode(['t'=>'Auth required'])."
|
|
|
|
data: [DONE]
|
|
|
|
";exit;}
|
|
$q=$_GET['q']??'';
|
|
if(!$q){echo "data: ".json_encode(['t'=>'No query'])."
|
|
|
|
data: [DONE]
|
|
|
|
";exit;}
|
|
|
|
$env=[];
|
|
foreach(file('/etc/weval/secrets.env',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES) as $l){
|
|
if($l[0]==='#'||!strpos($l,'='))continue;
|
|
[$k,$v]=explode('=',$l,2);
|
|
$env[trim($k)]=trim($v,'" ');
|
|
}
|
|
|
|
$sys="'.WEVAL_BRAND_CONTEXT.'Tu es L99 Brain, l'IA souveraine de WEVAL Consulting. Expert DevOps, Lean Six Sigma, architecture cloud. Reponds en francais, concis et actionnable.";
|
|
$msgs=[['role'=>'system','content'=>$sys],['role'=>'user','content'=>$q]];
|
|
|
|
// Cascade: Groq → Cerebras → Ollama
|
|
$providers=[
|
|
['n'=>'SambaNova','u'=>'https://api.sambanova.ai/v1/chat/completions','k'=>$env['SAMBANOVA_KEY']??'','m'=>'Llama-4-Maverick-17B-128E-Instruct'],
|
|
['n'=>'SambaNova','u'=>'https://api.sambanova.ai/v1/chat/completions','k'=>$env['SAMBANOVA_KEY']??'','m'=>'Meta-Llama-3.3-70B-Instruct'],
|
|
['n'=>'Groq','u'=>'https://api.groq.com/openai/v1/chat/completions','k'=>$env['GROQ_KEY']??'','m'=>'moonshotai/kimi-k2-instruct'],
|
|
['n'=>'Mistral','u'=>'https://api.mistral.ai/v1/chat/completions','k'=>$env['MISTRAL_KEY']??'','m'=>'mistral-small-latest'],
|
|
['n'=>'Cerebras','u'=>'https://api.cerebras.ai/v1/chat/completions','k'=>$env['CEREBRAS_API_KEY']??'','m'=>'qwen-3-235b-a22b-instruct-2507'],
|
|
['n'=>'Groq','u'=>'https://api.groq.com/openai/v1/chat/completions','k'=>$env['GROQ_KEY']??'','m'=>'llama-3.3-70b-versatile'],
|
|
];
|
|
|
|
foreach($providers as $p){
|
|
if(!$p['k'])continue;
|
|
$ch=curl_init($p['u']);
|
|
curl_setopt_array($ch,[
|
|
CURLOPT_POST=>1,
|
|
CURLOPT_POSTFIELDS=>json_encode(['model'=>$p['m'],'messages'=>$msgs,'stream'=>true,'max_tokens'=>1500]),
|
|
CURLOPT_HTTPHEADER=>['Content-Type: application/json','Authorization: Bearer '.$p['k']],
|
|
CURLOPT_RETURNTRANSFER=>0,CURLOPT_TIMEOUT=>25,
|
|
CURLOPT_WRITEFUNCTION=>function($c,$d)use($p){
|
|
foreach(explode("
|
|
",$d) as $line){
|
|
$line=trim($line);
|
|
if(!$line||$line==='data: [DONE]')continue;
|
|
if(strpos($line,'data: ')===0)$line=substr($line,6);
|
|
$j=@json_decode($line,1);
|
|
if(!$j)continue;
|
|
$t=$j['choices'][0]['delta']['content']??'';
|
|
if($t){echo "data: ".json_encode(['t'=>$t,'p'=>$p['n']])."
|
|
|
|
";@ob_flush();flush();}
|
|
}
|
|
return strlen($d);
|
|
}
|
|
]);
|
|
$ok=curl_exec($ch);
|
|
$code=curl_getinfo($ch,CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
if($code>=200&&$code<400){echo "data: [DONE]
|
|
|
|
";exit;}
|
|
}
|
|
|
|
// Fallback: Ollama local
|
|
$ch2=curl_init('http://127.0.0.1:11434/api/chat');
|
|
curl_setopt_array($ch2,[
|
|
CURLOPT_POST=>1,
|
|
CURLOPT_POSTFIELDS=>json_encode(['model'=>'qwen3:8b','messages'=>$msgs,'stream'=>true]),
|
|
CURLOPT_HTTPHEADER=>['Content-Type: application/json'],
|
|
CURLOPT_RETURNTRANSFER=>0,CURLOPT_TIMEOUT=>30,
|
|
CURLOPT_WRITEFUNCTION=>function($c,$d){
|
|
foreach(explode("
|
|
",$d) as $line){
|
|
$j=@json_decode(trim($line),1);
|
|
if($j&&isset($j['message']['content'])){
|
|
echo "data: ".json_encode(['t'=>$j['message']['content'],'p'=>'Ollama'])."
|
|
|
|
";
|
|
@ob_flush();flush();
|
|
}
|
|
}
|
|
return strlen($d);
|
|
}
|
|
]);
|
|
curl_exec($ch2);curl_close($ch2);
|
|
echo "data: [DONE]
|
|
|
|
";
|