Skip to main content
近半年主线是一套 端侧语音 Agent 智控平台:网页里运营设备与智能体,设备侧跑实时语音对话,两边靠配置契约连成闭环。功能已基本打通,进入上线阶段。 案例已脱敏——不写公司名、产品品牌和客户细节;写的是系统怎么拆、一次对话怎么走、以及几处真正难的地方。

先看这一天在干什么

可以把系统想成两条线,同时转: 运营线(人在电脑前)
登录智控台 → 管理设备与绑定 → 给智能体选模型、音色、插件和知识库 → 配团队权限 → 配置下发到对应设备。业务接口还能按区域切换,账号体系相对固定。
会话线(人在设备前)
设备连上语音服务 → 按「这台设备」的配置装配能力 → 用户说话 → 系统听清、思考、必要时查知识或调工具 → 把话播出来 → 用户打断时,上一轮声音必须立刻停干净。
若两条线各干各的:现场只能改本地文件;助手停在单轮闲聊;多团队时数据边界含糊。这半年做的事,就是把它们收成一条能运营、能降级的闭环。

一次对话怎么走完

下面按时间顺序走一遍(经典语音路径)。括号里是人话解释。
  1. 建连
    设备通过 WebSocket 连上语音服务,一带上设备身份。一设备一连接,会话状态挂在这条连接上。
  2. 拉配置
    若走智控台模式:先拿基座配置,再按设备拉「这一台」的智能体、模型、插件等差异项。模块没就绪前,不急着处理用户语音,避免半初始化乱答。本地开发也可以不连智控台,用本地配置跑通。
  3. 听(VAD)
    从连续音频里判断「用户是不是在说话、说完没有」。这是后面一切的门闩。
  4. 识(ASR)
    把语音打成文字。本地识别与云端识别在资源占用上不一样:有的可以多连接共享,有的必须每连接隔离。
  5. 想 / 办事(LLM + 工具)
    模型根据上下文决定直接回答,还是先调工具(查知识、设备能力、外部 MCP 等)。工具不是散落在代码各处的 if,而是收成统一目录再分发。
  6. 说(TTS)
    文字合成语音流式回传。理想情况是模型还没说完整段,设备已经开始播,体感才不像卡死。
  7. 打断
    用户说「停」或重新说话时:停止采集只是第一步;还在飞的生成、播报、字幕必须标成「过期」丢掉,否则会出现幽灵播报——旧句子冷不丁冒出来。长耗时工具也要有开始/结束状态,打断时把界面收干净。
另有一条 端到端语音路径(不经经典 ASR→LLM→TTS 级联)。同一连接里两条主路径只能活一条,否则会抢音频和状态。默认仍保证经典路径可运行,再扩端到端。

系统怎么拆


三层模块地图

我覆盖全链路,下面按层列能力——这是这半年「面」上做了什么。

智控台前端

  • 设备、智能体、模型、知识库、音色/克隆等管理界面
  • 路由与按钮级权限(和后端权限字符串对齐)
  • 团队上下文由具体业务请求显式带上,而不是全局偷偷注入(写错团队的代价很高)
  • 账号域相对固定;业务 API 可按数据中心/区域切换

智控台后端

  • 设备绑定与生命周期、智能体与模型配置、知识库运营入口
  • 系统功能权限(菜单/角色)与 团队数据权限(资源归属)分开建模
  • 读操作可在授权团队范围内聚合;写操作必须有明确团队上下文
  • 关键查询侧带团队过滤,不只靠前端藏按钮
  • 知识库通过适配器对接外部检索/向量引擎,业务层不绑死一家
  • 给设备侧的配置接口用服务身份保护,和运营人员的登录会话分离;基座配置可缓存

设备侧语音服务

  • 连接生命周期:握手、后台初始化、绑定/未绑定分支
  • 按配置装配 VAD/ASR/LLM/TTS/记忆/意图等可替换模块
  • 文本消息按类型路由(hello、打断、监听、IoT、MCP、视觉等),避免全堆在连接主逻辑里
  • 统一工具调度:服务端插件、服务端/设备 MCP、设备 IoT 等
  • 会话内按需检索知识(短超时,失败要说人话)
  • 日志按模块打标,并带设备/会话上下文;配置日志脱敏

三个深挖点

1. 配置:既要统一运营,又要能本地调试

最早如果只认本地文件,运维根本管不住现场;如果一切必须走云端,联调又慢得难受。后来定成:
  • 有控制面地址 → 以云端基座为主,建连后再拉「这一台设备」的差异配置
  • 默认可提交的结构 vs 密钥/现场覆盖分开,密钥不进默认模板
  • 留少量本地可覆盖项,方便排障或灰度换模块,但优先级写清楚
  • 字段名两边必须同一套;改契约就当改接口,双边一起动
联调里踩过最冤的,是同一含义两边各起一个字段名——改半天发现设备根本没读到新值。现在更在意契约纪律,而不是「再加一个开关」。 更深一层见 配置与控制面。

2. 会话:双路径互斥,打断必须「死干净」

语音产品里,用户感知几乎等于「我说完有没有声音、我说停停不停」。
  • 双路径:经典级联和端到端不要并行抢同一路音频;入口就互斥
  • 打断:用轮次标记作废过期的生成/播报/字幕;只停麦不够
  • 别堵事件循环:阻塞初始化、重计算丢线程池;记忆预热之类不挡首轮
  • 扩展往外挂:新协议、新工具走独立处理与可替换模块,连接核心保持瘦
幽灵播报这类 bug 复现不稳定,没有「这一通会话装了哪套模块、卡在哪一段」的日志,线上只能重启。可观测性在这里不是加分项,是排障前提。 更深一层见 会话与打断。

3. 权限与工具:能进后台 ≠ 能看全部;能说话 ≠ 能办事

多团队共用控制台时,只做登录和菜单,列表接口仍可能扫到不该看的数据。所以:
  • 系统层管「能不能进功能」
  • 团队层管「碰得到哪些资源」;写必须带团队上下文
  • 查询侧强制范围;前端团队头显式传递
工具侧则是另一件事:来源一多(插件、MCP、设备能力),若各写各的,模型一失败就容易空转重试。做法是统一目录分发,短超时与可理解错误,长任务有开始/结束,打断时收尾。知识检索也按「会话内工具」挂上,而不是写死在语音主循环里——控制面管知识运营,对话里按需查。

坏了的时候长什么样

上线前更在意失败形态,而不是只演示 Happy Path。 更多短复盘见 经验总结。

技术栈


相关阅读

配置与控制面

双模式、按设备配置、契约与鉴权分层。

会话与打断

走读加深、双路径、轮次作废与线程边界。

经验总结

跨主题短复盘。

项目概览

项目区入口。