Всем привет! Если Вы решили подключить в свою разработку на .NET Core поддержку GigaChat, то эта статья для Вас.

Небольшое признание про эту статью

Это мой первый пост на хабре, где я расскажу про свой первый опыт разработки для NuGet и впервые использовал GitHub в качестве Системы контроля версий. Не смотря на десятилетний опыт в разработке ранее не занимался подобными публикациями "для народа".
Но после полугодичного отдыха решил опробовать себя чуть в новой роли. Поэтому критику принимаю, но только обоснованную :)

В конце 2023 года я решил в один из своих пет-проектов добавить поддержку GigaChat. Выбор может показаться странным, на фоне YandexGPT и ChatGPT. Но я провел с каждым из них примерно десяток тестов, и, на мое удивление, под мои нужды самые релевантные ответы для рунета дал именно GigaChat.

Что проверял у ИИ

Мне нужно было получить по 5 ассоциаций связанных с запрашиваемым словом. ChatGPT давал ассоциации "западные" или "шаблонные". YandexGPT выдавал не 5 слов, а несколько абзацев в качестве ответа. Да и YandexGPT самый "боязливый" из всех как будто - многие вопросы он считает "нетолерантными", на которые остальные дают ответы, если правильно их разогреть. А вот GigaChat давал наиболее приемлемые для русского слуха ассоциации - поэтому выбор пал на него.

И я решил тогда создать dll для работы с ГигаЧатом. А заодно появились мысли поделиться ей - для этого провел доработку библиотеки и ниже представлю, как с ней работать.

Предварительные требования и шаги

1) Получить ключ разработчика.

Для этого нужно зарегистрироваться на сайте разработчиков сбера https://developers.sber.ru/. Далее в рабочем пространстве создать Проект, в котором нужно выбрать "GigaChat API".

Создание нового проекта
Создание нового проекта

Далее я активировал бесплатный некоммерческий тариф

Фримиум
Фримиум

И получил код, который далее используется для подключения к GigaChat API

2) Скачать сертификат минцифры https://developers.sber.ru/docs/ru/gigachat/certificates

Тут все как обычно, скачал, установил

3) Скачать с NuGet библиотеку GigaChatAdapter.

Со временем планирую назвать её GigaChatAdapter .NET Core так как написана под Core

Работа с библиотекой GigaChatAdapter .NET Core

Перехожу к основной части.

Работу в целом можно разделить на 4 части, как часто происходит с подобными API:

  1. Авторизация

  2. Основная бизнесовая часть (в данном случае общение с ИИ)

  3. Настройки

  4. Пример

Вопрос к знатокам хабра

Как сделать чтобы этот список-план, написанный чуть выше, превратился в меню на внутренние заголовки, которые указаны у меня ниже?

  1. Авторизация

    Чтобы авторизоваться необходимо создать экземпляр авторизации и отправить свои авторизационные данные, а также указать scope (персональное использование, или коммерческое). Если все удачно, то вернется 200 ОК с токеном доступа, который, кстати, дается на 30 минут и который потребуется для отправки запросов, то будет установлен статус Authorization.AuthorizationSuccess == true.

    Если же была ошибка на уровне Http или на уровне сервиса GigaChat, то Authorization.AuthorizationSuccess == false, а текст ошибки можно найти в Authorization.ErrorTextIfFailed

    Если по какой-то причине возникает ошибка, которой нет в поле ErrorTextIfFailed, то тогда можно углубиться в экземпляр Authorization, получить свойство LastResponse, в нем хранятся HttpResponse (а через него можно выйти и на httpRequest, если нужно) и GigaChatResponse.

using GigaChatAdapter;

//Укажите аутентификационные данные из личного кабинета
string authData = "{Авторизационные данные из скрины выше}";

//Запуск авторизации в гигачате
Authorization auth = new Authorization(authData, GigaChatAdapter.Auth.RateScope.GIGACHAT_API_PERS);
var authResult = await auth.SendRequest();

if (authResult.AuthorizationSuccess) {
  /// Общение с ИИ
}
else {
  Console.WriteLine(authResult.ErrorTextIfFailed);
}
  1. Общение с ИИ

Для отправки запроса нужно создать экземпляр Completion и через него отправить вопрос к ИИ. Ниже в коде это сделано в цикле, чтобы общение было продолжительным, пока не будет закрыто консольное приложение. При этом обращаю внимание, что перед вызовом желательно использовать обновление токена (строка 12) в случае, если у него закончился срок жизни. Т.е. если Вы не хотите контролировать время действия токена, то за Вас это сделает метод UpdateToken(). Он обновляется только в случае, если токен пустой, или не было еще запросов на авторизацию, или же истек срок действия токена. Если же Вам нужно в любом случае обновить его, то тогда в метод можно передать параметр Force = true, и токен обновится при любом раскладе.

Ответы от гигачата приходят в виде объекта "массив данных объекта Choices", поэтому берется последний ответ из всего массива.

if (authResult.AuthorizationSuccess)
{
    Completion completion = new Completion();
    Console.WriteLine("Напишите запрос к модели. В ином случае закройте окно, если дальнейшую работу с чатботом необходимо прекратить.");
    
    while (true)
    {
        //Чтение промпта с консоли
        var prompt = Console.ReadLine();

        //Обновление токена, если он просрочился
        await auth.UpdateToken();

        //отправка промпта
        var result = await completion.SendRequest(auth.LastResponse.GigaChatAuthorizationResponse?.AccessToken, prompt);

        if (result.RequestSuccessed)
        {
            Console.WriteLine(result.GigaChatCompletionResponse.Choices.LastOrDefault().Message.Content);
        }
        else
        {
            Console.WriteLine(result.ErrorTextIfFailed);
        }
    }

    
}

Отдельно выделю работу с историей чата. Она хранится не у ИИ, а у Вас, пока жив экземпляр сompletion. По умолчанию история сохраняется в поле Сompletion.History (как вопросы, так и ответы) и отправляется вместе с запросом каждый раз. Её можно сериализовать и сохранить куда угодно. При последующих сессиях эту историю можно достать, десериализовать, установить в объект Completion (оно доступно для изменения) и продолжать чатиться с ИИ с историей.

Сompletion.History = {Ваша история}

Если Вы не хотите использовать историю чата, тогда в методе SendRequest() нужно указать аргумент useHistory = false. Тогда вопрос отправляется без истории, он не сохраняется в истории равно как и ответ ИИ.

var result = await completion.SendRequest(auth.LastResponse.GigaChatAuthorizationResponse?.AccessToken, prompt, false);
  1. Настройки

GigaChat имеет несколько параметров для настройки ответов. Есть количество ответов, рандомизатор ответов, порог релевантности ответов, ограничения на использование токенов. Подробнее можно найти в описании документации GigaChat'а https://developers.sber.ru/docs/ru/gigachat/api/reference

Чтобы использовать свои настройки, а не дефолтные, необходимо создать экземпляр объекта CompletionSettings и передать его в метод completion.SendRequest().

CompletionSettings settings = new CompletionSettings("GigaChat:latest", 2, null, 4);
var result = await completion.SendRequest(auth.LastResponse.GigaChatAuthorizationResponse?.AccessToken, prompt, true, settings);

Единственный минус заключается в том, что указывать нужно все настройки при создании экземпляра CompletionSettings. Это связано с тем, что если разработчик вдруг не передает какие-либо параметры, то можно читать двояко:

  • Установить настройку в дефолтное состояние

  • Не менять предыдущую настройку

Поэтому решил что лучше обязать разработчика каждый раз указывать все настройки.

  1. Пример использования

Привожу полный код небольшого примера для консольного приложения на .NET Core. Так как он небольшой, не делю его на методы, читается (имхо) и так легко. Его можно копипастить (выполнив предварительные шаги, указанные в статье ранее)

using GigaChatAdapter;
using System.Text;

//Настройка для работы консоли с кириллицей
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Console.InputEncoding = Encoding.GetEncoding(1251);
Console.OutputEncoding = Encoding.GetEncoding(1251);

//Укажите аутентификационные данные из личного кабинета
string authData = "{Ваш код}";

//Запуск авторизации в гигачате
Authorization auth = new Authorization(authData, GigaChatAdapter.Auth.RateScope.GIGACHAT_API_PERS);
var authResult = await auth.SendRequest();

if (authResult.AuthorizationSuccess)
{
    Completion completion = new Completion();
    Console.WriteLine("Напишите запрос к модели. В ином случае закройте окно, если дальнейшую работу с чатботом необходимо прекратить."); //RU
    
    while (true)
    {
        //Чтение промпта с консоли
        var prompt = Console.ReadLine();

        //Обновление токена, если он просрочился
        await auth.UpdateToken();

        //Установка доп.настроек
        CompletionSettings settings = new CompletionSettings("GigaChat:latest", 2, null, 4);

        //Отправка промпта (с историей)
        var result = await completion.SendRequest(auth.LastResponse.GigaChatAuthorizationResponse?.AccessToken, prompt, true, settings);

        if (result.RequestSuccessed)
        {
            foreach (var it in result.GigaChatCompletionResponse.Choices)
            {
                Console.WriteLine(it.Message.Content);
            }
        }
        else
        {
            Console.WriteLine(result.ErrorTextIfFailed);
        }
    }   
}
else
{
    Console.WriteLine(authResult.ErrorTextIfFailed);
}

Проблемы и дальнейшее развитие

На текущий момент проблема заключается в том, что в исходном коде у меня присутствует описание всех методов и полей. Можно найти на ГитХабе. Но когда я загрузил сборку через NuGet, у меня в ней пропали все комментарии к методам и свойствам, что печально сказывается на юзабильности.

UPD: проблема с отсутствием комментариев в коде решена, спасибо откликнувшимся!

Кроме того пока не понимаю, могу ли поменять отображаемое в NuGet название, добавив к нему .NET Core, или оно теперь окончательное?

Сейчас библиотека не поддерживает потоковую передачу, которой обладает сам сервис GigaChat. Если будет такая необходимость - займусь. Но пока не вижу смысла тратить на это время в виду наличия других тем для разработки.

Если будет кто-то желающий помочь с развитием библиотеки - велкам :)

Комментарии (6)


  1. Vitimbo
    09.01.2024 13:11
    +2

    Не может ли отсутствие символов быть результатом отсутствия этой галочки?

    В вашем GigaChatAdapter.cspro не обнаружил тега DocumentationFile, который эти символы, вроде как, должен содержать.


  1. OwDafuq
    09.01.2024 13:11
    +1

    Чтобы оставались комментарии к методам/свойствам/etc., нужно генерировать документацию, которая должна будет попасть в nuget пакет, включать так (в настройках проекта):

    Либо в .csproj файле в блоке <PropertyGroup> добавить

    <GenerateDocumentationFile>True</GenerateDocumentationFile>


  1. reNNN Автор
    09.01.2024 13:11

    О, спасибо!

    Да, добавил эту галочку, выложил новую версию 1.0.4. Теперь появились комментарии в сборке :)


  1. Lifailon
    09.01.2024 13:11
    +1

    Полезная статья, развелось много моделей ИИ, про Сбер ранее и не слышал, спасибо! По поводу установки сертификата, этот процесс легко автоматизировать в несколько команд.

    Для Windows (PowerShell):

    Invoke-WebRequest "https://gu-st.ru/content/lending/russian_trusted_root_ca_pem.crt" -OutFile "$home\Downloads\russian_trusted_root_ca.cer" # скачать сертификат минцифры
    Invoke-WebRequest "https://gu-st.ru/content/lending/russian_trusted_sub_ca_pem.crt" -OutFile "$home\Downloads\russian_trusted_sub_ca.cer"
    Import-Certificate -FilePath "$home\Downloads\russian_trusted_root_ca.cer" -CertStoreLocation "Cert:\CurrentUser\Root" # установить сертификат минцифры
    Import-Certificate -FilePath "$home\Downloads\russian_trusted_sub_ca.cer" -CertStoreLocation "Cert:\CurrentUser\CA"

    Ubuntu (Bash):

    wget https://gu-st.ru/content/lending/russian_trusted_root_ca_pem.crt
    wget https://gu-st.ru/content/lending/russian_trusted_sub_ca_pem.crt
    mkdir /usr/local/share/ca-certificates/russian_trusted
    cp russian_trusted_root_ca_pem.crt russian_trusted_sub_ca_pem.crt /usr/local/share/ca-certificates/russian_trusted


    1. Lifailon
      09.01.2024 13:11
      +1

      В Ubuntu еще в конце для обновления списка сертификатов (забыл добавить):

      update-ca-certificates -v

      Опробовав модель, очень разочаровала, ответы сильно отличаются от тех, что отдает Web-версия. Можно получить что-то подходящее только запрос на 2-3, а то и 5, при этом продолжают тратиться токены...


      1. reNNN Автор
        09.01.2024 13:11

        Спасибо за скрипты для установки сертификатов!

        По поводу модели - да, модель сырая достаточно. Ее ввели в эксплуатацию относительно недавно (месяца 2-3 назад), и она дорабатывается еще. Веб-версия чата имеет какие-то свои настройки и модель. Например, я просил в промпте "умножь это число на 5". Веб-версия отрабатывала корректно, а веб-апи возвращал

        Пример ответа API
        Пример ответа API

        Плюс в декабре у сбера появилась модель GigaChat-Pro "с 29 миллиардами параметров" (тех.поддержка гигачата прислала). И где-то видел сообщение, что она бесплатна для фримиума до конца этого января, но может что-то поменялось с декабря. Название модели можно указать в настройках. Я пока ее не опробовал, отзыв о качестве не могу дать.