OpenAI API 流式输出

2026-11-06 18:37 更新

默认情况下,OpenAI API生成完整输出后才通过一次HTTP响应返回。长输出等待较久,流式响应可在模型继续生成时,先打印或处理已生成的部分。

本指南介绍HTTP的stream=true及服务器发送事件(SSE)。需要持久连接和通过previous_response_id增量输入时,见Responses WebSocket模式。

启用流式响应

对Responses设置stream=True(其他语言按其布尔值写法):

来源示例 1(javascript):

// [中文] 开启流式并逐个读取Responses语义事件,任务是快速重复“double bubble bath”十次。
import { OpenAI } from "openai";
const client = new OpenAI();

const stream = await client.responses.create({
  model: "gpt-6-astra",
  input: [
    {
      role: "user",
      content: "Say 'double bubble bath' ten times fast.",
    },
  ],
  stream: true,
});

for await (const event of stream) {
  console.log(event);
}

来源示例 2(python):

## [中文] 开启流式并逐个读取Responses语义事件,任务是快速重复“double bubble bath”十次。
from openai import OpenAI

client = OpenAI()

stream = client.responses.create(
    model="gpt-6-astra",
    input=[
        {
            "role": "user",
            "content": "Say 'double bubble bath' ten times fast.",
        },
    ],
    stream=True,
)

for event in stream:
    print(event)

来源示例 3(go):

// [中文] 开启流式并逐个读取Responses语义事件,任务是快速重复“double bubble bath”十次。
package main

import (
    "context"
    "fmt"

    "github.com/openai/openai-go/v3"
    "github.com/openai/openai-go/v3/responses"
)

func main() {
    client := openai.NewClient()
    stream := client.Responses.NewStreaming(context.Background(), responses.ResponseNewParams{
        Model: "gpt-6-astra",
        Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Say 'double bubble bath' ten times fast.")},
    })
    for stream.Next() {
        fmt.Println(stream.Current().Type)
    }
    if err := stream.Err(); err != nil {
        panic(err)
    }
}

来源示例 4(java):

// [中文] 开启流式并逐个读取Responses语义事件,任务是快速重复“double bubble bath”十次。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseStreamEvent;

ResponseCreateParams params =
    ResponseCreateParams.builder()
        .model("gpt-6-astra")
        .input("Say 'double bubble bath' ten times fast.")
        .build();

try (StreamResponse<ResponseStreamEvent> stream = client.responses().createStreaming(params)) {
  stream.stream().forEach(System.out::println);
}

来源示例 5(csharp):

// [中文] 开启流式并逐个读取Responses语义事件,任务是快速重复“double bubble bath”十次。
using OpenAI.Responses;
#pragma warning disable OPENAI001

string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);

var responses = client.CreateResponseStreamingAsync(
    "gpt-6-astra",
    "Say 'double bubble bath' ten times fast."
);

await foreach (StreamingResponseUpdate response in responses)
{
    if (response is StreamingResponseOutputTextDeltaUpdate delta)
    {
        Console.Write(delta.Delta);
    }
}

来源示例 6(ruby):

## [中文] 开启流式并逐个读取Responses语义事件,任务是快速重复“double bubble bath”十次。
require "openai"

openai = OpenAI::Client.new

stream = openai.responses.stream(
  model: "gpt-6-astra",
  input: [
    {
      role: "user",
      content: "Say 'double bubble bath' ten times fast."
    }
  ]
)

stream.each do |event|
  puts(event)
end

同页HTML另有Chat Completions版本,其分块结构不能直接套用为Responses事件:

来源示例 13(javascript):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
import OpenAI from "openai";
const openai = new OpenAI();

const stream = await openai.chat.completions.create({
  model: "gpt-6-astra",
  messages: [
    {
      role: "user",
      content: "Say 'double bubble bath' ten times fast.",
    },
  ],
  stream: true,
});

for await (const chunk of stream) {
  console.log(chunk);
  console.log(chunk.choices[0].delta);
  console.log("****************");
}

来源示例 14(python):

