跳转到主要内容
如果你是 Realtime API 的新手,可尝试 stepfun-realtime-api
本指南将介绍使用 Realtime API 时模型功能(如音频生成、文本生成、函数调用)所需的事件流程,以及如何理解实时会话的状态。 在模型生成响应的过程中,服务器会发出多个生命周期事件。您可以监听这些事件(如 response.text.delta),在响应生成时向用户提供实时反馈。 服务器发出的事件完整列表见Realtime API 事件列表,它们按大致的发出顺序排列,同时包含文本生成相关的客户端事件。

实时语音到语音会话

实时会话是模型与连接的客户端之间的有状态交互。会话的关键组成部分包括:
  • 会话(Session) 对象:控制交互参数,如使用的模型、生成输出的语音、其他配置等。
  • 对话(Conversation):表示当前会话中生成的用户输入项和模型输出项。
  • 响应(Responses):模型生成的音频或文本项,会被添加到对话中。
输入音频缓冲区与 WebSocket 如果使用 WebSocket 处理音频,需要通过发送包含 base64编码音频的 JSON 事件,手动与输入音频缓冲区交互。 所有这些组件共同构成了实时会话。您将使用客户端事件更新会话状态,并监听服务器事件以响应会话中的状态变化。 如需手动建立连接,也可通过 WebSocket 直接对接。

快速开始:创建 WebSocket 语音链路

通过 WebSocket 连接需使用以下连接信息:
类别详情
URLwss://api.stepfun.com/v1/realtime
查询参数model:需连接的实时模型,比如 step-audio-2/step-audio-2-mini/step-1o-audio
请求头Authorization: Bearer YOUR_API_KEY
以下是多个通过上述连接信息初始化 WebSocket 连接的示例,可用于对接 Realtime API:

示例1:使用 ws 模块(Node.js 环境)

示例2:使用 websocket-client 库(Python 环境)

一旦您通过 WebSocket 连接到实时 API,就可以调用实时模型进行语音到语音对话。这需要您发送客户端事件来发起操作,并监听服务器事件以响应实时 API 执行的操作。

会话生命周期事件

通过 WebSocket 启动会话后,服务器会发送 session.created 事件,表明会话已准备就绪。在客户端,您可以通过 session.update 事件更新当前会话配置。大多数会话属性可以随时更新,但模型用于音频输出的 voice(语音)在会话期间模型首次以音频响应后,就无法再修改。实时会话的最长持续时间为30分钟 以下示例展示了通过 session.update 客户端事件更新会话的操作。 更新本会话中模型使用的系统指令
当会话更新后,服务器会发出 session.updated 事件,包含会话的新状态。
相关客户端事件相关服务器事件
session.updatesession.created
session.updated

文本输入与输出

要使用实时模型生成文本,您可以向当前对话添加文本输入,请求模型生成响应,并监听服务器发送的事件以了解模型响应的进度。为了生成文本,会话必须配置为 text(文本)模态(默认已启用)。 使用 conversation.item.create 客户端事件创建新的文本对话项。 创建包含用户输入的对话项
将用户消息添加到对话后,发送 response.create 事件以启动模型响应。如果当前会话同时启用了音频和文本,模型将同时返回音频和文本内容。如果只想生成文本,可以在发送 response.create 客户端事件时指定,如下所示。 生成仅文本响应
当响应完全生成后,服务器会发出 response.done 事件。该事件将包含模型生成的完整文本,如下所示。 监听 response.done 以查看最终结果
在模型生成响应的过程中,服务器会发出多个生命周期事件。您可以监听这些事件(如 response.text.delta),在响应生成时向用户提供实时反馈。服务器发出的事件完整列表见下文的“相关服务器事件”,它们按大致的发出顺序排列,同时包含文本生成相关的客户端事件。
事件类型说明
conversation.item.createconversation.item.created
response.output_item.added
response.content_part.added
response.text.delta
response.text.done
response.content_part.done
response.output_item.done
response.done
rate_limits.updated

音频输入与输出

实时 API 最强大的功能之一是与模型进行语音到语音交互,无需中间的文本转语音或语音转文本步骤。这降低了语音界面的延迟,并为模型提供了更多关于语音输入的语调和抑扬顿挫的信息。

语音选项

实时会话支持配置多种内置语音用于音频输出。您可以通过 session.updateresponse.create 请求中的 voice 参数来设置模型的声音。当前的语音选项包括 qingchunshaonvwenrounanshengelegantgentle-femalelivelybreezy-female 等。
请注意,一旦模型在会话中生成了音频,该会话的 voice 设置将无法修改。
step-audio-2 模型支持音色复刻功能。您可以通过上传音频文件创建自定义音色,并在实时会话的 voice 参数中使用其 ID。详情请参考复刻音色

使用 WebSocket 处理音频

