从 LiveKit Agents 使用 ThunderPhone
将 ThunderPhone 语音智能体作为 LiveKit Agents 会话的实时(语音到语音)模型运行,并借助 LiveKit 房间、SIP 和电话功能进行集成。
LiveKit Agents 是一个基于 LiveKit 房间构建实时语音智能体的开源框架。ThunderPhone 作为 实时模型接入:框架发送参与者的音频,ThunderPhone 返回智能体的语音、转写文本和函数调用,而 LiveKit 的房间、 SIP 中继和电话服务负责传输音频。语音识别、语言模型、语音、 轮次管理、47 种语言和工具均在 ThunderPhone 上运行。
通过这种方式拨打的通话会显示在通话记录中,并且会像任何其他实时通话一样, 按您产品的每分钟费率计费。无需订阅,也不涉及 ThunderPhone 电话号码。
安装
pip install livekit-plugins-thunderphone
export THUNDERPHONE_API_KEY=sk_live_... # a secret API key该插件封装了 LiveKit 的 OpenAI Realtime 模型,因为 ThunderPhone 的
Realtime WebSocket 使用相同的协议。它
需要 livekit-agents 1.8 或更高版本。
运行已保存的智能体
智能体执行的所有操作(提示词、语音、引擎、语言、工具、问候语、 静默确认)均在 ThunderPhone 上配置。会话仅传输音频。
from livekit.agents import Agent, AgentSession, JobContext, WorkerOptions, cli
from livekit.plugins import thunderphone
async def entrypoint(ctx: JobContext):
session = AgentSession(llm=thunderphone.RealtimeModel(agent_id=12))
await session.start(agent=Agent(instructions=""), room=ctx.room)
if __name__ == "__main__":
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))已保存的智能体会在 ThunderPhone 上进行问候并运行自己的工具;LiveKit
Agent 的指令和工具不会被发送。ThunderPhone 智能体挂断时,
通话结束,会话也随之关闭。
内联配置会话
如果不使用 agent_id,指令和工具将与 OpenAI 的方式相同,来自 LiveKit Agent。
product 用于选择引擎,voice 用于选择 ThunderPhone 语音。
from livekit.agents import Agent, AgentSession, RunContext, function_tool
from livekit.plugins import thunderphone
class Receptionist(Agent):
def __init__(self):
super().__init__(instructions="You are Acme Dental's receptionist. Be brief.")
@function_tool
async def check_availability(self, context: RunContext, date: str) -> dict:
"""Free appointment slots on a date."""
return {"slots": await calendar.free_slots(date)}
async def entrypoint(ctx: JobContext):
session = AgentSession(
llm=thunderphone.RealtimeModel(product="bolt", voice="olivia", language="es"),
)
await session.start(agent=Receptionist(), room=ctx.room)
await session.generate_reply() # the agent speaks firstThunderPhone 会在通话开始时冻结指令和工具,因此通话过程中不支持
update_instructions、update_tools 以及会更改它们的智能体交接。
内联会话由客户端驱动:当您调用 generate_reply() 或参与者完成一轮发言时,
智能体会进行回应。
选项
| 参数 | 含义 |
|---|---|
api_key | 密钥(sk_live_...)。默认使用 THUNDERPHONE_API_KEY。 |
agent_id | 运行已保存的智能体。与 product 和 voice 互斥。 |
product | 用于内联会话的引擎:spark、bolt 或 storm。 |
voice | 用于内联会话的 ThunderPhone 语音名称。 |
language | 内联会话的主要语言提示,例如 es。 |
from_number, to_number | 当房间接入电话线路时,要在通话中记录的号码。 |
live_transcripts | 在话语进行过程中流式传输来电者转录片段(额外计费)。 |
base_url | 端点覆盖,默认值为 wss://api.thunderphone.com/v1/realtime。 |
事件
ThunderPhone 在实时协议之上添加了平台事件。会话会发出以下事件:
@session.llm.session.on("thunderphone_call_ended") # or on the RealtimeSession you hold
def on_call_ended(event):
print("call ended:", event["reason"])会话上线后,RealtimeSession 会公开 call_id。通话结束后,使用它调用
GET /v1/calls/{call_id} 获取录音、转录和评分。其他所有 call.* 事件(转接、按键、语音被忽略)都会作为 thunderphone_call_event 到达。
限制
- 轮次检测在服务器端执行且始终启用;框架端的轮次检测
(
AgentSession上的turn_detection)会被忽略。 - 通话开始后,无法更改指令和工具。
- 双向音频均为 24 kHz 的 16 位单声道 PCM。
- 视频帧会被忽略。