## [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
from openai import OpenAI

client = OpenAI()

stream = client.chat.completions.create(
    model="gpt-6-astra",
    messages=[
        {
            "role": "user",
            "content": "Say 'double bubble bath' ten times fast.",
        },
    ],
    stream=True,
)

for chunk in stream:
    print(chunk)
    print(chunk.choices[0].delta)
    print("****************")

来源示例 15(go):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
package main

import (
    "context"
    "fmt"

    "github.com/openai/openai-go/v3"
)

func main() {
    client := openai.NewClient()
    stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{
        Model: "gpt-6-astra",
        Messages: []openai.ChatCompletionMessageParamUnion{
            openai.UserMessage("Say 'double bubble bath' ten times fast."),
        },
    })
    for stream.Next() {
        fmt.Println(stream.Current())
    }
    if err := stream.Err(); err != nil {
        panic(err)
    }
}

来源示例 16(java):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params =
    ChatCompletionCreateParams.builder()
        .model("gpt-6-astra")
        .addUserMessage("Say hello.")
        .build();

try (StreamResponse<ChatCompletionChunk> stream =
    client.chat().completions().createStreaming(params)) {
  stream.stream().forEach(System.out::println);
}

来源示例 17(csharp):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
using System.ClientModel.Primitives;
using OpenAI.Chat;

string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, key);

await foreach (
    StreamingChatCompletionUpdate update in client.CompleteChatStreamingAsync(
        new UserChatMessage("Say double bubble bath ten times fast.")
    )
)
{
    Console.WriteLine(ModelReaderWriter.Write(update));
}

来源示例 18(ruby):

## [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
require "openai"

client = OpenAI::Client.new
stream = client.chat.completions.stream(
  model: "gpt-6-astra", messages: [
    {
      role: :user,
      content: "Say hello."
    }
  ]
)
stream.each { |event| puts(event) }

Responses使用预定义模式的语义事件,可订阅关心的类型。事件全集见接口参考,部分类型定义如下:

来源示例 7(javascript):

// [中文] 来源列举流式事件类型,依赖SDK类型定义;这是类型片段,不是完整可执行应用。
for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  } else if (event.type === "response.completed") {
    console.log("\nResponse completed.");
  } else if (event.type === "error") {
    console.error(event.message);
  }
}

来源示例 8(python):

## [中文] 来源列举流式事件类型,依赖SDK类型定义;这是类型片段,不是完整可执行应用。
StreamingEvent = (
    ResponseCreatedEvent
    | ResponseInProgressEvent
    | ResponseFailedEvent
    | ResponseCompletedEvent
    | ResponseOutputItemAdded
    | ResponseOutputItemDone
    | ResponseContentPartAdded
    | ResponseContentPartDone
    | ResponseOutputTextDelta
    | ResponseOutputTextAnnotationAdded
    | ResponseTextDone
    | ResponseRefusalDelta
    | ResponseRefusalDone
    | ResponseFunctionCallArgumentsDelta
    | ResponseFunctionCallArgumentsDone
    | ResponseFileSearchCallInProgress
    | ResponseFileSearchCallSearching
    | ResponseFileSearchCallCompleted
    | ResponseCodeInterpreterInProgress
    | ResponseCodeInterpreterCallCodeDelta
    | ResponseCodeInterpreterCallCodeDone
    | ResponseCodeInterpreterCallInterpreting
    | ResponseCodeInterpreterCallCompleted
    | Error
)

来源示例 9(go):

// [中文] 来源列举流式事件类型,依赖SDK类型定义;这是类型片段,不是完整可执行应用。
type StreamingEvent = responses.ResponseStreamEventUnion

来源示例 10(java):

// [中文] 来源列举流式事件类型,依赖SDK类型定义;这是类型片段,不是完整可执行应用。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseStreamEvent;

ResponseCreateParams params =
    ResponseCreateParams.builder().model("gpt-5.5").input("Say hello.").build();

try (StreamResponse<ResponseStreamEvent> stream = client.responses().createStreaming(params)) {
  stream.stream().forEach(System.out::println);
}

