Перейти к содержимому
ChatGPT API
Документация

Документация

Как работать с ChatGPT API

Обновлено:

Первый запрос отправить просто. Сложности начинаются дальше: как вести диалог, чтобы модель помнила контекст, что делать с ошибкой 429, какие параметры влияют на цену. Собрал здесь всё, что нужно знать после первого запроса.

Из чего состоит запрос

Запрос это массив сообщений. У каждого своя роль, и модель читает их по порядку. Роли определяют, что модель считает инструкцией, а что репликой собеседника.

system
Инструкция, которая задаёт поведение на весь диалог: тон, формат ответа, ограничения. Ставится первой и не меняется от реплики к реплике.
user
Сообщение пользователя. То, на что модель отвечает прямо сейчас.
assistant
Предыдущие ответы самой модели. Нужны, чтобы она помнила, что уже говорила.
Структура запроса
curl https://api.llm-gate.tech/v1/chat/completions \
  -H "Authorization: Bearer $CHATGPT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6.1-sol",
    "messages": [
      { "role": "system", "content": "Отвечай кратко, по-русски." },
      { "role": "user", "content": "Что такое токен?" }
    ]
  }'

Как вести диалог

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

Диалог из двух реплик
messages = [
    {"role": "system", "content": "Отвечай кратко, по-русски."},
    {"role": "user", "content": "Что такое токен?"},
    # ответ модели возвращаем обратно в массив
    {"role": "assistant", "content": "Токен это кусок текста примерно в 4 символа."},
    {"role": "user", "content": "А сколько их в слове «программирование»?"},
]

response = client.chat.completions.create(
    model="gpt-6.1-sol",
    messages=messages,
    max_completion_tokens=300,
)

История растёт, а вместе с ней растёт счёт: вы платите за все входные токены при каждом запросе. На длинных диалогах обрезайте старые реплики или сжимайте их в краткое резюме.

Стриминг: ответ по мере генерации

По умолчанию ответ приходит целиком, когда модель договорила. На длинных ответах это выглядит как зависание на десятки секунд. Со стримингом текст идёт кусками сразу, как в веб-интерфейсе ChatGPT.

Включение стриминга
stream = client.chat.completions.create(
    model="gpt-6.1-sol",
    messages=messages,
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
  • Чат-интерфейсы, где пользователь ждёт ответ и смотрит на экран
  • Длинные ответы: тексты, код, разборы
  • Не нужен для фоновых задач: классификации, извлечения полей, обработки по расписанию

Параметры, которые реально влияют

Их больше, но на практике вы будете трогать эти четыре. Остальные имеют смысл в редких сценариях.

ПараметрЧто делаетКогда менять
modelВыбирает модельГлавный рычаг цены и качества. Начинайте с дешёвой, поднимайтесь при провале
max_completion_tokensПотолок длины ответаСтавьте всегда: защищает от неожиданно длинного и дорогого ответа
temperatureРазброс формулировокНиже для фактов и кода, выше для текстов и идей
streamОтдавать ответ потокомВключайте в интерфейсах, где человек ждёт

Ошибки и что они значат

Код ответа говорит, чья это проблема и надо ли повторять запрос. Половина ошибок лечится ретраем, половина нет.

КодПричина и что делать
401Ключ неверный или не передан. Проверьте заголовок Authorization и сам ключ. Повторять бесполезно
404Модель не найдена. Сверьте написание с нашим списком моделей. Повторять бесполезно
429Превышен лимит запросов. Повторите с задержкой, увеличивая её с каждой попыткой
5xxСбой на стороне сервиса. Повторите с задержкой, обычно проходит
ТаймаутОтвет не пришёл вовремя. Поднимите таймаут клиента: длинные ответы с рассуждением идут дольше

Ретраи с нарастающей задержкой

Повторять сразу бессмысленно: при лимите вы просто получите ту же ошибку и потратите квоту. Увеличивайте паузу с каждой попыткой и ограничьте их число. Официальные SDK так умеют из коробки, но если ходите в API напрямую, схема такая.

Повтор с задержкой
import time

for attempt in range(5):
    try:
        response = client.chat.completions.create(
            model="gpt-6.1-sol",
            messages=messages,
            max_completion_tokens=300,
        )
        break
    except Exception:
        if attempt == 4:
            raise
        time.sleep(2 ** attempt)  # 1, 2, 4, 8 секунд

Как не переплачивать

Счёт растёт не от числа запросов, а от объёма токенов. Четыре вещи, которые дают основную экономию.

Ставьте потолок ответа

Без max_completion_tokens модель может выдать максимум длины, и вы за это заплатите. Один параметр защищает от самых дорогих случаев.

Не отправляйте лишнюю историю

Каждый запрос оплачивает весь массив сообщений целиком. На длинных диалогах обрезайте старое или заменяйте кратким резюме.

Держите стабильную часть промпта в начале

Повторяющийся префикс попадает в кеш и стоит в разы дешевле обычного ввода. Переменные данные ставьте в конец.

Берите модель под задачу

Классификацию и извлечение полей незачем гонять на флагмане: разница в цене доходит до ста раз при одинаковом результате.

Частые вопросы

Почему модель не помнит предыдущие сообщения?+

Потому что API не хранит состояние. Каждый запрос обрабатывается с нуля, и всё, что модель знает о диалоге, вы передаёте в массиве messages. Добавляйте туда её прошлые ответы с ролью assistant.

Что делать с ошибкой 429?+

Это превышение лимита запросов. Повторите запрос через паузу, увеличивая её с каждой попыткой: секунда, две, четыре. Если 429 приходит постоянно, снизьте частоту обращений или распределите нагрузку во времени.

Нужно ли переписывать код ради нашего API?+

Нет. Формат запросов и ответов совпадает с OpenAI, поэтому официальные SDK работают после замены base URL и ключа. Весь код из этой статьи одинаково работает и с официальным API, и с нашим.

Как узнать, сколько токенов съел запрос?+

Ответ API содержит поле usage с числом входных и выходных токенов. Сохраняйте его в логах: это единственный способ понять, куда уходят деньги, до того как придёт счёт.

Стриминг стоит дороже?+

Нет, цена за токены одинаковая. Меняется только способ доставки ответа: кусками по мере генерации вместо одного пакета в конце.

Что дальше