Skip to main content

Overview

Text generation endpoints support Server-Sent Events (SSE) streaming. Set stream: true to receive output token by token as it’s generated.

Streaming-Enabled Endpoints

  • /v1/chat/completions — OpenAI compatible
  • /v1/messages — Claude Messages
  • /v1/responses — OpenAI Responses API

Example

from openai import OpenAI

client = OpenAI(
    base_url="https://www.qingbo.dev/v1",
    api_key="your-api-key"
)

stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "写一首短诗"}],
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://www.qingbo.dev/v1',
  apiKey: 'your-api-key'
});

const stream = await client.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: '写一首短诗' }],
  stream: true
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content || '');
}

SSE Data Format

Each chunk is a single data: {json} SSE event:
data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"你"},"index":0}]}

data: {"id":"chatcmpl-xxx","choices":[{"delta":{"content":"好"},"index":0}]}

data: [DONE]
When the stream ends, you’ll receive data: [DONE].

Final Frame Usage & Billing (cost)

The last data frame before [DONE] carries the usage and the charge of the call:
data: {"id":"chatcmpl-xxx","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":8,"total_tokens":20,"cost":150}}

data: [DONE]
  • usage.cost is the actual quota charged for this call (integer); use it for per-call reconciliation
  • It is sent by default; explicitly passing stream_options: {"include_usage": false} disables it
  • With the OpenAI SDK, the final chunk’s chunk.usage contains this data