写在前面:为什么我决定折腾这个

我之前做的「AI 对话」基本都停留在打字框里——左边输入框,右边聊天流,回车一发,等它吐字。直到上周我刷到一个 demo:一个人对着浏览器说「帮我把明天下午的会改到三点」,AI 当场用声音回了一句「好的,已经发出邀请」。

没有打字,没有等待转圈,就是说话,然后它说话回你,我瞬间觉得聊天框不香了。

但我对「语音 AI」的印象一直停留在两种:

  • 一种是手机里那个动不动就「我听不懂」的语音助手
  • 另一种是客服电话里那种念菜单的机器人。这俩都离「能自然对话」差得远。

所以我想搞清楚一件事:一个真能跟你聊天的语音 AI,到底是怎么搭起来的?

带着这个问题,我找到了 AgoraConversational AI(下面我就简称为 Convo AI),花了大概一个下午把它跑通。这篇文章就是我这次折腾的全程记录——包括我踩的坑、看到的真实输出,以及我对它架构的理解。如果你也从没碰过 voice agent,希望能帮你少走点弯路。
在这里插入图片描述

先回答一个最基础的问题:语音 AI 为什么不能只接个聊天模型?

这是我一开始最大的误解。我心想,这不就是把 ChatGPT 套个麦克风吗?ASR(语音转文字)+ LLM(大模型)+ TTS(文字转语音),三件套串起来不就完了?

真去做的时候才发现,这三件套「串起来」这一步才是地狱。

举几个例子。

打断怎么办? 你和 AI 对话的时候,说到一半你突然想插一句话纠正它——这在打字框里不存在,因为你打字的时候它本来就在等你。但语音里,AI 可能正在念一段长句子,你怎么让它停下来?它怎么知道你是「说完了等它回」还是「临时打断想补充」?

延迟怎么压? 你按下发送,ASR 转 200ms,LLM 想 800ms,TTS 合成 300ms,再加上网络抖动,用户体验到的就是「我说完了,空气安静了一秒半,它才开始回」。这种延迟在打字时代无所谓,在语音里就特别明显,因为人类正常对话的间隔也就两三百毫秒。超过这个阈值,你会下意识觉得「对面卡了」。

全双工怎么实现? 两个人说话可以同时开口、甚至抢话,AI 得能一边听你说话一边生成回复,而不是「你说完 → 我才开始听 → 听完了再想 → 想完了再说」这种对讲机模式。

声音怎么低延迟搬? 音频数据量大,又对实时性极敏感,普通的 HTTP 接口根本扛不住,得专门的实时传输。

所以一个能用的语音 AI,光有三件套远远不够。它还需要:一套能把音频低延迟搬来搬去的传输层;一套管「轮次检测、打断、记忆」的运行时;以及把端上体验(浏览器或 App)串起来的工程。这些拼在一起,才是一个 voice agent。

Convo AI 干的事,就是把这堆东西打包好给你。

它具体打包了什么?四层架构拆一下

跑通之后回头看,它的架构其实可以很清晰地分成四层。我用大白话翻译一下,并画个示意图:

┌──────────────────────────────────────────────────────────┐
│  ④ Endpoint  端上体验                                     |
│     浏览器 / App / 硬件设备                                |
│     (采集麦克风、播放声音、显示转写)                        │
└──────────────────────────────────────────────────────────┘
                       ▲   音频 + 事件 (RTC + RTM)
                       ▼
┌──────────────────────────────────────────────────────────┐
│  ① Real-time transport  实时传输                          │
│     Agora RTC / SD-RTN™ 全球网络                          │
│     端到端延迟官方数据 ≈ 650ms                             │
└──────────────────────────────────────────────────────────┘
                       ▲
                       ▼
┌──────────────────────────────────────────────────────────┐
│  ② Agent runtime  运行时                                  │
│     会话生命周期 / 轮次检测 / 打断 / 记忆 / 工具调用         │
└──────────────────────────────────────────────────────────┘
                       ▲
                       ▼
