API e SDKGuia
Respostas em streaming em Python
Imprima a resposta do modelo conforme ela é gerada com o pacote oficial openai — exemplos síncronos e assíncronos, saída de raciocínio, uso de tokens e tratamento de erros.

Nesta página
Com streaming, a resposta chega pedaço por pedaço enquanto o modelo ainda a está gerando, então seus usuários veem o texto imediatamente em vez de esperar pela resposta completa. A API usa o formato de streaming padrão da OpenAI (server-sent events), e o pacote oficial openai Python cuida disso para você.
Todos os exemplos abaixo são completos: copie para um arquivo e execute. Os exemplos foram verificados com Python 3.10.12 e openai 3.31.0 contra um servidor de teste local que reproduz o formato de streaming da API (sintaxe e execução).
Configuração#
pip install openai
export CHEAPTOKENS_API_KEY="paste-your-key-here"Exemplo mínimo#
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": "Write a haiku about latency"}],
stream=True,
)
for chunk in stream:
if not chunk.choices: # service chunk without text, e.g. the final usage chunk
continue
text = chunk.choices[0].delta.content
if text:
print(text, end="", flush=True)
print()Dois detalhes importam:
- Ignore chunks sem
choices. Alguns chunks não carregam texto — por exemplo, o chunk final com o uso de tokens. delta.contentpode estar vazio. O primeiro chunk geralmente carrega apenas o role, e o último apenasfinish_reason. Imprima texto somente quando ele estiver presente.
Modelos de raciocínio#
zai- raciocina antes de responder. O raciocínio vem em um campo separado do delta, reasoning_, e a resposta em si em content. O SDK mantém campos desconhecidos, então você pode lê-lo com getattr. Este é um exemplo completo com seu próprio client e seu próprio stream:
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": "Is 1013 a prime number?"}],
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) # reasoning → stderr
if delta.content:
print(delta.content, end="", flush=True) # answer → stdout
print()O raciocínio pode demorar um pouco antes que a primeira palavra da resposta apareça — mais um motivo para usar streaming.
Uso de tokens#
Peça o uso com stream_options; ele vem no último chunk, que não tem 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": "Explain idempotency in one paragraph"}],
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}")Multiplique esses números pelas tarifas do modelo para obter o custo da requisição — veja How to estimate the cost of an AI agent.
asyncio#
Em código assíncrono use AsyncOpenAI e async for. O client tem seu próprio nome, async_client, para não colidir com o síncrono client dos outros exemplos:
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": "Name three uses of a message queue"}],
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())Parar cedo e timeouts#
Saia do loop para interromper a geração. Abrir o stream com with fecha a conexão quando o bloco termina. O timeout do client é definido explicitamente; o SDK também tenta novamente algumas requisições com falha por conta própria (max_retries, 2 por padrão).
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
timeout=120, # seconds; long answers take time
)
received = ""
with client.chat.completions.create(
model="deepseek-ai/DeepSeek-V4-Flash-0731",
messages=[{"role": "user", "content": "Write a long story about a lighthouse"}],
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: # stop early: enough text received
break
print(received)Erros#
Erros que acontecem antes do primeiro chunk — chave errada, saldo vazio, modelo desconhecido — são lançados como exceções quando você cria o stream:
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": "Hello"}],
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: wrong or rotated key
print("Check the API key")
except openai.BadRequestError as e: # 400: e.g. unknown model ID
print("Bad request:", e.message)
except openai.APIStatusError as e: # other statuses, e.g. 402 when the balance is used up
print(e.status_code, e.message)Uma lista completa de códigos de status e correções está em Common connection errors and how to fix them.
O que trafega na rede#
Para depurar, veja o stream bruto com curl (-N desativa o buffering):
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"}]}'Cada evento é uma linha data: {…} com um chunk JSON; o stream termina com data: [DONE]. Linhas que começam com dois-pontos são comentários de keep-alive enviados durante longas pausas — os clients as ignoram.



