namespace gigachat;
class Gigachat{
protected const CLIENT_AUTH = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //сгенерировать в ЛК https://developers.sber.ru/studio/workspaces/ (Значения Client Id и Client Secret, закодированные в Base 64)
protected static $instance;
private static $token = false; //токен на полчаса
private static $tokenExp = false; //когда истекает токен
private static $messages = []; //история переписки с гигачатом
private function __construct(){
}
private function __clone(){
}
private function __wakeup(){
}
public static function getInstance(){
if (is_null(self::$instance)) {
self::$instance = new self;
self::$token = \COption::GetOptionString("main", "GIGACHAT_TOKEN");
self::$tokenExp = \COption::GetOptionString("main", "GIGACHAT_TOKEN_EXP");
}
self::$messages = [];
return self::$instance;
}
public static function getHistory(){
return self::$messages;
}
public static function clearHistory(){
self::$messages = [];
}
public static function updateHistory($messages){
self::$messages = $messages;
}
private static function get($url, $headers, $data){
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => 1,
]);
if(!empty($data)){
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
$result = curl_exec($curl);
return json_decode($result,true);
}
private static function guidv4($data = null) {
// Generate 16 bytes (128 bits) of random data or use the data passed into the function.
$data = $data ?? random_bytes(16);
assert(strlen($data) == 16);
// Set version to 0100
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
// Set bits 6-7 to 10
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
// Output the 36 character UUID.
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
private static function getToken(){
$now = time()-300;
if(!self::$token || !self::$tokenExp || (self::$tokenExp > $now)){
$url = "https://ngw.devices.sberbank.ru:9443/api/v2/oauth"; // шаг 2 https://developers.sber.ru/docs/ru/gigachat/api/authorization
$headers = [
'Authorization: Bearer ' .self::CLIENT_AUTH,
'RqUID: '.self::guidv4(), //генерируем уникальный UUID
'Content-Type: application/x-www-form-urlencoded'
];
$data = [
'scope'=>'GIGACHAT_API_PERS'
];
$result = self::get($url, $headers, http_build_query($data));
if(!empty($result["access_token"])){
self::$token = $result["access_token"];
\COption::SetOptionString("main","GIGACHAT_TOKEN",self::$token);
self::$tokenExp = $result["expires_at"];
\COption::SetOptionString("main","GIGACHAT_TOKEN_EXP",self::$tokenExp);
}
else{
self::$token = false;
\COption::SetOptionString("main","GIGACHAT_TOKEN","");
self::$tokenExp = false;
\COption::SetOptionString("main","GIGACHAT_TOKEN_EXP","");
}
}
return self::$token;
}
public static function ask($question, $temperature = 0.7){
$answer = "";
if(!empty($question)){
$tok = self::getToken();
if($tok){
$url = "https://gigachat.devices.sberbank.ru/api/v1/chat/completions";
$headers = [
'Authorization: Bearer ' .$tok,
'Content-Type: application/json'
];
$messages = self::$messages;
$messages[] = [
"role" => "user",
"content"=> $question
];
$data = [
"model" => "GigaChat:latest",
"temperature" => $temperature,
"messages" => $messages
];
$result = self::get($url, $headers, json_encode($data));
$answer = $result["choices"][0]["message"]["content"];
if(!empty($answer)){
$messages[] = [
"role" => "assistant",
"content"=> $answer
];
self::$messages = $messages;
}
}
}
return $answer;
}
} |