快速开始

大模型 API 流式输出与 SSE 接入教程

区分 Chat Completions、Responses 和 Messages 的 SSE 结束事件、usage 缺失与输出截断;附 curl、Python、Node.js 示例和断流判断表。

更新于 2026-11-04已核对 2026-07-12预计阅读 10 分钟适用于 Chat Completions 流式接口
配置字段已按公开文档核对;模型、价格和可用能力会变化,请以控制台与接口实时返回为准。

流式输出不是“模型更快”,而是让客户端在完整结果生成前持续收到增量内容。它能改善首字等待体验,但也会引入 SSE 解析、代理缓冲、连接中断和用量统计 等额外问题。

Link GPT、Claude 和 Gemini 的流事件需要按实际接口分别解析。Chat Completions 的分块不能直接交给 Messages 或 Responses 解析器;先保存原始事件类型和结束事件,再判断是网络中断还是客户端解析错误。

流式中断不等于没有产生用量。月卡用户应在 Link 使用日志检查失败请求和重试请求的实际消耗,并留意日额度耗尽后是否转扣钱包;不建议无上限重试长输出。

查看 Link 充值与月卡规则

SSE 是否完整:按接口检查,不按模型品牌猜测

HTTP 200、首个文本片段和连接关闭是三个不同信号,都不能单独证明任务完成。先查看最终请求路径,再按下表判断。GPT、Claude 或 Gemini 的名称不能替代协议判断;Gemini 通过 Chat Completions 接入时按该协议检查,原生接口不套用本表。

当前接口 需要记录的结束证据 仍需区分
/v1/chat/completions data: [DONE] 与每个 choice 的 finish_reason stop 是停止生成;length 是输出上限;tool_calls 需要继续处理工具,不等于业务任务结束
/v1/responses response.completed、response.failed 或 response.incomplete response.output_text.done 只结束一个文本部分;failed 与 incomplete 不能记作完整成功
/v1/messages message_stop 与 message_delta 中的 stop_reason content_block_stop 只结束一个块;tool_use 需要工具结果回传,流内 error 需独立处理

2026-11-04 对照下方官方协议资料整理。这里定义的是验收条件,不是 Link 所有模型已通过测试的声明;同一响应完整结束也不证明工具执行、文件内容或整轮 Agent 任务正确。

两种容易误判的结束情况

以下是简化的教学片段,不是 Link 线上调用记录。第一段即使收到 [DONE],仍因 length 达到输出上限;第二段说明服务端报告未完成,不能只因收到了 text delta 就判成功。

data: {"choices":[{"index":0,"delta":{},"finish_reason":"length"}]}

data: [DONE]
event: response.incomplete
data: {"type":"response.incomplete","response":{"status":"incomplete","incomplete_details":{"reason":"max_output_tokens"}}}

如果连接在任何终止事件前关闭,应记录为中断或结果未知,再查看客户端取消、超时及服务端日志。不要伪造一个 stop 或 [DONE] 补齐残缺流,也不要自动重放可能已经执行的工具。

开始前检查

先完成三个确认:

  1. 使用非流式请求验证 API Key、模型 ID 和基础接口正常。
  2. 确认目标模型与接口支持流式输出。
  3. 确认客户端、反向代理和 CDN 不会缓存或合并事件流。

如果非流式请求也失败,先排查 401、model not found 或接口路径,不要直接从 SSE 开始调试。

配置步骤

1. 使用 curl 查看原始事件流

curl -N --include --connect-timeout 10 --max-time 120 https://www.aifast.link/v1/chat/completions \
  -H "Authorization: Bearer ${AIFAST_API_KEY:?Set AIFAST_API_KEY locally before running}" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_MODEL_ID",
    "stream": true,
    "messages": [
      {"role": "user", "content": "Explain SSE in three points."}
    ]
  }'

-N 会关闭 curl 的输出缓冲。正常情况下,终端会连续出现多个 data: 数据块,而不是等待全部内容生成后一次性显示。

这条命令会向 Link 发起真实请求,可能产生费用。120 秒是本示例的总时限,不是服务 SLA;达到时限由 curl 主动中止,不能据此断言上游故障。发布日志前删除密钥、Cookie、用户输入和响应正文中的敏感信息。

