Files
html/api/l99-chat.php
2026-04-16 02:28:32 +02:00

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]
";