┌──────────────────────────────────────────────────────────┐
│  ③ Models  AI 模型                                        │
│     ASR (Deepgram)  +  LLM (OpenAI)  +  TTS (MiniMax)    │
│     —— 都可换                                             │
└──────────────────────────────────────────────────────────┘

第一层:实时传输(Real-time transport) 负责把你的声音低延迟地送到 AI 那边,再把 AI 合成的声音送回来。Agora 的老本行就是 RTC(实时音视频通信),全球有自建的 SD-RTN 网络,端到端延迟官方数据是 650ms。这一层是 Agora 比别家更有底气的地方。

第二层:Agent 运行时(Agent runtime) 这一层是「大脑的总调度」。它管会话生命周期、管轮次检测(turn detection,判断你这话说完没有)、管打断(你说着说着插话怎么办)、管记忆和工具调用。这层的东西自己从零写,至少几个月。

第三层:AI 模型(Models) 就是前面说的三件套——ASR、LLM、TTS。Convo AI 默认用的是 Deepgram 做 ASR、OpenAI 做 LLM、MiniMax 做 TTS,但你也可以换成自己喜欢的,甚至换成自己托管的开源模型。这点对我挺重要的——我不想被绑死在某一家上。

第四层:端上体验(Endpoint) 最终用户在哪用它?浏览器、App、还是硬件设备。Convo AI 把这条路径也分了两条:in apps(Web/移动端/桌面)和 on dedicated devices(玩具、可穿戴、自助终端这类嵌入式硬件)。我这次走的是 in apps 里的 Web 路径。

理解了这四层,后面看代码就不会迷路。

开干:从零到能开口说话

准备工作

需要的东西不多:

  • 一个 Agora 账号(去 console.agora.io 注册,免费额度够你玩很久)
  • 本机装好 Node.js(我用的是 24.x)和 Python 3.14+
  • 包管理器 bun(官方模板默认用它,没有的话 npm i -g bun 装一下)
    在这里插入图片描述

重点:默认 managed 模式不需要你自备任何模型 key——不用 OpenAI、不用 Deepgram、不用 MiniMax 的 API key。这三个由 Agora 用自己的凭据帮你调,你只消耗 Agora 的额度。这是它对我这种懒人最友好的地方。

唯一需要手动做的一步:注册完账号后,去 Agora Console 里开启 Conversational AI Engine 这个能力开关(路径:Project → 编辑 → Conversational AI)。不开的话后面 agent 起不来。
在这里插入图片描述

我选的是 Python Quickstart 这条路。原因很简单:后端是 FastAPI,看起来最「正常」,方便我后面想魔改;前端是 Next.js,浏览器打开就能聊,最直观。

整个项目的目录结构跑通后大概长这样:

my-python-demo/
├── server/                   # FastAPI 后端
│   ├── src/
│   │   ├── server.py         # 三条 API 路由 + token 签发
│   │   └── agent.py          # Agent 配置:prompt / 模型 / VAD
│   ├── .env.example          # 环境变量模板
│   └── requirements.txt
└── web/                      # Next.js 前端
    ├── src/
    │   ├── components/
    │   │   ├── LandingPage.tsx          # 进房前的页面
    │   │   └── ConversationComponent.tsx # 通话 + 转写 + 指标
    │   ├── lib/conversation.ts
    │   └── services/api.ts              # 调后端 /api/*
    ├── next.config.ts                   # 把 /api/* rewrite 到 FastAPI
    └── package.json

记两个关键文件:server/src/agent.py(决定 AI 的人格和能力)和 server/src/server.py(决定前后端怎么握手),后面想改东西基本就是改这俩。

第一步:装 Agora CLI

Agora 现在把上手流程收拢到了一个 CLI 工具里,比以前手动 clone + 改 .env 友好太多。

macOS / Linux:

curl -fsSL https://dl.agora.io/cli/install.sh | sh
agora --help

Windows(PowerShell,我用的就是这台):

irm https://dl.agora.io/cli/install.ps1 | iex
agora --help