通过 WebSocket 发送和接收音频时,您需要做更多工作来从客户端发送媒体和从服务器接收媒体。下面是一个表格,描述了 WebSocket 会话期间通过 WebSocket 发送和接收音频所需的事件流程。 以下事件按生命周期顺序排列,但有些事件(如 delta 事件)可能同时发生。
生命周期阶段客户端事件服务器事件
会话初始化session.updatesession.created
session.updated
用户音频输入conversation.item.create(发送完整音频消息)
input_audio_buffer.append(分块流式传输音频)
input_audio_buffer.commit(禁用 VAD 时使用)
response.create(禁用 VAD 时使用)
input_audio_buffer.speech_started
input_audio_buffer.speech_stopped
input_audio_buffer.committed
服务器音频输出input_audio_buffer.clear(禁用 VAD 时,或者需要主动创建一轮输出时使用)conversation.item.created
response.created
response.output_item.created
response.content_part.added
response.audio.delta
response.audio_transcript.delta
response.text.delta
response.audio.done
response.audio_transcript.done
response.text.done
response.content_part.done
response.output_item.done
response.done
rate_limits.updated

向服务器流式传输音频输入

要向服务器流式传输音频输入,可以使用 input_audio_buffer.append 客户端事件。该事件要求您通过套接字向实时 API 发送Base64编码的音频字节块。每个块的大小不能超过15 MB。 输入块的格式可以为整个会话配置,也可以为每个响应单独配置。
  • 会话级:session.update 中的 session.input_audio_format
  • 响应级:response.create 中的 response.input_audio_format
向对话附加音频输入字节

发送完整音频消息

也可以创建包含完整音频录制的对话消息。使用 conversation.item.create 客户端事件创建带有 input_audio 内容的消息。 创建完整音频输入对话项

处理 WebSocket 的音频输出

您需要监听 response.audio.delta 事件,其中包含模型发来的 base64编码音频数据块。您需要缓冲这些块并将其写入文件。 请注意,response.audio.doneresponse.done 事件实际上不包含音频数据,只包含音频内容的转录文本。要获取实际的字节数据,需要监听 response.audio.delta 事件。 输出块的格式可以为整个会话配置,也可以为每个响应单独配置。
  • 会话级:session.update 中的 session.output_audio_format
  • 响应级:response.create 中的 response.output_audio_format
监听 response.audio.delta 事件

语音活动检测

默认情况下,实时会话启用语音活动检测(VAD),这意味着 API 会判断用户何时开始或停止说话,并自动响应。

禁用 VAD

可以通过 session.update 客户端事件将 turn_detection 设置为 null 来禁用 VAD。这对于需要精细控制音频输入的界面很有用,例如按键通话界面。 禁用 VAD 后,客户端必须手动发出一些额外的客户端事件来触发音频响应:
  • 手动发送 input_audio_buffer.commit,这将为对话创建新的用户输入项。
  • 手动发送 response.create 以触发模型的音频响应。
  • 在开始新的用户输入之前发送 input_audio_buffer.clear

自定义 Tool Call

目前 StepFun Realtime API 内置了以下工具: web_search 和 retrieval。 另外,也支持自定义工具调用(Tool Call),用户可以根据需求定义自己的工具并在会话中使用。

工具配置方式

在 update session 请求中配置 tools 参数来启用工具功能:
通过 type: "web_search" 工具,模型可实时访问互联网,获取最新信息和数据。适用于需要广泛知识和实时数据的场景。

使用示例

在 update session 请求的 tools 参数中添加以下结构:
即可在回复中启用 web_search 工具。

高级参数

  • options.top_k: 指定返回结果的数量,默认为 5。
  • options.timeout_seconds: 请求超时时间,默认为 3 秒。
示例
启用后,模型在回答需要搜索的问题时会自动调用该工具,你不需要做其他额外的逻辑处理。

知识库检索工具 retrieval

通过 type: "retrieval" 工具,模型可实时访问指定知识库(Vector Store),精准回答用户问题。适用于垂直领域问答场景,用户可以提前定义用于参考的回复数据。

一、功能配置步骤

在 update session 请求的 tools 参数中添加以下结构:

二、参数详解

参数是否必填说明
type固定值 “retrieval”,声明使用知识库检索功能。
function.description关键提示:用1-2句话明确触发条件,例如:“仅当问题与菜谱、食材或烹饪相关时使用本知识库”。
options.vector_store_id知识库的唯一 ID(示例:133192900598194176),需提前在平台创建。
options.prompt_template定制化提示模板,支持占位符 \{\{knowledge\}\}(检索到的片段)和 \{\{query\}\}(用户原始问题);若不提供则使用默认模板。默认:从文档 \{\{knowledge\}\} 中找到问题 \{\{query\}\} 的答案。根据文档内容中的语句提取答案,若文档中无答案则告知用户无法回答

