Потоковая выдача (SSE) и подсчёт токенов
При stream: true ответ приходит не одним JSON-объектом, а потоком событий SSE: текст появляется по мере генерации. Ниже — как читать этот поток, как получить расход токенов и как посчитать стоимость запроса.
Включение стриминга
Стриминг включается булевым параметром stream в том же запросе POST /chat/completions. Ответ приходит с типом содержимого text/event-stream и состоит из строк вида data: {...} — в каждой такой строке лежит один JSON-чанк.
Чанк повторяет структуру обычного ответа, но вместо готового сообщения содержит дельту: choices[0].delta. Текст ответа накапливается в delta.content, ход рассуждений — в delta.reasoning_content (в thinking mode). Завершение генерации отмечается в choices[0].finish_reason.
Пока инференс не начался, сервер удерживает соединение. В стриминге для этого приходят SSE-комментарии : keep-alive — строки, начинающиеся с двоеточия, они не несут данных и их нужно пропускать. Если инференс не начался за 10 минут, сервер закрывает соединение. В нестриминговых ответах роль keep-alive играют пустые строки.
curl https://api.deepseek.com/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-d '{
"model": "deepseek-flash",
"messages": [{"role": "user", "content": "Перечисли три свойства SSE."}],
"stream": true,
"stream_options": {"include_usage": true}
}'
Расход токенов: stream_options.include_usage
При стриминге объект usage нужно запросить отдельно: stream_options.include_usage — булев параметр, который требует stream: true. Если передать его без стриминга, запрос завершится HTTP 400.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
stream = client.chat.completions.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "Зачем нужен контекстный кэш? Три абзаца."}],
stream=True,
stream_options={"include_usage": True},
)
usage = None
for chunk in stream:
# usage приходит отдельным чанком ближе к концу потока,
# поэтому сохраняем его по ходу чтения
if chunk.usage is not None:
usage = chunk.usage
if not chunk.choices:
continue
delta = chunk.choices[0].delta
if getattr(delta, "reasoning_content", None):
print(delta.reasoning_content, end="", flush=True)
if delta.content:
print(delta.content, end="", flush=True)
print()
if usage is None:
# Так бывает, если поток оборвался и финальный чанк с usage не пришёл
print("usage не получен: проверьте stream_options.include_usage")
else:
print("prompt_tokens:", usage.prompt_tokens)
print("completion_tokens:", usage.completion_tokens)
print("total_tokens:", usage.total_tokens)
print("попало в кэш:", usage.prompt_cache_hit_tokens)
print("не попало в кэш:", usage.prompt_cache_miss_tokens)
print("токенов на рассуждение:", usage.completion_tokens_details.reasoning_tokens)
| Поле | Значение |
|---|---|
prompt_tokens |
Все токены ввода; равен сумме prompt_cache_hit_tokens и prompt_cache_miss_tokens |
completion_tokens |
Все токены вывода, включая токены рассуждений |
total_tokens |
Сумма ввода и вывода |
prompt_cache_hit_tokens |
Токены ввода, совпавшие с контекстным кэшем: тариф в десятки раз дешевле |
prompt_cache_miss_tokens |
Токены ввода, которые в кэш не попали |
prompt_tokens_details.cached_tokens |
Равен prompt_cache_hit_tokens |
completion_tokens_details.reasoning_tokens |
Сколько токенов ушло на цепочку рассуждений (в non-thinking — ноль) |
Кэширование на диске включено по умолчанию, включать его вручную не нужно и управлять им нельзя. Хит возможен только при полном совпадении с сохранённым префиксом, поэтому 100% попаданий не гарантируется. Кэш влияет только на цену ввода: сам вывод всё равно генерируется заново.
Нужен API-ключ сегодня
Регистрация по email или Telegram занимает пару минут, оплата идёт в рублях, VPN не нужен. Один ключ работает и с DeepSeek, и с другими моделями.
Как посчитать стоимость запроса
Формула простая: количество токенов умножается на цену за 1M токенов и делится на 1 000 000. Отдельно считаются три составляющие — попадание в кэш, промах и вывод. Ниже — цены deepseek-flash вне пика.
| Составляющая | Цена за 1M токенов |
|---|---|
| Ввод, попадание в кэш | $0.003 |
| Ввод, промах мимо кэша | $0.15 |
| Вывод | $0.60 |
В часы пик те же значения ровно вдвое выше: $0.006, $0.30 и $1.20. Пик — 01:00–04:00 и 06:00–10:00 UTC по будням, кроме китайских государственных праздников; это соответствует 04:00–07:00 и 09:00–13:00 по Москве. Всё остальное время, включая полные выходные, — вне пика. Точные цены обеих моделей — в разделе «Цены и расчёт».
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
# Цены deepseek-flash вне пика, USD за 1M токенов
PRICE_HIT = 0.003 # ввод, попадание в кэш
PRICE_MISS = 0.15 # ввод, промах мимо кэша
PRICE_OUT = 0.60 # вывод
response = client.chat.completions.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "Сформулируй три тезиса о кэше промптов."}],
extra_body={"thinking": {"type": "disabled"}, "reasoning_effort": "none"},
)
u = response.usage
cost = (
u.prompt_cache_hit_tokens * PRICE_HIT
+ u.prompt_cache_miss_tokens * PRICE_MISS
+ u.completion_tokens * PRICE_OUT
) / 1_000_000
print(f"ввод из кэша: {u.prompt_cache_hit_tokens}")
print(f"ввод мимо кэша: {u.prompt_cache_miss_tokens}")
print(f"вывод: {u.completion_tokens}")
print(f"стоимость запроса: ${cost:.6f}")
# В часы пик умножайте на 2 — например, cost * 2.
Подсчёт токенов до отправки запроса
Официального эндпоинта, который считает токены до отправки запроса, нет. Оценить объём можно двумя способами:
- офлайн-токенизатор DeepSeek:
https://cdn.deepseek.com/api-docs/deepseek_v4_tokenizer.zip; - калькулятор на официальной странице Token & Token Usage.
Для быстрой прикидки без инструментов используют ориентиры: 1 английский символ ≈ 0.3 токена, 1 китайский иероглиф ≈ 0.6 токена, слово, число или знак ≈ 1 токен. Изображения считаются по размерам (они сжимаются или растягиваются), верхняя граница — 1024 токена на изображение. Vision доступен только у deepseek-flash.
Оценка по символам — только ориентир. Реальный расход всегда берите из usage и логируйте его: расхождение с прикидкой на смешанном русско-английском тексте может быть заметным.
Нужен API-ключ сегодня
Регистрация по email или Telegram занимает пару минут, оплата идёт в рублях, VPN не нужен. Один ключ работает и с DeepSeek, и с другими моделями.
Читайте также
- Цены и расчёт Полные цены обеих моделей, часы пик и вне пика, разбор списания баланса.
-
Режим рассуждений
Почему токены рассуждения попадают в вывод и как ими управлять через
reasoning_effort. -
JSON и инструменты
Стриминг вызова инструментов и разбор
tool_calls. - Примеры на Python Готовый скрипт потокового вывода с подсчётом стоимости.