# 流式输出 (/docs/zh-CN/api/streaming)

每个对话模型都支持在全部四种协议上流式输出。在 Chat Completions、Responses 或 Messages 中设置 `stream: true`，在 Gemini 中调用 `:streamGenerateContent`。响应是一串 server-sent events，格式与你调用的协议一致。流以 token 用量结尾（Chat Completions 需要你主动要求）；Chat Completions、Responses 和 Messages 的流还会带上本次请求的费用。

| 协议 | 事件 | 最后一个事件 |
|---|---|---|
| Chat Completions | `data: {chat.completion.chunk}` | `data: [DONE]` |
| Responses | `response.created`、`response.output_text.delta`…… | `response.completed`、`response.incomplete` 或 `response.failed` |
| Messages | `message_start`、`content_block_delta`、`ping`…… | `message_stop` |
| Gemini | `data: {GenerateContentResponse}` | 带有 `usageMetadata` 的那个数据块 |

## 通过 SDK 调用 [#通过-sdk-调用]

```python tab="Python"
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.ohmygpt.com/v1",
    api_key=os.environ["OHMYGPT_API_KEY"],
)

stream = client.chat.completions.create(
    model="ohmygpt/mock",
    messages=[{"role": "user", "content": "ping"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

```ts tab="TypeScript"
import OpenAI from 'openai'

const client = new OpenAI({
  baseURL: 'https://api.ohmygpt.com/v1',
  apiKey: process.env.OHMYGPT_API_KEY,
})

const stream = await client.chat.completions.create({
  model: 'ohmygpt/mock',
  messages: [{ role: 'user', content: 'ping' }],
  stream: true,
})
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}
```

<Callout>
与 OpenAI 一致，Chat Completions 的流只在设置了 `"stream_options": {"include_usage": true}` 时返回用量。用量放在最后一个数据块里，这个数据块的 `choices` 是空数组，所以取下标之前先检查 `choices`。
</Callout>

## 原始数据帧 [#原始数据帧]

设置了 `stream_options.include_usage` 时，Chat Completions 流的结尾：

```text
data: {"id":"chatcmpl-ohmygpt-mock","object":"chat.completion.chunk","created":1793318400,"model":"mock","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-ohmygpt-mock","object":"chat.completion.chunk","created":1793318400,"model":"mock","choices":[],"usage":{"prompt_tokens":29,"completion_tokens":17,"total_tokens":46}}

: x-cost-credits: 0
data: [DONE]
```

Messages 流的结尾：

```text
event: message_delta
data: {"delta":{"stop_reason":"end_turn","stop_sequence":null,"stop_details":null},"type":"message_delta","usage":{"input_tokens":33,"output_tokens":17}}

: x-cost-credits: 0
event: message_stop
data: {"type":"message_stop"}
```

如果自己解析流，请逐行读取，跳过以 `:` 开头的行，解析 `data: ` 之后的 JSON。在 Chat Completions 中，读到 `data: [DONE]` 即停止。

## 流式请求的费用 [#流式请求的费用]

Chat Completions、Responses 和 Messages 的流会在最后一个事件之前，以一行 SSE 注释 `: x-cost-credits: N` 给出本次费用（单位为 Credits）。SDK 会跳过注释行，所以要拿到它，需要读取原始流。

对于任何请求，无论是否流式、使用哪种协议，都可以用响应头 `X-Request-ID` 查询费用：

```bash
curl https://api.ohmygpt.com/v1/generations/$REQUEST_ID \
  -H "Authorization: Bearer $OHMYGPT_API_KEY"
```

```json
{
  "object": "request_receipt",
  "id": "01a19b55-f2f8-787b-941c-7e3e0bda2b0a",
  "status": "succeeded",
  "model": { "id": "google/gemini-3.1-flash-lite" },
  "usage": { "input_tokens": 16, "output_tokens": 3, "reasoning_tokens": 118, "cache_read_tokens": 0, "cache_creation_tokens": 0 },
  "cost": { "list_credits": 48, "credits": 43 }
}
```

## 流式输出中途出错 [#流式输出中途出错]

第一个事件之前发生的错误，会以普通的 HTTP 错误返回。如果流已经以 `200` 开始、模型随后出错，流会以一个错误事件结束，格式与你调用的协议一致：

| 协议 | 最后一个事件 |
|---|---|
| Chat Completions | `data: {"error": {...}}` |
| Responses | `event: response.failed`，带有 `response.error.code` 和 `response.error.message` |
| Messages | `event: error`，内容为 `{"type": "error", "error": {...}}` |
| Gemini | `data: {"error": {"code": ..., "status": ...}}` |

出错之前收到的输出不完整，请重新发送请求。

## 取消请求 [#取消请求]

关闭连接即可停止流。生成随即停止，只按已经发给你的输出计费。