三、工作原理

  1. 触发条件:用户问题匹配 description 中的领域描述(如“如何煎牛排?”)。
  2. 知识检索:
  • 系统根据 vector_store_id 定位知识库。
  • 将用户问题 \{\{query\}\} 嵌入为向量,检索最相关的知识片段。
  1. 生成答案:
  • 自动将 \{\{knowledge\}\}\{\{query\}\} 填入 prompt_template。
  • 模型基于模板生成最终回复(例:“根据知识库:牛排需每面煎2分钟…”)。

四、最佳实践

  1. 在 description 中精准描述: "description": "仅限回答菜谱步骤、食材替代方案、烹饪时间问题,其他问题忽略检索"
  2. 错误处理:在 prompt_template 中明确无答案时的响应,例如:“下面是检索到的结果: {{knowledge}},如果未在知识库中找到关于{{query}}的信息,请告诉用户尝试更具体的问题。”
  3. 避免冲突:如果你启用了内置工具的 web_search ,模型可能会尝试调用 web 搜索而不是在知识库,你可以在初始化会话时,通过 instructions 引导其优先使用知识库:
    “你是一个专业烹饪助手,当用户询问菜谱、食材处理或烹饪技巧时,必须从知识库中检索答案。若知识库无相关信息,需明确告知用户。“

自定义 Tool Call

通过自定义函数调用,你可以扩展模型的能力,使其能够执行特定业务逻辑(如查询天气、生成星座运势等)。基本流程如下:
  1. 配置函数:在会话级别定义可用函数
  2. 检测调用:模型根据用户输入决定是否调用函数
  3. 执行函数:客户端使用生成的参数执行自定义代码
  4. 返回结果:将函数执行结果返回给模型并获取最终响应

函数配置

通过 session.update 事件的 session.tools 参数添加函数定义:

函数调用流程

1. 检测函数调用
当用户输入触发函数调用时,您将收到包含函数调用参数的对话项:
2. 接收函数参数
参数生成过程中会收到增量更新事件:
参数生成完成后会收到完成事件:
3. 返回函数执行结果
客户端执行函数后,需要将结果返回给模型:
4. 触发模型响应
返回函数结果后,需要手动触发模型生成最终响应:

完整示例:星座运势查询

1. 配置星座运势函数
2. 用户请求与函数调用
用户输入:“我的运势如何?我是水瓶座。” 模型检测到需要调用函数,返回调用参数:
3. 返回函数执行结果
4. 获取最终响应
通过以上流程,您可以灵活扩展模型能力,实现各种自定义功能。
注意,函数调用和语音可能会出现在同一轮,比如如果有 get_weather 函数,模型可能会先输出:“让我先查查天气” 的口水话,然后再创建函数调用。这样的好处是,如果有比较复杂的函数调用,可以利用语音播放的时间来并行处理函数调用的生成。但是你需要注意要在语音播放完后才调用 response.create 来触发最终回复。

开发技巧

实现开场白

在某些应用场景下,你可能希望在对话开始时,模型能够主动打招呼或介绍自己。这可以通过在创建会话时,使用特殊的提示词实现:
客户端主动创建响应:
这样,模型会主动输出问候语:你好,我是阶跃星辰开发的 AI 助手。

更灵活的 VAD

如果你使用 server_vad 模式,但每次 append 的音频片段较长,可能会导致系统响应延迟较高。这是因为 VAD 需要积累足够长的音频数据才能做出判断,建议以20ms 左右的间隔提交音频,以保证检测的实时性。 此外,VAD 判断用户停止说话的依据是检测到连续若干帧的空白或低音量音频。如果你提交的音频末尾没有包含足够的静音帧,VAD 可能无法准确识别语音结束点,从而导致系统未能及时触发自动回复。为避免该问题,应确保在语音段后保留一定时长的静音音频。 最佳实践建议:
  • 音频分段提交:尽量以小块(如 20ms~30ms)为单位频繁提交音频数据;
  • 如果你用音频文件输入,务必在文件确保有一定的静音段;

网页中播放声音示例代码

为了支持流式 pcm16 的播放,你的播放逻辑需要支持多次 append 动作。另外,为了可以及时打断,最好可以实现及时清空缓冲区的功能。 这里是一份简易的示例代码,用 typescript 写成,适用于浏览器环境。

错误处理

服务器在会话期间遇到错误情况时,会发出 error 事件。有时,这些错误可以追溯到您的应用发出的客户端事件。 与 HTTP 请求和响应不同(其中响应隐式关联到客户端的请求),我们需要使用客户端事件上的 event_id 属性来确定其中某个事件是否在服务器上触发了错误情况。下面的代码展示了这种方法,客户端尝试发出不支持的事件类型。
客户端发送的这个失败事件将触发如下错误事件: