语音智能体(Voice Agent)和普通聊天机器人最大的区别是:用户开口说完,到听见回复,整段延迟得压在 1 秒以内,否则对话就断开、像卡顿的电话。LiveKit Agents 是开源的实时语音智能体框架(基于 WebRTC),它把语音识别(STT)→ 大模型(LLM)→ 语音合成(TTS)用语音活动检测(VAD)和打断处理串成一条可生产的流水线。本教程带你从装依赖、配密钥,到跑通一个能自然插话、会调用工具的语音助手,全程可复现。
先搞懂:语音智能体为什么难
语音对话是一条接力:用户说话 → VAD 判断"说完了"→ STT 转成文字 → LLM 生成回答 → TTS 合成语音 → 播放。每一段都吃延迟,加起来要控制住:
| 阶段 | 典型耗时 | 说明 |
|---|---|---|
| VAD 端点检测 | 200–500ms | 判断用户何时说完,太激进会打断半句话 |
| STT 语音识别 | 60–300ms | Deepgram Nova-3 较快 |
| LLM 生成 | 300–800ms | 流式输出,首字越快越好 |
| TTS 首包音频 | 75–200ms | Cartesia / ElevenLabs 较快 |
打断(barge-in)是必做项:用户说话时,Agent 正在念的半句 TTS 必须立刻停掉,否则两边同时响。LiveKit 的 VAD 会接管这件事——你只要打开允许打断即可,不要自己写停播逻辑。
Step 1:装好 LiveKit Agents 与插件
用一个干净的虚拟环境,避免和别的项目依赖打架。下面按"可换厂商"的经典流水线装:OpenAI 做 LLM、Deepgram 做 STT、Cartesia 做 TTS、Silero 做 VAD、并带上降噪插件。
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install "livekit-agents[openai,deepgram,cartesia,silero,noise-cancellation]"
livekit-agents[openai,realtime,silero,turn-detector,noise-cancellation],并把下面的 AgentSession 里的 llm= 换成 openai.realtime.RealtimeModel(...) 即可,其余结构不变。Step 2:准备三把密钥
LiveKit Agents 需要一个实时房间(LiveKit Cloud 或自托管 Server),再各选一家 STT / LLM / TTS 供应商。把密钥写进项目根目录的 .env:
LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=your_livekit_api_key
LIVEKIT_API_SECRET=your_livekit_api_secret
DEEPGRAM_API_KEY=your_deepgram_key
OPENAI_API_KEY=your_openai_key
CARTESIA_API_KEY=your_cartesia_key
密钥安全:.env 绝不能提交进 git。在项目里加一个 .gitignore 写 .env;任何 API Key 泄露都能被别人拿去扣费。本机调试用 python-dotenv 读取即可。
Step 3:写出最小可运行语音 Agent
新建 agent.py。核心是 AgentSession:把 STT、LLM、TTS 分别挂上去,框架自动处理 VAD、轮次和打断。VoicePipelineAgent 是经典流水线封装,allow_interruptions=True 打开打断。
import asyncio
from dotenv import load_dotenv
from livekit import agents
from livekit.agents import AgentSession, Agent
from livekit.plugins import openai, deepgram, cartesia, silero
load_dotenv()
class Assistant(Agent):
def __init__(self):
super().__init__(instructions="你是简洁友好的语音客服,每次回答不超过两句话。")
async def entrypoint(ctx: agents.JobContext):
await ctx.connect()
session = AgentSession(
vad=silero.VAD.load(),
stt=deepgram.STT(model="nova-3", language="multi"),
llm=openai.LLM(model="gpt-4.1-mini"),
tts=cartesia.TTS(),
)
await session.start(agent=Assistant(), room=ctx.room)
await session.generate_reply(instructions="向用户问好,并说明你能帮什么忙。")
if __name__ == "__main__":
agents.cli.run_app(agents.WorkerOptions(entrypoint_fnc=entrypoint))
nova-3、OpenAI 用 gpt-4.1-mini 这类小模型即可压低延迟与成本;TTS 换声音用 cartesia.TTS(voice="...")。Step 4:让 Agent 能插话(打断)
打断在 LiveKit 里是"开箱即用"的:VAD 一旦检测到用户又开始说话,会取消正在播放的 TTS、截断 Agent 上句未念完的部分,把新的用户语音路由给 STT。你只需要显式允许,并控制 VAD 灵敏度。
session = AgentSession(
vad=silero.VAD.load(min_speech_duration=0.2), # 多短算"开口"
stt=deepgram.STT(model="nova-3"),
llm=openai.LLM(model="gpt-4.1-mini"),
tts=cartesia.TTS(),
turn_detection="stt", # 用 STT 做端点检测
)
await session.start(agent=Assistant(), room=ctx.room, allow_interruptions=True)
别在 HTTP-only 环境里硬扛:LiveKit 建立在 WebRTC 房间模型上,需要实时传输。纯 HTTP 环境请走 Twilio Media Streams 或托管平台(Vapi / Retell)。电话场景用 LiveKit 的 SIP 中继接入 PSTN。
Step 5:给语音 Agent 加工具调用
语音 Agent 也能在对话中途调工具,例如查订单。用 @function_tool 装饰一个异步函数,框架会把函数注册进会话,模型按名字调用,schema 写清楚能显著降低幻觉。
from livekit.agents import function_tool
class Assistant(Agent):
@function_tool
async def lookup_order(self, order_id: str) -> str:
"""按订单号查询客户订单状态。"""
# 这里换成你真实的 CRM 查询
return f"订单 {order_id}:已发货,预计明天送达。"
Step 6:本地试跑与上线
不接 LiveKit 房间也能先验证逻辑:console 模式用麦克风本地对话;dev 模式连 LiveKit Cloud 的开发房间,打开 agents-playground 网页即可对话。
python agent.py console # 本地麦克风,无需 LiveKit 连接
python agent.py dev # 连 LiveKit Cloud 开发房间
python agent.py start # 生产 worker 模式
livekit server cli deploy 或 Docker Compose 自托管。常见问题
| 现象 | 原因与处理 |
|---|---|
| 运行报缺 API Key | 检查 .env 是否能被 load_dotenv 读到,变量名是否与插件一致 |
| 用户一开口就被打断 | VAD 太灵敏,调大 min_speech_duration 或 silence 阈值 |
| 延迟明显偏高 | 换小模型 + 流式 TTS,并优先选同区域供应商 |