2. Python SDK 流式读取

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AIFAST_API_KEY"],
    base_url="https://www.aifast.link/v1",
)

stream = client.chat.completions.create(
    model="YOUR_MODEL_ID",
    stream=True,
    messages=[
        {"role": "user", "content": "List three API pre-launch checks."}
    ],
)

for chunk in stream:
    if not chunk.choices:
        continue
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

不要假设每个数据块都有文本。工具调用、角色信息、结束原因或兼容层事件可能出现在不同字段中,正式代码需要先判断字段是否存在。

3. Node.js SDK 流式读取

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AIFAST_API_KEY,
  baseURL: "https://www.aifast.link/v1",
});

const stream = await client.chat.completions.create({
  model: "YOUR_MODEL_ID",
  stream: true,
  messages: [
    { role: "user", content: "Explain two common streaming failures." },
  ],
});

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

4. 记录完整性而不是只显示文字

生产环境至少记录:

字段 用途
请求开始时间 计算总耗时
首个响应字节时间 计算 TTFB;可能只是响应头或心跳
首个非空文本增量时间 计算客户端观察到的首字延迟;不含角色或空增量
最后事件或结束原因 判断是否完整结束
请求 ID 联系支持时定位请求
已拼接内容长度 识别中途断流
usage 与最终结算 分别记录客户端统计和账单;缺少统计不代表零消耗

Chat Completions 如何获取流式 usage?

只有接口支持该选项时,才在 stream: true 的请求中加入 stream_options: {"include_usage": true}。官方协议会在 [DONE] 前发送统计块,choices 为 [];先读取 usage,再决定是否跳过空 choices。上面的最简 SDK 示例只显示文本,没有采集账单数据。

不要把该选项直接复制到 Responses 或 Messages 请求。如果兼容接口拒绝此字段,应单独核验其支持范围,不能靠忽略错误伪造用量。中断时缺少最终统计,需要回到 Link 使用日志核对。

常见问题

服务端是流式,但网页仍然一次性显示

先用 curl -N 验证源站。如果终端能逐块显示,问题通常在你的后端框架、反向代理或前端读取逻辑。检查是否开启响应缓冲,以及是否真的按流读取 response.body。

输出到一半突然停止

记录最后一个数据块、结束原因和请求 ID。常见原因包括读取超时、网络中断、代理空闲超时、浏览器取消请求或上游生成失败。不要把残缺内容当成成功结果写入数据库。

为什么流式请求没有 usage

部分协议只在最后数据块返回完整 usage。如果连接提前中断,客户端可能拿不到最终统计。账务核对应以控制台和服务端记录为准,不能只依赖前端收到的数据块。

下一步

分别测试短文本、长文本、中文、多字节字符、主动取消、网络断开和代理超时。上线前还应为流式请求设置最大任务时长、断线状态和用户可见的重试入口。

已经遇到中断时,按 502 与断流判断表确定下一项检查;接口通过后,再用 API 成本计算器把实际用量和计费重试纳入预算。计算器不需要 Key,演示值不是 Link 报价。

常见问题

SSE 返回 HTTP 200 或出现文字,就算请求成功了吗?

不算。HTTP 200 只说明响应已开始;还要按当前协议检查终止事件、结束原因和任务产物。收到部分文字后断开,或达到输出上限,都不能当成完整业务结果。

Responses 和 Messages 也必须等到 data: [DONE] 吗?

不需要混用协议标记。Chat Completions 检查 [DONE] 和 finish_reason;Responses 区分 response.completed、response.failed、response.incomplete;Messages 检查 message_stop 和 stop_reason。单个内容块结束不等于整条消息结束。

流式 usage 缺失,是否代表没有扣费?

不是。Chat Completions 支持时可请求 stream_options.include_usage,但中断可能导致最终统计丢失。客户端缺少 usage 不等于零消耗,应核对 Link 使用日志与最终结算,重试也可能产生新的用量。

已核对来源

参考与核对来源

下一步

先检测当前接口,再决定修复、迁移或创建测试 Key

用临时限额 Key 检查模型声明、Token、SSE 和工具调用;需要新接口时再核对模型与价格。

模型质量检测查看模型与价格注册使用