Я интегрирую LLM-модели в продакшен-системы с 2023 года — начинал с GPT-3.5, прошёл через Claude, Gemini, YandexGPT, а сейчас три из шести моих production-сервисов работают на GigaChat. За это время я собрал коллекцию граблей, на которые наступает каждый, кто впервые открывает документацию Сбера. В этой статье — всё, что я хотел бы знать до первого коммита.
TL;DR: GigaChat API — зрелый продукт с адекватным качеством русского языка, но с тремя подводными камнями: OAuth-токен живёт ровно 30 минут (не «примерно», а ровно — expires_at в миллисекундах), сертификат Минцифры обязателен (и нет, verify=False — не решение), а scope определяет не только лимиты, но и доступные модели. Ниже — рабочий код на Python, который можно копировать в проект прямо сейчас.
Если вы уже знаете, что такое GigaChat, и хотите быстро получить рабочий код — листайте к разделу «Production-ready клиент». Если хотите разобраться в каждой детали — читайте по порядку.
Зачем эта статья, если уже читали официальную документацию
Официальная документация GigaChat — это справочник по API-endpoints. Там есть curl-примеры, описание параметров и список моделей. Но там нет ответа на вопрос «почему мой запрос возвращает 401 через 29 минут после получения токена». Нет объяснения, почему verify=False — это не «временное решение для тестирования», а дыра в безопасности, через которую ваш API-ключ может утечь при MITM-атаке. Нет сравнения стоимости PERS vs B2B на реальных нагрузках.
Я написал этот гайд после того, как в третий раз помогал коллеге разобраться с ошибкой SSL: CERTIFICATE_VERIFY_FAILED. Каждый раз одна и та же история: человек читает документацию, находит пример с verify=False, копирует, запускает, радуется — а через месяц получает инцидент безопасности или, что чаще, непонятные 401 в три часа ночи, когда токен протух, а retry-логики нет.
Эта статья — мой ответ на все вопросы, которые мне задавали. Здесь рабочий код, реальные цифры и честные выводы. Без маркетинга.
Получение доступа за 5 шагов
Шаг 1. Регистрация на developers.sber.ru
Откройте developers.sber.ru и зарегистрируйтесь. Для физлиц достаточно SberID (привязка к номеру телефона). Для юрлиц потребуется ИНН и данные компании — регистрация занимает 1–2 рабочих дня на модерации.
Важный нюанс: учётная запись физлица и юрлица — это разные сущности. Если вы сначала зарегистрировались как физлицо (PERS), а потом хотите перейти на B2B — придётся создавать новый проект с новыми ключами. Старые перестанут работать.
Шаг 2. Создание проекта GigaChat API
В личном кабинете откройте раздел «Мои проекты» → «Создать проект». Выберите продукт «GigaChat API». Проект — это контейнер для ваших ключей и статистики использования. Один аккаунт может содержать несколько проектов с разными scope.
Шаг 3. Выбор scope: PERS, B2B или CORP — это критично
Scope — это не просто «тариф». Это определяет, какие модели вам доступны, какие лимиты действуют, и нужен ли договор. Вот таблица по состоянию на 8 апреля 2026 года:
| Параметр | GIGACHAT_API_PERS | GIGACHAT_API_B2B | GIGACHAT_API_CORP |
|---|---|---|---|
| Кто может получить | Физлицо (SberID) | ИП / юрлицо | Крупный бизнес |
| Модель оплаты | Бесплатно (лимиты) + пакеты | Пакеты токенов / помесячно | Индивидуальный договор |
| Договор | Оферта | Электронный договор | Бумажный договор |
| Доступные модели | GigaChat, GigaChat-Plus | GigaChat, GigaChat-Plus, GigaChat-Pro | Все модели + on-premise |
| RPS (запросов/сек) | 1 | 5–50 (зависит от пакета) | По договору |
| Бесплатный лимит | 1 000 000 токенов/мес | Нет | Нет |
| Function Calling | Да (ограничено) | Да | Да |
| Embeddings | Да | Да | Да |
Моя рекомендация: начинайте с PERS для прототипа — миллиона бесплатных токенов хватает на 2–3 недели активной разработки. Как только прототип готов и вы понимаете нагрузку — переходите на B2B. CORP нужен только если у вас требования к on-premise или SLA в договоре.
Шаг 4. Генерация Authorization Key
В настройках проекта нажмите «Сгенерировать новый ключ». Система выдаст строку вида MjJhYjEzZDgtOTk4Yi00... — это base64 от client_id:client_secret. Именно эту строку вы будете передавать в заголовке Authorization: Basic {key} при получении OAuth-токена.
Внимание: при генерации нового ключа старый немедленно перестаёт работать. Это не то поведение, к которому привыкли пользователи OpenAI (где можно иметь несколько активных ключей). Планируйте ротацию ключей заранее, чтобы не получить даунтайм в продакшене.
# Как устроен ключ (для понимания, генерировать вручную не нужно)
import base64
client_id = "22ab13d8-998b-4a3e-..."
client_secret = "a1b2c3d4-e5f6-..."
auth_key = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
print(auth_key) # MjJhYjEzZDgtOTk4Yi00...
Шаг 5. Скачивание сертификата Минцифры
GigaChat API использует TLS-сертификат, выданный российским удостоверяющим центром (Минцифры). Стандартные хранилища сертификатов (Mozilla, Apple, Google) этот CA не содержат. Поэтому без явного указания сертификата вы получите ошибку SSL: CERTIFICATE_VERIFY_FAILED.
Скачайте корневой сертификат с gosuslugi.ru/crt или developers.sber.ru (раздел документации GigaChat). Файл называется russian_trusted_root_ca_pem.crt или аналогично.
Три способа установки:
Способ 1. Явный путь к файлу (рекомендую для серверов)
import requests
response = requests.post(
"https://ngw.devices.sberbank.ru:9443/api/v2/oauth",
verify="/path/to/russian_trusted_root_ca.pem",
...
)
Плюсы: явно, контролируемо, работает в Docker. Минусы: нужно следить за обновлением сертификата.
Способ 2. Добавление в certifi (рекомендую для локальной разработки)
import certifi
# Найти файл certifi
print(certifi.where()) # /path/to/certifi/cacert.pem
# Дописать сертификат Минцифры в конец файла
# cat russian_trusted_root_ca.pem >> $(python -m certifi)
Плюсы: requests/httpx подхватят автоматически, не нужно указывать verify. Минусы: при обновлении certifi через pip сертификат пропадёт.
Способ 3. Установка на уровне ОС (рекомендую для Docker-образов)
# Ubuntu / Debian
sudo cp russian_trusted_root_ca.pem /usr/local/share/ca-certificates/russian_trusted_root_ca.crt
sudo update-ca-certificates
# Alpine (Docker)
cp russian_trusted_root_ca.pem /usr/local/share/ca-certificates/
update-ca-certificates
# macOS
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain russian_trusted_root_ca.pem
Плюсы: работает для всех приложений в ОС. Минусы: требует root-доступа, влияет на всю систему.
Первый рабочий запрос на Python
Минимальный пример (10 строк)
import requests
import uuid
# 1. Получаем OAuth-токен
token_response = requests.post(
"https://ngw.devices.sberbank.ru:9443/api/v2/oauth",
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
"RqUID": str(uuid.uuid4()),
"Authorization": "Basic ВАШ_AUTHORIZATION_KEY",
},
data={"scope": "GIGACHAT_API_PERS"},
verify="/path/to/russian_trusted_root_ca.pem",
)
access_token = token_response.json()["access_token"]
# 2. Отправляем запрос к модели
chat_response = requests.post(
"https://gigachat.devices.sberbank.ru/api/v1/chat/completions",
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer {access_token}",
},
json={
"model": "GigaChat",
"messages": [{"role": "user", "content": "Привет! Расскажи о себе в двух предложениях."}],
"temperature": 0.7,
},
verify="/path/to/russian_trusted_root_ca.pem",
)
print(chat_response.json()["choices"][0]["message"]["content"])
Разбор по строкам:
- Строка 6: OAuth-эндпоинт на порту 9443 — это отдельный сервер авторизации, не путайте с API-эндпоинтом
- Строка 10:
RqUID— уникальный идентификатор запроса (UUID v4). Обязательный заголовок, без него получите 400 - Строка 13:
scopeпередаётся в теле запроса, не в URL - Строка 14:
verify— путь к сертификату Минцифры, неFalse! - Строка 20: API чатов на другом домене —
gigachat.devices.sberbank.ru - Строка 27: формат messages идентичен OpenAI —
role+content
Что не так с verify=False
Вот что делает verify=False: отключает проверку TLS-сертификата полностью. Это значит, что ваш клиент будет доверять любому сертификату — включая поддельный. В кофейне с публичным Wi-Fi злоумышленник может подменить DNS, перехватить ваш запрос и получить ваш Authorization Key. С этим ключом он будет генерировать токены и тратить ваш баланс.
«Но это же только для тестирования!» — скажете вы. Я видел verify=False в production-коде чаще, чем хочу признать. Код, написанный «временно», живёт годами. Потратьте 5 минут на установку сертификата — и забудьте об этой проблеме навсегда.
Production-ready клиент
Кэширование токена с учётом expires_at
OAuth-токен GigaChat живёт 30 минут. Поле expires_at в ответе — это Unix-timestamp в миллисекундах (не в секундах, как у многих OAuth-серверов). Если вы делите на 1000 и сравниваете с time.time(), не забудьте про буфер: запрашивайте новый токен за 60 секунд до истечения, чтобы запрос не попал в окно между «токен ещё валиден» и «токен уже протух».
Retry с экспоненциальным backoff
GigaChat API возвращает 429 при превышении RPS-лимита. Для PERS это 1 запрос в секунду — значит, при параллельных запросах вы будете получать 429 постоянно. Retry с экспоненциальным backoff и jitter решает проблему:
import random
import time
def retry_with_backoff(func, max_retries=5, base_delay=1.0):
"""Выполняет функцию с повторными попытками и экспоненциальным backoff."""
for attempt in range(max_retries):
try:
return func()
except Exception as e:
if attempt == max_retries - 1:
raise
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
Обработка ошибок GigaChat
API возвращает ошибки в двух форматах: стандартные HTTP-коды и JSON с деталями. Вот что нужно обрабатывать:
| Код | Причина | Действие |
|---|---|---|
| 400 | Невалидный запрос (нет RqUID, пустые messages) | Проверьте тело запроса, добавьте RqUID |
| 401 | Токен протух или невалидный scope | Обновите токен, проверьте scope |
| 429 | Превышен RPS-лимит | Retry с backoff, увеличьте scope |
| 500 | Внутренняя ошибка GigaChat | Retry через 5–10 секунд |
| 503 | Сервис перегружен | Retry через 30–60 секунд |
Полный класс GigaChatClient — копируйте и используйте
"""Production-ready клиент для GigaChat API.
Автор: НейроСкоп (neiroscop.ru)
Проверено: 8 апреля 2026
Python: 3.10+
Зависимости: requests, typing
"""
import random
import time
import uuid
from dataclasses import dataclass, field
from typing import Any, Generator
import requests
@dataclass
class GigaChatConfig:
"""Конфигурация клиента GigaChat."""
auth_key: str
scope: str = "GIGACHAT_API_PERS"
cert_path: str = "/etc/ssl/certs/russian_trusted_root_ca.pem"
model: str = "GigaChat"
temperature: float = 0.7
max_tokens: int = 1024
max_retries: int = 5
base_delay: float = 1.0
token_refresh_buffer: int = 60 # секунд до истечения
class GigaChatError(Exception):
"""Базовое исключение для ошибок GigaChat API."""
def __init__(self, status_code: int, message: str, response: dict | None = None):
self.status_code = status_code
self.message = message
self.response = response
super().__init__(f"GigaChat API Error {status_code}: {message}")
class GigaChatClient:
"""Production-ready клиент для GigaChat API с кэшированием токена и retry."""
AUTH_URL = "https://ngw.devices.sberbank.ru:9443/api/v2/oauth"
API_URL = "https://gigachat.devices.sberbank.ru/api/v1"
def __init__(self, config: GigaChatConfig):
self.config = config
self._access_token: str | None = None
self._token_expires_at: float = 0.0
self._session = requests.Session()
self._session.verify = config.cert_path
def _is_token_valid(self) -> bool:
"""Проверяет, что токен ещё валиден с учётом буфера."""
if not self._access_token:
return False
return time.time() < (self._token_expires_at - self.config.token_refresh_buffer)
def _obtain_token(self) -> None:
"""Получает новый OAuth-токен."""
response = self._session.post(
self.AUTH_URL,
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
"RqUID": str(uuid.uuid4()),
"Authorization": f"Basic {self.config.auth_key}",
},
data={"scope": self.config.scope},
)
if response.status_code != 200:
raise GigaChatError(
response.status_code,
f"Ошибка авторизации: {response.text}",
response.json() if response.headers.get("content-type", "").startswith("application/json") else None,
)
data = response.json()
self._access_token = data["access_token"]
# expires_at приходит в миллисекундах!
self._token_expires_at = data["expires_at"] / 1000.0
def _ensure_token(self) -> str:
"""Гарантирует наличие валидного токена."""
if not self._is_token_valid():
self._obtain_token()
return self._access_token # type: ignore[return-value]
def _request_with_retry(self, method: str, url: str, **kwargs: Any) -> requests.Response:
"""Выполняет HTTP-запрос с retry и экспоненциальным backoff."""
last_exception: Exception | None = None
for attempt in range(self.config.max_retries):
try:
token = self._ensure_token()
kwargs.setdefault("headers", {})
kwargs["headers"]["Authorization"] = f"Bearer {token}"
kwargs["headers"]["Content-Type"] = "application/json"
kwargs["headers"]["Accept"] = "application/json"
response = self._session.request(method, url, **kwargs)
if response.status_code == 401:
# Токен протух — обновляем и повторяем
self._access_token = None
continue
if response.status_code == 429:
delay = self.config.base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
continue
if response.status_code >= 500:
delay = self.config.base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
continue
if response.status_code != 200:
raise GigaChatError(response.status_code, response.text)
return response
except requests.exceptions.ConnectionError as e:
last_exception = e
delay = self.config.base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
raise GigaChatError(0, f"Все {self.config.max_retries} попыток исчерпаны: {last_exception}")
def chat(
self,
messages: list[dict[str, str]],
model: str | None = None,
temperature: float | None = None,
max_tokens: int | None = None,
) -> dict[str, Any]:
"""Отправляет сообщение в чат и возвращает ответ.
Args:
messages: Список сообщений в формате [{"role": "user", "content": "..."}]
model: Модель (по умолчанию из конфига)
temperature: Температура генерации (0.0–2.0)
max_tokens: Максимальное количество токенов в ответе
Returns:
Полный JSON-ответ API
"""
payload = {
"model": model or self.config.model,
"messages": messages,
"temperature": temperature if temperature is not None else self.config.temperature,
"max_tokens": max_tokens or self.config.max_tokens,
}
response = self._request_with_retry("POST", f"{self.API_URL}/chat/completions", json=payload)
return response.json()
def chat_simple(self, prompt: str, system: str | None = None) -> str:
"""Упрощённый метод: строка на входе, строка на выходе.
Args:
prompt: Текст запроса пользователя
system: Системный промпт (опционально)
Returns:
Текст ответа модели
"""
messages: list[dict[str, str]] = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
result = self.chat(messages)
return result["choices"][0]["message"]["content"]
def embeddings(self, texts: list[str], model: str = "Embeddings") -> list[list[float]]:
"""Получает эмбеддинги для списка текстов.
Args:
texts: Список текстов для векторизации
model: Модель эмбеддингов
Returns:
Список векторов (list[list[float]])
"""
payload = {"model": model, "input": texts}
response = self._request_with_retry("POST", f"{self.API_URL}/embeddings", json=payload)
data = response.json()
return [item["embedding"] for item in data["data"]]
def models(self) -> list[dict[str, Any]]:
"""Возвращает список доступных моделей."""
response = self._request_with_retry("GET", f"{self.API_URL}/models")
return response.json()["data"]
# Пример использования
if __name__ == "__main__":
config = GigaChatConfig(
auth_key="ВАШ_AUTHORIZATION_KEY",
scope="GIGACHAT_API_PERS",
cert_path="/path/to/russian_trusted_root_ca.pem",
)
client = GigaChatClient(config)
answer = client.chat_simple("Что такое квантовые вычисления? Объясни в трёх предложениях.")
print(answer)
Этот класс решает три главные проблемы: автоматическое обновление токена, retry с backoff при 429/5xx и правильную работу с сертификатом. Копируйте в свой проект, подставьте ключ и cert_path — и у вас есть production-ready клиент.
Streaming-ответы (Server-Sent Events)
Зачем нужны
GigaChat-Pro на сложных промптах может генерировать ответ 10–15 секунд. Без стриминга пользователь видит пустой экран всё это время. Со стримингом — текст появляется посимвольно, как в ChatGPT. Для UX это критично.
Рабочий код на httpx
Для стриминга рекомендую httpx вместо requests — у него нативная поддержка SSE и async:
import httpx
import json
def stream_chat(
access_token: str,
messages: list[dict[str, str]],
cert_path: str,
model: str = "GigaChat",
) -> Generator[str, None, None]:
"""Стриминг ответа от GigaChat (Server-Sent Events).
Args:
access_token: OAuth-токен
messages: Список сообщений
cert_path: Путь к сертификату Минцифры
model: Модель GigaChat
Yields:
Фрагменты текста по мере генерации
"""
with httpx.Client(verify=cert_path) as client:
with client.stream(
"POST",
"https://gigachat.devices.sberbank.ru/api/v1/chat/completions",
headers={
"Content-Type": "application/json",
"Accept": "text/event-stream",
"Authorization": f"Bearer {access_token}",
},
json={
"model": model,
"messages": messages,
"stream": True,
},
) as response:
for line in response.iter_lines():
if not line or not line.startswith("data: "):
continue
data_str = line[6:] # Убираем "data: "
if data_str == "[DONE]":
break
chunk = json.loads(data_str)
delta = chunk["choices"][0].get("delta", {})
content = delta.get("content", "")
if content:
yield content
# Пример использования
# for chunk in stream_chat(token, [{"role": "user", "content": "Расскажи сказку"}], cert_path):
# print(chunk, end="", flush=True)
Отличие от формата OpenAI
Формат SSE у GigaChat на 95% совместим с OpenAI. Основные отличия:
- Завершение: GigaChat отправляет
data: [DONE]— идентично OpenAI - Структура chunk:
choices[0].delta.content— идентично - Разделитель: двойной
\n\nмежду event — идентично - Отличие: GigaChat иногда отправляет пустые chunks без
delta— нужна проверка.get("delta", {})
Если у вас уже есть код для стриминга OpenAI — замените URL и добавьте сертификат, остальное будет работать.
Function Calling: как это сделано в GigaChat
Сравнение с OpenAI-форматом
GigaChat поддерживает Function Calling (инструменты), но формат описания функций слегка отличается от OpenAI. Основная идея та же: вы описываете функции, модель решает, когда их вызвать, и возвращает структурированный JSON с аргументами.
Пример: парсим почту в JSON
def parse_email_with_functions(client: GigaChatClient, email_text: str) -> dict:
"""Извлекает структурированные данные из текста письма через Function Calling.
Args:
client: Инстанс GigaChatClient
email_text: Текст письма для парсинга
Returns:
Словарь с извлечёнными данными (sender, subject, action_items, deadline)
"""
functions = [
{
"name": "extract_email_data",
"description": "Извлекает структурированные данные из текста электронного письма",
"parameters": {
"type": "object",
"properties": {
"sender": {"type": "string", "description": "Имя или email отправителя"},
"subject": {"type": "string", "description": "Тема письма в 5-10 словах"},
"action_items": {
"type": "array",
"items": {"type": "string"},
"description": "Список действий, которые нужно выполнить",
},
"deadline": {
"type": "string",
"description": "Дедлайн в формате YYYY-MM-DD, если упоминается",
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "critical"],
"description": "Приоритет на основе содержания",
},
},
"required": ["sender", "subject", "action_items", "priority"],
},
}
]
payload = {
"model": "GigaChat-Pro",
"messages": [
{"role": "system", "content": "Ты — ассистент для обработки электронной почты."},
{"role": "user", "content": f"Извлеки данные из письма:\n\n{email_text}"},
],
"functions": functions, # Не "tools", а "functions" — это отличие от OpenAI
"function_call": {"name": "extract_email_data"},
}
response = client._request_with_retry("POST", f"{client.API_URL}/chat/completions", json=payload)
data = response.json()
function_call = data["choices"][0]["message"].get("function_call", {})
import json
return json.loads(function_call.get("arguments", "{}"))
Что не работает (апрель 2026)
По состоянию на 8 апреля 2026 года:
- Параллельные вызовы функций: GigaChat не поддерживает parallel function calling (несколько функций за один вызов). OpenAI поддерживает с GPT-4 Turbo
- Вложенные объекты: сложные вложенные JSON-схемы иногда генерируют невалидный JSON. Рекомендация: делайте схемы максимально плоскими
- Модель GigaChat (базовая): function calling работает, но качество заметно ниже, чем на GigaChat-Pro. Для продакшена — только Pro
- Формат tools: OpenAI перешёл на формат
toolsвместоfunctions. GigaChat использует старый форматfunctions. Если переносите код с OpenAI — нужна адаптация
Embeddings и работа с векторами
Доступные модели
GigaChat предоставляет модель Embeddings для получения векторных представлений текста. Размерность вектора — 1024. Это меньше, чем у OpenAI text-embedding-3-large (3072), но достаточно для большинства задач RAG и семантического поиска.
# Получение эмбеддингов
config = GigaChatConfig(auth_key="ВАШ_КЛЮЧ", cert_path="/path/to/cert.pem")
client = GigaChatClient(config)
texts = [
"Как подключить GigaChat API к Python-проекту",
"Инструкция по настройке OAuth для Сбер API",
"Рецепт борща с пампушками",
]
vectors = client.embeddings(texts)
print(f"Размерность: {len(vectors[0])}") # 1024
print(f"Количество: {len(vectors)}") # 3
Совместимость с pgvector / Qdrant
Эмбеддинги GigaChat — это обычные float-массивы размерности 1024. Они совместимы с любым векторным хранилищем:
- pgvector (PostgreSQL):
CREATE TABLE items (embedding vector(1024))— работает из коробки - Qdrant: создайте коллекцию с
size=1024, distance=Cosine - ChromaDB: передайте эмбеддинги как list[float] при вставке
- FAISS:
faiss.IndexFlatIP(1024)для inner product илиIndexFlatL2для L2
Важный нюанс: эмбеддинги GigaChat и OpenAI не совместимы друг с другом. Если вы переходите с одного провайдера на другой — придётся перевекторизовать всю базу.
Тарифы и оплата для ИП — реальные цифры на апрель 2026
Сколько стоит реально
Цены GigaChat менялись трижды за последний год. Вот актуальная таблица на 8 апреля 2026:
| Модель | Вход (₽/1K токенов) | Выход (₽/1K токенов) | Контекст | Scope |
|---|---|---|---|---|
| GigaChat | 0.35 | 1.40 | 8 192 | PERS, B2B, CORP |
| GigaChat-Plus | 0.70 | 2.80 | 32 768 | PERS, B2B, CORP |
| GigaChat-Pro | 3.50 | 14.00 | 32 768 | B2B, CORP |
| Embeddings | 0.20 | — | — | PERS, B2B, CORP |
Пример расчёта: 1000 запросов по 500 входных + 300 выходных токенов на GigaChat = (500 × 0.35 + 300 × 1.40) / 1000 × 1000 = 175 + 420 = 595 ₽. Для сравнения, GPT-4o на аналогичной нагрузке обойдётся примерно в $2.50 (≈225 ₽ по курсу), но потребует зарубежную карту и VPN.
PERS vs B2B vs CORP — какой scope выбирать
Для пет-проектов и прототипов — PERS. Миллион бесплатных токенов в месяц покрывает 2000–3000 запросов средней длины. Ограничение в 1 RPS — не проблема для одного разработчика.
Для коммерческих проектов с нагрузкой больше 1 RPS — B2B. Здесь появляется доступ к GigaChat-Pro (лучшее качество для сложных задач) и увеличенный RPS до 50. Минимальный пакет — 500 000 токенов.
CORP — только если вам нужен on-premise (свои серверы, данные не уходят за периметр) или гарантированный SLA в договоре. Для 95% проектов B2B достаточно.
Оплата с зарубежной карты
GigaChat — российский сервис, принимает карты российских банков и СБП.
Самые частые ошибки и как их чинить
401 unauthorized после первого запроса
Причина №1: вы используете Authorization Key вместо access_token. Помните: ключ авторизации нужен только для получения токена. Для всех остальных запросов используйте Bearer {access_token}.
Причина №2: токен протух. Проверьте expires_at из ответа OAuth — он в миллисекундах. Если expires_at / 1000 < time.time(), токен нужно обновить.
Причина №3: scope не соответствует модели. Если у вас scope PERS, а вы запрашиваете GigaChat-Pro — получите 401. Проверьте таблицу совместимости scope/модели выше.
# Диагностика 401
import time
response = get_token(...)
data = response.json()
expires_at = data["expires_at"] / 1000 # миллисекунды → секунды
now = time.time()
remaining = expires_at - now
print(f"Токен истекает через {remaining:.0f} секунд ({remaining/60:.1f} минут)")
SSL: CERTIFICATE_VERIFY_FAILED
Причина: сертификат Минцифры не установлен. Решение — смотрите раздел «Шаг 5. Скачивание сертификата Минцифры» выше.
Частный случай в Docker: вы установили сертификат на хост-машине, но не в Docker-контейнере. Добавьте в Dockerfile:
COPY russian_trusted_root_ca.pem /usr/local/share/ca-certificates/russian_trusted_root_ca.crt
RUN update-ca-certificates
Частный случай с certifi: вы добавили сертификат в certifi, но потом обновили пакет через pip — сертификат пропал. Решение: используйте явный путь через verify= параметр.
429 rate limit
Причина: превышен RPS-лимит вашего scope. Для PERS это 1 запрос в секунду.
Решение:
- Добавьте retry с экспоненциальным backoff (код выше в разделе GigaChatClient)
- Если вам нужно больше 1 RPS — переходите на B2B
- Для пакетной обработки используйте очередь с rate limiter:
asyncio.Semaphore(1)для PERS,Semaphore(5)для базового B2B
Function calling возвращает текст вместо JSON
Причина №1: вы используете базовую модель GigaChat вместо GigaChat-Pro. Базовая модель иногда «забывает» вызвать функцию и просто отвечает текстом.
Причина №2: слишком сложная JSON-схема. GigaChat плохо работает с глубоко вложенными объектами (3+ уровня вложенности).
Решение:
- Используйте GigaChat-Pro для function calling
- Упрощайте JSON-схемы: максимум 2 уровня вложенности
- Добавьте
function_call: {"name": "имя_функции"}для принудительного вызова функции - Всегда проверяйте, что в ответе есть
function_call, и добавляйте fallback на текстовый парсинг
Когда GigaChat — правильный выбор, а когда нет
GigaChat — правильный выбор, когда:
- Ваши пользователи в России и данные должны оставаться в российской юрисдикции
- Вам нужен API без VPN, зарубежных карт и валютных переводов
- Основной язык — русский, и качество русского текста критично
- У вас требования к 152-ФЗ и хранению персональных данных в РФ
- Вы уже в экосистеме Сбера (SberCloud, SberDevices)
GigaChat — не лучший выбор, когда:
- Вам нужна максимальная точность на английском — ChatGPT и Claude объективно лучше
- Вам нужен мультимодальный ввод (анализ изображений) — GigaChat генерирует картинки, но не анализирует их
- Вам нужен длинный контекст (100K+ токенов) — максимум GigaChat-Pro/Plus — 32K
- Вам нужна кодогенерация уровня Copilot — DeepSeek и Claude значительно сильнее
- Вы хотите запускать модель локально — для этого есть Ollama с открытыми моделями
GigaChat занимает свою нишу: российский API с хорошим русским языком, легальной оплатой в рублях и соответствием российскому законодательству. Для многих проектов это единственно правильный выбор.
FAQ
Как получить ключ GigaChat API
Зарегистрируйтесь на developers.sber.ru, создайте проект GigaChat API, выберите scope (PERS для начала) и нажмите «Сгенерировать ключ». Ключ — это base64 от client_id:client_secret. Процесс занимает 5 минут для физлиц.
Почему GigaChat возвращает 401
Три причины: 1) вы отправляете Authorization Key вместо access_token в запросах к API, 2) access_token истёк (живёт 30 минут), 3) scope не соответствует запрашиваемой модели (PERS не даёт доступ к GigaChat-Pro). Решение: обновите токен, проверьте scope, убедитесь, что в заголовке Bearer {access_token}, а не Basic {auth_key}.
Как часто обновлять токен
Токен живёт ровно 30 минут. Поле expires_at в ответе OAuth — в миллисекундах. Рекомендация: обновляйте за 60 секунд до истечения. В production-коде — используйте класс GigaChatClient из этой статьи, он делает это автоматически.
Чем отличается PERS от B2B
PERS — для физлиц: 1 RPS, бесплатный лимит 1M токенов/мес, нет доступа к GigaChat-Pro. B2B — для юрлиц/ИП: до 50 RPS, все модели включая Pro, пакетная оплата. Для прототипа начинайте с PERS, для коммерческого продукта — B2B.
Можно ли без сертификата Минцифры
Технически можно с verify=False, но это отключает TLS-проверку полностью — ваш ключ может утечь при MITM-атаке. Установка сертификата занимает 5 минут и решает проблему навсегда. Инструкция — в разделе «Шаг 5» выше.
Какой scope для бота
Для Telegram/Discord бота: PERS, если бот для личного использования (до 1 RPS); B2B, если бот публичный или обслуживает более 1 пользователя одновременно. Для бота с function calling — только B2B (GigaChat-Pro значительно надёжнее базовой модели).
GigaChat vs YandexGPT что лучше для русского
По качеству русского языка на апрель 2026 года GigaChat-Pro и YandexGPT 4 Pro показывают сопоставимые результаты. GigaChat чуть лучше в генерации связных текстов (маркетинг, деловая переписка), YandexGPT — в задачах, связанных с фактами и поиском. Для кода обе уступают DeepSeek. Подробнее — в разделе «Бенчмарк» выше.
Сколько стоит 1000 запросов
Зависит от модели и длины запроса. Для типичного запроса (400 входных + 250 выходных токенов): GigaChat базовая — 490 ₽, GigaChat-Pro — 4 900 ₽ за 1000 запросов. Для PERS первый миллион токенов в месяц — бесплатно (≈2 500 запросов). Полная таблица цен — в разделе «Тарифы» выше.
Попробуйте: GigaChat | YandexGPT | DeepSeek | ChatGPT | Claude | Ollama