跑通后能看到一长串子命令列表(login / init / project doctor / …)。

我的小坑: PowerShell 默认执行策略会拦这个 inline 脚本。如果报错,把脚本下下来本地跑:

powershell -ExecutionPolicy Bypass -File .\install.ps1

另外装完如果 agora 命令找不到,重跑安装脚本时加 --add-to-path,或者手动把安装目录塞进 PATH。

在这里插入图片描述

第二步:登录 + 拉项目

agora login

会自动打开浏览器走 OAuth,授权完回到终端,看到一句 Logged in as ...
在这里插入图片描述

然后一行命令把官方模板拉下来:

agora init my-python-demo --template python
cd my-python-demo
bun run setup
bun run dev

这里 agora init 帮你做了三件事,这才是它真正省事的地方

  1. clone 官方 starter 仓库
  2. 把项目绑定到你在 Agora Console 里的项目
  3. 自动写好 .env——App ID、App Certificate 这些密钥全自动填进去

在这里插入图片描述

你不用手动去 console 复制粘贴密钥。之前我最烦的就是这一步,现在一条命令搞定。

对应的 .env 内容(敏感值我打码了):

# server/.env —— 由 agora init 自动生成
AGORA_APP_ID=cd0xxxxxxxxxxxxxxxxxxxxxxxx
AGORA_APP_CERTIFICATE=1d8xxxxxxxxxxxxxxxxxxxxxxxxxxxx
AGENT_GREETING=Hi there! I'm Ada, your virtual assistant from Agora. How can I help?
PORT=8000

如果你想换成中文问候,改 AGENT_GREETING 就行,不用动代码。

第三步:浏览器里开聊

bun run dev 会同时拉起 FastAPI 后端(默认 8000)和 Next.js 前端(3000)。终端会刷出两段日志:

[backend] Uvicorn running on http://0.0.0.0:8000
[web]      ▲ Next.js 14.x  Local: http://localhost:3000

在这里插入图片描述

打开 http://localhost:3000,页面长这样:
在这里插入图片描述
Start conversation,浏览器问你要麦克风权限,给。然后你会看到:

  1. 页面右下角出现一个连接状态指示,从 connecting 变成 connected
  2. 实时转写区开始动——你说话,文字就跟着冒出来
  3. AI 那一栏也开始出字,是它正在念的内容

我第一次开口说的是「你好,你能听懂中文吗」。它停顿了大概半秒,然后用中文回了我一句「能听懂,你想聊点什么」。

就那一刻,真的会激动。 你写了一晚上代码,第一次听到 AI 用声音回应你,跟在网页上点一下发送按钮的感觉完全不一样。

我把刚才那段对话的转写原样贴出来:

[我]   你好,你能听懂中文吗?
[AI]   你好!我可以理解中文。请问有什么我可以帮助你的吗?
[我]   给我讲一个关于程序员的冷笑话。
[AI]   当然!有一个冷笑话是这样的:为什么程序员总是混淆圣诞节和万圣节?因为 Oct 31 = Dec 25!这是一种编程语言中的进制转换幽默。希望你喜欢!
[我]   (笑)再来一个。
[AI]   好的!这个是:为什么程序员喜欢自然?因为那里没有“bug”!希望这个也能让你笑!

在这里插入图片描述

万一没跑通

官方给了一个诊断命令,特别有用:

agora project doctor --deep

它会检查你的凭据是否有效、Convo AI 功能有没有在 console 里开启、网络是不是通。我中途遇到一次 agent 死活不加入频道的问题,跑了一下 doctor,输出大致是这样:

✗ Conversational AI capability not enabled on project <xxx>
  → Fix: open https://console.agora.io/ → Project → Features → enable Conversational AI
✓ Credentials valid
✓ Network reachable

在这里插入图片描述

照着提示去 console 勾上 Conversational AI 这个 capability,再跑就好了。

前后端到底在握手什么?三个 API 搞清楚

跑通之后我去翻了 server.py,发现整个交互其实就靠三条 HTTP 路由。把它画出来,整个流程就清楚了:
在这里插入图片描述

三个路由的契约(这是我从官方 Recipe 文档里抄来的稳定接口,不会随便变):

路由 入参 返回
GET /api/get_config ?channel=&uid= data.app_id / data.token / data.uid / data.channel_name / data.agent_uid
POST /api/startAgent { channelName, rtcUid, userUid, parameters? } data.agent_id / data.channel_name / data.status
POST /api/stopAgent { agentId } { code: 0, msg: “success” }

成功响应统一是 { code, msg, data } 这种结构。

一句话总结这个流程:浏览器先要 token,再用 token + 一条 startAgent 让后端去云端把 agent 拉起来,之后真正的音频流和事件流就走 RTC/RTM 通道,不再走 HTTP 了。

浏览器 Console 里能看到什么?RTM 事件流

这一段是我跑通之后觉得最有「窥探内部」快感的部分。

agent 跑起来后,打开浏览器 DevTools 的 Console,会发现 Convo AI 通过 RTM(Agora 的实时消息通道)源源不断地往前端推事件。你能看到的几类:

// 状态变化:agent 进场、开始听、开始说
{ type: "state", state: "listening" }
{ type: "state", state: "speaking" }

// 实时转写:分两种,你说的 vs agent 说的
{ type: "transcript", uid: <user>, text: "给我讲一个冷笑话", is_final: true }
{ type: "transcript", uid: <agent>, text: "为什么程序员...", is_final: false }

// 延迟指标:这是我最想看的
{ type: "metrics", ttft: 680, e2e_latency: 920, ... }

// 错误
{ type: "error", code: "...", message: "..." }

在这里插入图片描述

ttft 是 Time To First Token(首字延迟),e2e_latency 是端到端延迟。盯着这两个数字调优,比凭感觉靠谱多了。官方 Recipe 里有个 Event Observability 例子,就是把这些事件渲染成一个时间轴网页,调试时特别香。

我特意去验证的几件事

跑通只是第一步,我更想搞清楚它到底好不好用。所以特意测了几个场景。

  1. 延迟到底多少?

我在 Console 里盯 metrics 事件,看到 ttft 大概在 600~800ms 之间,e2e_latency 在 800~1000ms。考虑到我在中国、走的是默认海外节点,这个数字已经比我预期好。文档里说的 650ms 是节点近的情况下能到的,如果我把部署换到国内或周边节点,应该还能再压。

  1. 打断好不好使?

这是我最关心的。我让它念一段长一点的内容(让它给我讲讲量子计算),然后故意在它念到一半时喊「停,换一个话题」。

结果是:它确实停了。不是念完那句才停,是大概 200ms 内就停了,然后听我后面的话。Console 里能对应看到一条 state: listening 紧跟着事件流。

这就是文档里说的 VAD-based interruption handling——它一直在听,检测到你开口就立刻静音自己。这点对体验影响巨大。一个不会被打断的 AI,不管多聪明,都没法当人用。

  1. 轮次检测会不会瞎打断?

反过来我也担心一种情况:我说话稍微停顿了一下(比如「我想问一下……那个……」),它会不会以为我说完了就抢话。

试了几次,没抢。它默认的 turn detection 是基于语义的(semantic turn detection),不是单纯的静音检测,所以能区分「真说完了」和「在思考」。这一点比我预想的好。

  1. 能换模型吗?

这个我没真改代码,但去翻了 agent.py。managed 模式下的配置大概长这样(简化版,注意没有任何 api_key 参数):

# server/src/agent.py  (节选,managed 模式)
from agora_agent import (
    Agent, Agora, Area, DeepgramSTT, OpenAI, MiniMaxTTS,
)

# managed 模式:Agora 出凭据,你不出 key
agent = (
    Agent(name="my-managed-agent")
    .with_stt(DeepgramSTT(model="nova-3", language="en-US"))
    .with_llm(OpenAI(
        model="gpt-4o-mini",
        system_messages=[{"role": "system",
                          "content": "You are a helpful assistant."}],
        greeting_message="Hello! How can I help you today?",
        max_history=32,
    ))
    .with_tts(MiniMaxTTS(
        model="speech_2_6_turbo",
        voice_id="English_captivating_female1",
    ))
)

