Open in
将 ThunderPhone 与 OpenAI Realtime 客户端配合使用
使用已保存的智能体或内联会话配置,将兼容 OpenAI Realtime 的服务器客户端连接到 ThunderPhone。
ThunderPhone 实现了 OpenAI Realtime 事件模型中经过聚焦的一个子集。 现有服务端客户端可以在使用 ThunderPhone 语音智能体时,保留其 WebSocket、音频、会话和响应事件流。
连接前准备
您需要 ThunderPhone 组织密钥 API 密钥,以及能够打开 WebSocket 的服务器运行环境。请勿从浏览器代码连接,也不要将密钥暴露给浏览器。若要使用已保存的智能体,请先部署该智能体并复制其数字智能体 ID。
连接至:
wss://api.thunderphone.com/v1/realtime从您的服务器对 WebSocket 升级进行身份验证:
Authorization: Bearer sk_live_YOUR_API_KEY对于无法设置握手标头的客户端,可以使用查询字符串身份验证,但 URL 更容易泄露到日志中。
选择配置由谁负责
| 模式 | 连接方式 | 配置来源 |
|---|---|---|
| 已保存的智能体 | ?agent_id=12 | 已部署的提示词、语音、产品、语言、知识库,以及兼容的服务器端运行工具 |
| 内联 | 无 agent_id | 客户端首次被接受的 session.update |
已保存的智能体
使用已部署的智能体 ID 连接:
wss://api.thunderphone.com/v1/realtime?agent_id=12智能体会在套接字连接时启动。其问候语仍然可用,
但 Realtime 会禁用其语音静默确认,并省略 transfer_call
和 send_keypad_input。其他兼容工具将在 ThunderPhone 上运行。请勿为此模式发送内联指令或由客户端执行的工具。
在智能体启动前,通过 input_audio_format、
output_audio_format、input_rate 和 output_rate 查询参数设置传输音频。连接后,您无法更改已保存的配置或音频格式。
内联会话
不使用 agent_id 时,请等待 session.created,然后发送 session.update:
{
"type": "session.update",
"session": {
"type": "realtime",
"instructions": "Answer questions clearly and keep responses brief.",
"audio": {
"input": {
"format": { "type": "audio/pcm", "rate": 24000 }
},
"output": {
"format": { "type": "audio/pcm", "rate": 24000 },
"voice": "olivia"
}
},
"config": {
"product": "bolt"
}
}
}首次被接受的更新会创建通话。session.updated 表示
会话已激活。此后,指令、语音、产品、工具和音频格式均无法更改。
内联会话没有自动问候语或语音静默确认。若要让智能体先说话,请追加一条系统或用户消息,并发送
response.create。完全空闲的会话仍会在平台的静默通话限制时结束,默认限制为 600 秒。
使用官方 OpenAI SDK
传入以 /v1 结尾的 WebSocket 基础 URL;SDK 会追加 /realtime。model 值是兼容性名称,不会选择 ThunderPhone 产品。请在会话配置或已保存的智能体中选择产品。
此连接检查会创建一个内联 Bolt 会话,持续打印事件直到第一个 session.updated,然后关闭。使用最简 Python 客户端流式传输音频。
import asyncio
import os
from openai import AsyncOpenAI
async def main():
client = AsyncOpenAI(
api_key=os.environ["THUNDERPHONE_API_KEY"],
websocket_base_url="wss://api.thunderphone.com/v1",
)
async with client.realtime.connect(
model="thunderphone-realtime"
) as connection:
await connection.session.update(session={
"type": "realtime",
"instructions": "Listen to the caller and help them complete the call.",
"config": {"product": "bolt"},
})
async for event in connection:
print(event.type)
if event.type == "session.updated":
break
if __name__ == "__main__":
asyncio.run(main())保留您现有的输入音频追加、响应音频增量、中断、函数调用、错误处理以及套接字正常关闭逻辑。内联自定义函数在您的客户端中执行;请通过 Realtime 协议返回其结果。已保存智能体的工具在 ThunderPhone 上执行。
会话生命周期和失败情况
一个 WebSocket 对应一个通话。无效的智能体 ID 或被拒绝的内联配置会产生 error 事件。请在收到 session.updated 后再将会话视为已启动。声明实际的输入和输出格式以及采样率:PCM 采样率不匹配会导致音频播放过快或过慢,而不会产生验证错误。
会话启动后,请在您的应用完成时正常关闭套接字。内联会话可以使用由客户端执行的函数。已保存智能体会话使用由 ThunderPhone 运行的兼容工具,且不提供转接或按键输入功能。
测试集成
请从最简 Python WAV 客户端开始,并使用与其声明采样率相同的单声道 PCM16 WAV。验证:
- 服务器接受配置并发送
session.updated。 - 输入以预期速度生成转录和响应音频事件。
- 中断和响应取消会停止剩余的输出音频。
- 内联函数结果或已保存智能体工具结果会返回给模型。
- 无效输入会产生由您的客户端处理的
error事件。 - 您的客户端关闭套接字,且该通话显示在通话记录中。
Realtime WebSocket 参考列出了可接受的事件、音频格式、会话字段和完整示例。
费用
Realtime 通话采用所选产品的常规每分钟费率。启用实时转录增量会为整个会话增加每分钟附加费用;有关费率,请参阅实时转录,有关产品费率,请参阅定价。
POST /v1/realtime/sessions 是独立的托管 LiveKit 路径。它会创建房间和作用域参与者令牌;直接 WebSocket 连接不需要它。
如需框架集成,请参阅从 Pipecat 使用 ThunderPhone和从 LiveKit Agents 使用 ThunderPhone。