Всем привет! В этой статье я расскажу о том, как подключиться к API GigaChat в IntelliJ IDEA на Java и настроить безопасное соединение с использованием SSL-сертификатов, чтобы получать ответы от GigaChat в своем приложении.

1. Что такое GigaChat и зачем он нужен?

GigaChat API — это интерфейс для интеграции AI-системы, разработанной для проведения диалогов и помощи с генерацией текста. Он может применяться для создания интерактивных приложений, таких как чат-боты, системы поддержки и более сложных аналитических инструментов, требующих обработки языка.

Сам GigaChat имеет подробную документацию по интеграции по API -> Установка | Документация для разработчиков , однако, я решил, что пошаговый личный пример, может быть интересен сообществу и возможно кому-то сэкономит немного времени при настройке.

2. Настройка окружения

Для работы с GigaChat API вам потребуется Java, а также клиент для HTTP-запросов, например, OkHttp. Ниже приведён список зависимостей и некоторые базовые настройки.

Зависимости

Добавим в проект OkHttp для отправки HTTP-запросов. Если используете Gradle, добавьте в build.gradle:

dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
}

3. Получение SSL-сертификатов

Поскольку GigaChat API требует защищённого соединения, необходимо настроить сертификаты SSL. Получите корневой и подчинённый сертификаты (CA Certificates) согласно документации и сохраните их в папке проекта. У себя я их разместил в src/main/resources/certs.

4. Класс для подключения к API

Ниже привожу код, который создаёт запрос к GigaChat API, используя OkHttpClient с настройками SSL-сертификата.

Код для GigaChatDialog

import okhttp3.*;
import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

public class GigaChatDialog {

    private static final String API_URL = "https://gigachat.devices.sberbank.ru/api/v1/chat/completions";
    private static final String CERT_PATH = "src/main/resources/certs/russian_trusted_sub_ca.cer";
    private static final String ACCESS_TOKEN = "токен_доступа";

    private OkHttpClient client;

    public GigaChatDialog() {
        try {
            this.client = createClient();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private OkHttpClient createClient() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        FileInputStream certInput = new FileInputStream(CERT_PATH);
        X509Certificate caCert = (X509Certificate) cf.generateCertificate(certInput);

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        keyStore.setCertificateEntry("caCert", caCert);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        return new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0])
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .build();
    }

    public String getResponse(String message) {
        String jsonPayload = "{ \"model\": \"GigaChat\", \"messages\": [{ \"role\": \"user\", \"content\": \"" + message + "\" }], \"stream\": false }";
        RequestBody body = RequestBody.create(jsonPayload, MediaType.get("application/json; charset=utf-8"));

        Request request = new Request.Builder()
                .url(API_URL)
                .post(body)
                .addHeader("Authorization", "Bearer " + ACCESS_TOKEN)
                .addHeader("Content-Type", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            return new String(response.body().bytes(), StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Что делает этот код?

  1. Загружает сертификат: Использует TrustManagerFactory, чтобы загружать корневой сертификат.

  2. Настраивает SSLContext: Настраивает клиент OkHttp для работы с сертификатом и SSLContext.

  3. Формирует запрос: Создаёт JSON-пayload с текстом запроса и отправляет его на сервер.

  4. Обрабатывает ответ: Получает ответ и возвращает его как строку в UTF-8, чтобы избежать проблем с кодировкой.

5. Что за зверь AccessToken и где его взять

В доке GigaChat API указано, что для взаимодействия необходим AccessToken, срок жизни его 30 минут. Достать его можно несколькими способами:

пробросить curl, как написано в официальной документации или есть небольшой метод на Phyton, однако curl у меня не сработал, поэтому я пошел своим путем и написал небольшой метод на java, который получает токен, привожу ключевые моменты

            // Кодирование client_id и client_secret в формате Base64
            String authKey = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8));
          
            // Создание тела запроса для POST
            RequestBody formBody = new FormBody.Builder()
                    .add("scope", "GIGACHAT_API_PERS")
                    .build();

            // Создание запроса
            Request request = new Request.Builder()
                    .url(url)
                    .post(formBody)
                    .addHeader("Content-Type", "application/x-www-form-urlencoded")
                    .addHeader("Accept", "application/json")
                    .addHeader("RqUID", "хххххххх-хххх-хххх-хххх-хххххххххххх")  // Замените на уникальный идентификатор запроса
                    .addHeader("Authorization", "Basic " + authKey)
                    .build();

            // Создание OkHttpClient с SSL-сертификатом
            OkHttpClient client = new OkHttpClient.Builder()
                    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0])
                    .build();

            // Выполнение запроса
            try (Response response = client.newCall(request).execute()) {

                // Обработка ответа
                if (response.isSuccessful() && response.body() != null) {
                    System.out.println("Access Token: " + response.body().string());
                } else {
                    System.out.println("Response body: " + (response.body() != null ? response.body().string() : "No response body"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

Тут отмечу, что RqUID - обязательное поле, без него у меня сыпалась ошибка неверного формата запроса.

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

Теперь давайте используем наш класс GigaChatDialog, чтобы получить ответ от GigaChat API.

    public static void main(String[] args) {
        GigaChatDialog chatDialog = new GigaChatDialog();
        String response = chatDialog.getResponse("Привет, GigaChat! Как дела?");
        System.out.println("GigaChat: " + response);
    }

Ответ получим в следующем формате:

7. Проблемы с которыми я столкнулся при подключении

  • RqUID - обязательный в хедерах запроса

  • 401 Unauthorized: Проверьте, правильно ли указан токен доступа.

  • SSLHandshakeException: Убедитесь, что сертификаты загружены правильно и пути к ним указаны верно.

Вместо заключения

Теперь вы знаете, как подключить Java-приложение к GigaChat API и как настроить клиент для работы с SSL-сертификатами. Надеюсь, статья была полезной и поможет вам использовать AI в своих проектах! Делитесь своими мыслями и вопросами в комментариях — будет интересно обсудить!

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


  1. alekseypro
    31.10.2024 11:19

    1. CURL сработал нормально, проблем не было.

    2. Authorization Key не шифровал в Base64, передал в заголовке, как есть, все сработало.

    3. Сертификат не подключал.