来源示例 11(ruby):

## [中文] 来源列举流式事件类型,依赖SDK类型定义;这是类型片段,不是完整可执行应用。
require "openai"

client = OpenAI::Client.new
stream = client.responses.stream(model: "gpt-5.5", input: "Say hello.")
stream.each { |event| puts(event) }

读取响应

SDK中的每个事件是有类型的实例,也可用type识别。某些生命周期事件只出现一次,另一些在生成过程中反复出现。文本流常见事件:

来源示例 12():

- `response.created`
- `response.output_text.delta`
- `response.completed`
- `error`

Chat Completions分块示意及消费循环保留如下,分别是输出片段和代码示例:

来源示例 19(text):

{ role: 'assistant', content: '', refusal: null }
****************
{ content: 'Why' }
****************
{ content: " don't" }
****************
{ content: ' scientists' }
****************
{ content: ' trust' }
****************
{ content: ' atoms' }
****************
{ content: '?\n\n' }
****************
{ content: 'Because' }
****************
{ content: ' they' }
****************
{ content: ' make' }
****************
{ content: ' up' }
****************
{ content: ' everything' }
****************
{ content: '!' }
****************
{}
****************

来源示例 20(javascript):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
import OpenAI from "openai";
const client = new OpenAI();

const stream = await client.chat.completions.create({
  model: "gpt-6-astra",
  messages: [
    {
      role: "user",
      content: "Say 'double bubble bath' ten times fast.",
    },
  ],
  stream: true,
});

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

来源示例 21(python):

## [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
from openai import OpenAI

client = OpenAI()

stream = client.chat.completions.create(
    model="gpt-6-astra",
    messages=[
        {
            "role": "user",
            "content": "Say 'double bubble bath' ten times fast.",
        },
    ],
    stream=True,
)

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

来源示例 22(go):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
package main

import (
    "context"
    "fmt"

    "github.com/openai/openai-go/v3"
)

func main() {
    client := openai.NewClient()
    stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{
        Model: "gpt-6-astra",
        Messages: []openai.ChatCompletionMessageParamUnion{
            openai.UserMessage("Say 'double bubble bath' ten times fast."),
        },
    })
    for stream.Next() {
        if len(stream.Current().Choices) > 0 {
            fmt.Print(stream.Current().Choices[0].Delta.Content)
        }
    }
    if err := stream.Err(); err != nil {
        panic(err)
    }
}

来源示例 23(java):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params =
    ChatCompletionCreateParams.builder()
        .model("gpt-6-astra")
        .addUserMessage("Say 'double bubble bath' ten times fast.")
        .build();

try (StreamResponse<ChatCompletionChunk> stream =
    client.chat().completions().createStreaming(params)) {
  stream.stream()
      .flatMap(chunk -> chunk.choices().stream())
      .flatMap(choice -> choice.delta().content().stream())
      .forEach(System.out::print);
}

来源示例 24(csharp):

// [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
using OpenAI.Chat;

string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, key);

await foreach (
    StreamingChatCompletionUpdate update in client.CompleteChatStreamingAsync(
        new UserChatMessage("Say double bubble bath ten times fast.")
    )
)
{
    foreach (ChatMessageContentPart part in update.ContentUpdate)
    {
        Console.Write(part.Text);
    }
}

来源示例 25(ruby):

## [中文] 使用Chat Completions的choices/delta读取分块文本;与Responses的事件结构不同,任务仍为重复短语十次。
require "openai"

client = OpenAI::Client.new
stream = client.chat.completions.stream(
  model: "gpt-6-astra",
  messages: [
    {
      role: :user,
      content: "Say 'double bubble bath' ten times fast."
    }
  ]
)
stream.text.each { |text| print(text) }

完整类型见流式接口参考。

高级用例

内容审核风险

生产环境流式输出更难审核,因为部分内容可能难以完整判断,会影响获准使用方式。

如果在生成请求中请求审核分数,分数在完整生成输出可用后才到达,不随文本增量返回。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号