# 流式响应：边写边到的答案

> 使用 server-sent events 流式传输 chat completions：stream: true、分块格式、最后一个事件中的 token 用量，以及 curl、Python 和 Node.js 示例。

- URL: https://llmwithcrypto.com/zh/docs/streaming/
- 最后更新: 2026-10-23
- 发布者: LLMwithCrypto (https://llmwithcrypto.com)

使用 `stream: true`，答案会在模型书写时以小片段到达，就像聊天界面逐字显示文本一样。格式是 OpenAI 的格式：server-sent events，每个事件一个 JSON 分块，然后是 `[DONE]`。

**快速回答 — 如何从 LLMwithCrypto 流式获取 chat completion？**

在 `POST https://llmwithcrypto.com/api/v1/chat/completions` 的请求体中加入 `"stream": true`。**LLMwithCrypto** 随后以 server-sent events 作答：每条 `data:` 行包含一个 `chat.completion.chunk`，其中 `delta.content` 带有一段文本，流最后以 `data: [DONE]` 结束。加入 `"stream_options": {"include_usage": true}` 可在最后一个分块中获得 token 计数。这适用于所有模型，截至 2026 年 10 月 23 日的文档如此说明。

## 为什么要用流式？

对人来说，第一批词片刻即至，而不必等整个答案写完。大模型的长答案可能需要许多秒才能完成；流式传输时，读者可以立刻开始阅读。

对程序来说则没那么重要：需要完整文本的脚本从流式中得不到好处，反而要处理更多解析。有人在看时用流式，否则发送普通请求。无论哪种方式价格都一样。按 token 从余额扣费：输入和输出 token 由模型自己的 tokenizer 计数，按该模型每 1M token 的价格计费。以错误结束的调用不收费。

*curl：-N 保持连接不缓冲*

```bash
curl -sN "https://llmwithcrypto.com/api/v1/chat/completions" \
  -H "Authorization: Bearer $LLMWITHCRYPTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4.1-flash",
    "messages": [{"role": "user", "content": "Write a haiku about latency."}],
    "stream": true,
    "stream_options": {"include_usage": true},
    "max_tokens": 120
  }'

```

*Python：文本到达时即打印*

```python
import os

from openai import OpenAI

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

stream = client.chat.completions.create(
    model="deepseek-v4.1-flash",
    messages=[{"role": "user", "content": "Write a haiku about latency."}],
    stream=True,
    stream_options={"include_usage": True},
    max_tokens=120,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        print("\n", chunk.usage.prompt_tokens, "in,", chunk.usage.completion_tokens, "out")

```

*Node.js：对分块使用 for await*

```javascript
import OpenAI from 'openai';

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

const stream = await client.chat.completions.create({
  model: 'deepseek-v4.1-flash',
  messages: [{ role: 'user', content: 'Write a haiku about latency.' }],
  stream: true,
  stream_options: { include_usage: true },
  max_tokens: 120,
});
for await (const chunk of stream) {
  const text = chunk.choices[0]?.delta?.content;
  if (text) process.stdout.write(text);
  if (chunk.usage) console.log(`\n${chunk.usage.prompt_tokens} in, ${chunk.usage.completion_tokens} out`);
}

```

## 流在传输线上是什么样子？

每个事件是一行以 `data: ` 开头，后跟一个空行。第一个分块通常带有 `role`，接下来的分块各带几个 `content` 字符，带有 `finish_reason` 的分块结束答案。使用 `include_usage` 时，还会再跟一个分块，带有空的 `choices` 数组和 `usage` 对象。流总是以 `data: [DONE]` 结束。下方的 id 和计数仅为示例。

*一个简短答案的 server-sent events（示例）*

```text
data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{"content":"Packets"},"finish_reason":null}]}

data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{"content":" cross the"},"finish_reason":null}]}

data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[],"usage":{"prompt_tokens":14,"completion_tokens":19,"total_tokens":33}}

data: [DONE]

```

## 如果流中断了怎么办？

第一个 token 之前发现的错误（例如密钥错误或余额不足）会以带 JSON 正文的普通 HTTP 错误返回，而不是流；[错误页面](https://llmwithcrypto.com/zh/docs/errors/) 列出了这些错误。生成过程中的错误会提前结束流，且没有 `finish_reason`。

如果你自己关闭连接，生成就会停止。此时你需要为输入和已生成的 token 付费，与任何调用一样。代码应将没有 `finish_reason` 且没有 `[DONE]` 就结束的流视为不完整，如需完整答案则重新发送请求。

## 流式传输：常见问题

### 流式传输会更贵吗？

不会。相同的 token 按相同的价格计费。按 token 从余额扣费：输入和输出 token 由模型自己的 tokenizer 计数，按该模型每 1M token 的价格计费。以错误结束的调用不收费。

### 我可以在工具调用时使用流式吗？

可以，在支持工具的模型上：函数名和参数会分片出现在 `delta.tool_calls` 中，使用前必须拼接起来。[工具调用页面](https://llmwithcrypto.com/zh/docs/tool-calling/) 展示了非流式循环，起步更简单。

### 为什么流式调用中我没有收到用量信息？

添加 `"stream_options": {"include_usage": true}`。没有它，流式响应不携带 token 计数；仪表盘仍会显示这些计数。

---

LLMwithCrypto: LLMwithCrypto 是一个兼容 OpenAI 的开放权重模型 LLM API，涵盖 DeepSeek V4 Pro、DeepSeek V4.1 Flash、DeepSeek R1、Qwen3.5 397B A17B、Qwen3 235B A22B Instruct、gpt-oss-120b、gpt-oss-20b、GLM-4.7、Llama 3.3 70B Instruct、Gemma 4 31B、Mistral Large 3、Mistral Small 4，按 token 从预付加密货币余额中扣费，价格比公共托管商的中位价低 5%。无需 KYC：无需身份证件、无需自拍、无需文件。不存储提示词和输出。
