语音接待 Agent 的电话链路与延迟设计
文章围绕真实电话接待,组合 LiveKit、Whisper、Claude 和 Chatterbox,讲解通话、转写、推理及语音合成链路。内容包含架构、延迟预算与起步代码,并列出组件许可证和 API 依赖。
AI 深度解读
能开口聊天,离能替牙科诊所接电话还差一整套工程。作者给出的方案是用 LiveKit 接真实电话,用 Whisper 转写、Claude 决策、Chatterbox 合成语音,再连接日历、短信和诊所系统。
它最有参考价值的地方,是把预约、转人工、打断和延迟放进同一条链路。但原文提供的是架构起点和代码骨架,没有端到端实测,也没有足以验证收入预期的经营数据。适合拿来拆需求,不能直接当成交付方案。
电话接进来以后,模型只负责其中一段
作者引用 Patient Prism 对 8,280 家牙科机构、1,150 万通电话的分析:31% 的来电者在接通前挂断;另引 CallRail 调查,只有 42% 的消费者表示会留下语音留言。这些数据解释了诊所为什么关心漏接,但原文没有交代统计口径,也没有证明 AI 能挽回多少预约。
系统从公共电话网 PSTN 开始,通过 SIP trunk 把电话接入 LiveKit,每通电话对应一个房间,Agent worker 加入房间处理音频。患者仍拨诊所原来的号码,诊所可以迁移号码,也可以做呼叫转接。
worker 内部再分工:语音活动检测(VAD)和轮次检测器判断来电者是否说完;GPU 上的 faster-whisper 分块转写;Claude 结合规则调用工具;Chatterbox 按句生成语音。最后,工具连接日历、诊所业务软件、CRM 和短信。
作者把扩容概括为增加 worker 进程。房间隔离确实方便分配任务,但 GPU 容量、并发上限和外部系统限流,原文都没有展开。
这里的设计价值是职责清楚:电话接入、识别、决策、发声、业务执行可以分别替换,不必绑死在一个模型供应商上。
预约有没有成功,必须由业务系统回答
会改变业务状态的动作,必须通过工具执行并返回结果。
Claude 不能只在对话里宣布预约成功。它要提交工具调用,由代码完成预约,再根据结果回复患者。下面这段代码展示了规则和工具如何接到 Agent 上:
CLINIC_RULES = """You are the receptionist for Bright Smile Dental.
Hours: Mon to Sat, 9am to 6pm. Book cleanings, checkups and consultations only.
Never give medical advice. Transfer emergencies, billing disputes and upset callers to a human.
Keep answers under two sentences."""
class Receptionist(Agent):
def __init__(self):
super().__init__(instructions=CLINIC_RULES)
@function_tool
async def check_slots(self, date: str) -> list[str]:
"""Return free appointment slots for a date (YYYY-MM-DD)."""
return await calendar.free_slots(date)
@function_tool
async def book_appointment(self, name: str, phone: str, slot: str, reason: str) -> str:
"""Book a slot and send an SMS confirmation."""
booking = await calendar.book(name, phone, slot, reason)
await sms.send(phone, f"Confirmed: {slot} at Bright Smile Dental")
return booking.id
要看紧 calendar.book 和 sms.send 两行:它们先后执行,示例没有处理预约成功但短信失败,也没有展示重复调用、号源冲突的处理。calendar、sms 的实现同样需要自己补。
提示词规定周一至周六 9:00 至 18:00 营业,只预约洁牙、检查和咨询,不提供医疗建议;紧急情况、账单争议和情绪激动的来电者转人工,每次回答少于两句。但这些只是模型指令。营业时间、可预约项目等硬约束,仍应在业务代码里校验。
原文架构还列出 take_message、transfer,示例却没有实现。读者不能把写进提示词的「转人工」当成已经具备的能力。
对话自然不自然,要测整条链路
作者认为,沉默超过约一秒,来电者就开始觉得尴尬。因此延迟应该从「用户停止说话」量到「Agent 开始出声」,不能只看模型生成速度。
原文提到了分阶段延迟预算,但提供的内容中没有具体预算表。能确认的建议是:分块转写、流式接收模型回答、按完整句子合成语音,尽早播放第一句;同时缩短提示词,让 GPU worker 保持预热。
模型配置骨架如下:
session = AgentSession(
stt=WhisperSTT(model="large-v3", device="cuda"),
llm=ClaudeLLM(),
tts=ChatterboxTTS(voice_ref="voices/clinic_consented.wav"),
)
注意 WhisperSTT、ClaudeLLM、ChatterboxTTS 都是作者要求自行编写的适配器,分别封装 faster-whisper、Anthropic SDK 和 Chatterbox Python 包,并非导入后即可使用的现成实现。
起步命令是 lk agent init my-agent --template agent-starter-python,模板使用托管模型。作者也提醒 LiveKit API 变化较快,示例中的 AgentServer、@server.rtc_session、session.start、session.generate_reply 应按当前文档核对签名。
另外,来电者插话时必须立即停止 TTS;需要人工处理时,要有接通前台并交接上下文的路径。否则再流畅的语音,也可能把人困在自动回复里。
我的判断
我赞同作者把价值放在行业软件集成、可靠转接和效果报告上。和只做语音聊天演示相比,这些环节更接近诊所真正购买的服务。
但「100 家诊所 × 每月 300 美元 = 30,000 美元月度经常性收入(MRR)」只是收入算式。原文没有给出通话成本、GPU 利用率、人工支持投入、预约成功率或续费数据,也没有自托管与托管语音服务的对照。所谓「更短提示词、按句合成、保持预热通常收益最大」,也应视为作者的工程经验,不能当成本文实测结论。
自写适配器有利于替换模型,也会增加接口维护和流式事件处理的工作。一般团队是否值得这么做,要看定制需求与维护能力。
原文标注了 AI 辅助写作,结尾推广开发服务,阅读时应把架构建议与商业宣传分开。它还提出声音克隆需取得书面许可,并称 Chatterbox 会为每次输出添加水印;水印的具体机制和效果没有展开。健康及个人信息的存储、保留规则,也只是提醒,尚未形成方案。
能拿来做什么
- 先跑通一个完整预约闭环:查询空位、执行预约、发送短信,再覆盖重复提交和短信失败,确认模型回复始终依据实际结果。
- 用 Python worker 承接本文的语音链路;如果现有业务在 Node 中,可以让工具调用已有预约接口,把号源校验和预约约束放在服务端。
- 给每通电话记录转写、工具调用和各阶段延迟,再用真实通话定位等待发生在哪一段;同时提前确定记录内容、访问权限和保留期限。
- 把插话停止播放、紧急情况转人工、账单争议交接列入验收场景,并向诊所展示接听、转接与预约结果,验证服务是否产生价值。