API и SDKИнструкция
Потоковые ответы через Python
Выводим ответ модели по мере генерации с официальным пакетом openai — синхронный и асинхронный примеры, рассуждения модели, учёт токенов и обработка ошибок.

Содержание
В потоковом режиме ответ приходит частями, пока модель его ещё генерирует: пользователь сразу видит текст, а не ждёт ответ целиком. API использует стандартный потоковый формат OpenAI (server-sent events), а официальный пакет openai для Python всё разбирает сам.
Каждый пример ниже полный: скопируйте его в файл и запустите. Примеры проверены на Python 3.10.12 с openai 3.31.0 на локальном тестовом сервере, повторяющем потоковый формат API (синтаксис и выполнение).
Подготовка#
pip install openai
export CHEAPTOKENS_API_KEY="вставьте-ваш-ключ"Минимальный пример#
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
stream = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": "Напиши хокку о задержках сети"}],
stream=True,
)
for chunk in stream:
if not chunk.choices: # служебная часть без текста, например последняя — с числом токенов
continue
text = chunk.choices[0].delta.content
if text:
print(text, end="", flush=True)
print()Важны две детали:
- Пропускайте части без
choices. В некоторых частях нет текста — например, в последней, с числом токенов. delta.contentбывает пустым. Первая часть часто содержит только роль, последняя — толькоfinish_reason. Печатайте текст, только когда он есть.
Рассуждающие модели#
zai- рассуждает перед ответом. Рассуждение приходит в отдельном поле reasoning_, а сам ответ — в content. SDK сохраняет незнакомые поля, поэтому прочитать его можно через getattr. Это полный пример со своим клиентом и своим потоком:
import os
import sys
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
stream = client.chat.completions.create(
model="zai-org/GLM-5.3-Flash",
messages=[{"role": "user", "content": "Является ли 1013 простым числом?"}],
stream=True,
)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
thinking = getattr(delta, "reasoning_content", None)
if thinking:
print(thinking, end="", flush=True, file=sys.stderr) # рассуждение → stderr
if delta.content:
print(delta.content, end="", flush=True) # ответ → stdout
print()Рассуждение может занять время, прежде чем появится первое слово ответа, — ещё одна причина использовать поток.
Число токенов#
Попросите статистику через stream_options — она придёт в последней части, у которой нет choices:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
stream = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": "Объясни идемпотентность одним абзацем"}],
stream=True,
stream_options={"include_usage": True},
)
usage = None
for chunk in stream:
if chunk.usage:
usage = chunk.usage
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if usage:
print(f"\ninput: {usage.prompt_tokens}, output: {usage.completion_tokens}")Умножьте эти числа на тарифы модели — получите стоимость запроса; подробнее — в статье Как рассчитать расходы AI-агента.
asyncio#
В асинхронном коде используйте AsyncOpenAI и async for. У клиента своё имя, async_client, — чтобы не путать его с синхронным client из других примеров:
import asyncio
import os
from openai import AsyncOpenAI
async_client = AsyncOpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
async def main() -> None:
stream = await async_client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": "Назови три применения очереди сообщений"}],
stream=True,
)
async for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
print()
asyncio.run(main())Досрочная остановка и тайм-ауты#
Чтобы остановить генерацию, выйдите из цикла. Если открыть поток через with, соединение закроется в конце блока. Тайм-аут клиента задан явно; кроме того, SDK сам повторяет некоторые неудачные запросы (max_retries, по умолчанию 2).
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
timeout=120, # секунды; длинным ответам нужно время
)
received = ""
with client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": "Напиши длинный рассказ о маяке"}],
stream=True,
) as stream:
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
received += chunk.choices[0].delta.content
if len(received) > 300: # досрочная остановка: текста достаточно
break
print(received)Ошибки#
Ошибки, которые случаются до первой части ответа, — неверный ключ, пустой баланс, неизвестная модель — выбрасываются исключениями при создании потока:
import os
import openai
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
try:
stream = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": "Привет"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
print()
except openai.AuthenticationError: # 401: неверный или заменённый ключ
print("Проверьте API-ключ")
except openai.BadRequestError as e: # 400: например, неизвестный ID модели
print("Ошибка в запросе:", e.message)
except openai.APIStatusError as e: # другие коды, например 402, когда закончился баланс
print(e.status_code, e.message)Полный список кодов и способов исправления — в статье Частые ошибки подключения и их исправление.
Что передаётся по сети#
Для отладки посмотрите на «сырой» поток через curl (-N отключает буферизацию):
curl -N https://api.cheaptokens.dev/v1/chat/completions \
-H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "deepseek-ai/DeepSeek-V4-Flash-0731", "stream": true,
"messages": [{"role": "user", "content": "Hi"}]}'Каждое событие — строка data: {…} с JSON-частью ответа; поток заканчивается строкой data: [DONE]. Строки, начинающиеся с двоеточия, — служебные комментарии, которые приходят во время долгих пауз, чтобы соединение не обрывалось; клиенты их пропускают.



