Обучаю битриксу программистов, интеграторов. Подробнee ⇒

Класс для работы с API GigaChat на PHP



Дока Сбера по GigaChat  https://developers.sber.ru/docs/ru/gigachat/api/overview
т.к. token генерируется на полчаса и его можно использовать несколько раз, я его запоминаю, проверяю дату истечения токена. вместо того. чтобы каждый раз новый токен запрашивать
реализовала через Singleton

COption::GetOptionString, COption::SetOptionString - битриксовские методы, можно в свою БД или файл писать токен корректный
файл
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;   
    }
}
пример работы
require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/php_interface/classes/gigachat.php");
use gigachat\Gigachat;
if($giga = Gigachat::getInstance()){
   echo $giga::ask('Какой самый теплый город в России?');

}
заполняем PREVIEW_TEXT автоматом у элементов
require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/php_interface/classes/gigachat.php");
use gigachat\Gigachat;
if($giga = Gigachat::getInstance()){
   CModule::IncludeModule('iblock');
   $el = new CIBlockElement;
   $arFilter = [
     "IBLOCK_ID"=>30, 
      "ACTIVE"=>"Y",
      "IBLOCK_SECTION_ID"=>2074,
      "PREVIEW_TEXT" =>false
   ];
   $arSelect = ["ID", "NAME", "PROPERTY_AUTHOR_T"];
   $res = CIBlockElement::GetList(["id"=>"asc"], $arFilter, false, ["nPageSize"=>100,"iNumPage"=>1], $arSelect);
   while($arItem = $res->Fetch()){
      $qst = "Расскажи кратко о чем книга '".$arItem["NAME"]."'";
      if(!empty($arItem["PROPERTY_AUTHOR_T_VALUE"])){
         $qst .=" автора ".$arItem["PROPERTY_AUTHOR_T_VALUE"];
      } 
      $qst .= "?";
      echo $qst."<br>";
      $answer =  $giga::ask($qst);
      if(!empty($answer)){
         $el->Update($arItem["ID"], ["PREVIEW_TEXT"=>$answer]);
      }
      $giga::clearHistory();
      sleep(1);
        echo $answer."<br>";
   }
}
Если блог был полезным, можете угостить меня "чашечкой кофе" :)

Сбер по номеру телефона +7 (953) 585-13-09 Вероника.
Спасибо!