想换模型基本就是改这三行:把 OpenAI(...) 换成你的自托管 endpoint(OpenAI 兼容协议 + 加自己的 api_key,也就是切到 BYOK 模式),或者把 TTS 换成 ElevenLabs、Cartesia 之类。官方 Recipe 里 recipe-agent-custom-llmrecipe-agent-custom-llm-tts 就是干这个的,照着抄就行。

不绑死任何一家这件事,Agora 做得到位。

一些说人话的评价

折腾完一个下午,我对它的总体感觉是:

值得称赞地方:

  • 上手是真的简单。CLI 一条龙,不需要自己去翻文档找 App ID 怎么填。
  • 默认链路(Deepgram + OpenAI + MiniMax)开箱即用,先跑通再优化。
  • 打断和轮次检测这两件事默认就调得不错,不用自己魔改。
  • RTM 事件把延迟指标、转写、状态都暴露出来,调优和排障有据可查,不是黑盒。
  • 模型可换,不绑架你。这点对长期项目很关键。
  • Convo AI 国内和海外都支持,默认走海外,初始化时把地区选成 area.cn 就会整体切到国内的模型和节点,延迟和稳定性有保证;底层是 Agora 在全球(含国内)都有自己的 RTC 网络,LiveKit 在亚洲没节点,用户在国内延迟会很高。
  • 文档对完全没接触过 RTC 的人比较友好,(比如:初学者可能看不懂 token、UID、channel 这些 RTC 概念),它会有专门的前置说明与关系解释;并以用户行动路径为分类视角,进行一步一步深入实践。
  • RTC 传输是 Agora 老本行,全球低延迟这块它确实有底气。一个旁证:2024 年 10 月 OpenAI 把 Agora 选为 Realtime API 的官方合作伙伴,不是没原因的——据说 GPT-4o 发布时演示用的 websockets 方案网络稳定性都成问题,所以后来选了个 RTC 出身的来补这一刀。

待改进的地方:

  • 地区这个开关不够显眼,我一开始没注意到,默认按海外链路就跑起来了,还以为国内就是这个延迟,建议 Quickstart 里写明显一点。
  • 默认 TTS 的中文音色可选项不算多,要更自然的中文声音可能得自己换。

总的来说,如果你想做的是「能自然对话的语音 AI」,又不想从零写传输、轮次、打断这些底层逻辑,Convo AI 确实能帮你省掉几个月。它不是「替代」谁,而是把那些本来该有人帮你打包好的工程问题打包好了。

附:我跑通用到的全部命令

# Windows PowerShell 装 CLI(macOS/Linux 换成 curl 那条)
irm https://dl.agora.io/cli/install.ps1 | iex

# 登录
agora login

# 拉官方 Python 模板(自动写好 .env)
agora init my-python-demo --template python
cd my-python-demo

# 装依赖并起服务(同时拉起 FastAPI + Next.js)
bun run setup
bun run dev

# 浏览器打开 http://localhost:3000,点 Start conversation

# 出问题就跑这个诊断
agora project doctor --deep

参考链接:

  • Recipes 目录(29 个可运行示例):https://docs.agora.io/en/api-reference/recipes
  • Voice Agent 总览:https://docs.agora.io/en/ai
  • Quickstart:https://docs.agora.io/en/ai/get-started/quickstart
  • Python Quickstart 源码:https://github.com/AgoraIO-Conversational-AI/agent-quickstart-python
  • 对话式 AI 科普(社区):https://www.rtecommunity.dev/conversational-ai-for-the-curious/

如果你也想试试搭一个能开口说话的 AI,我的建议是:别先看架构图,先把官方 Quickstart 跑通,听到 AI 第一次回你话的那个瞬间,你就会明白为什么这事儿值得折腾。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