16 KiB
16 KiB
BigWo 智能语音对话系统 — 系统架构文档
版本:2.0 | 更新日期:2026-03-13
1. 系统概述
BigWo 是一个企业级智能客服对话系统,支持语音通话和文字对话两种交互模式,可无缝切换且保持上下文连续。
核心能力
| 能力 | 说明 |
|---|---|
| 实时语音对话 | Native WebSocket + S2S 端到端语音大模型,混合编排模式 |
| 知识库问答 | Function Calling → 方舟私域知识库 → 本地知识库 |
| 文字对话 | Coze v3 Chat API,支持 SSE 流式输出 |
| 语音↔文字切换 | 同一 sessionId 贯穿,MySQL 持久化完整历史 |
| 工具调用 | 知识库检索、天气、订单、时间、计算 |
技术栈
- 前端:React 18 + Vite 5 + TailwindCSS 4 + Lucide Icons
- 后端:Node.js + Express 4 (port 3012)
- 语音:Native WebSocket (
wss://openspeech.bytedance.com/api/v3/realtime/dialogue) + S2S 端到端 + 方舟 LLM - 文字:Coze v3 Chat API(流式 SSE)
- 知识库:方舟 Chat Completions API + knowledge_base metadata
- 数据库:MySQL 8 (mysql2/promise)
- 部署:PM2 (cluster) + Nginx 反向代理 + 宝塔面板
2. 系统架构图
┌───────────────────────────────────────────────────────────┐
│ 浏览器客户端 │
│ ┌────────────┐ ┌───────────┐ ┌────────────────────┐ │
│ │ VoicePanel │ │ ChatPanel │ │SessionHistoryPanel │ │
│ └─────┬──────┘ └─────┬─────┘ └────────────────────┘ │
│ │ │ │
│ ┌─────▼──────────┐ ┌──▼───────┐ ┌────────────────┐ │
│ │useNativeVoice │ │ chatApi │ │ voiceApi │ │
│ │ Chat (Hook) │ │(HTTP/SSE)│ │ (HTTP 封装) │ │
│ └─────┬──────────┘ └──┬───────┘ └────────────────┘ │
│ │ │ │
│ ┌─────▼──────────────┐ │ │
│ │nativeVoiceService │ │ │
│ │ (WebSocket+Audio) │ │ │
│ └─────┬──────────────┘ │ │
└────────┼────────────────┼─────────────────────────────────┘
│ WebSocket │ HTTPS
│ PCM 音频流 │ REST/SSE
▼ ▼
┌──────────────────────────────────────────────────┐
│ Express 后端 (port 3001) │
│ │
│ /ws/realtime-dialog — Native 语音网关 (核心) │
│ routes/voice.js — 语音配置、直连会话 │
│ routes/chat.js — 文字对话 (Coze SSE) │
│ routes/session.js — 会话列表、历史、删除 │
│ │
│ services/nativeVoiceGateway.js — WebSocket 网关 │
│ services/realtimeDialogProtocol.js — 二进制协议 │
│ services/realtimeDialogRouting.js — 意图路由 │
│ services/toolExecutor.js — 工具执行器 │
│ services/arkChatService.js — 方舟 LLM │
│ services/cozeChatService.js — Coze Chat │
│ db/index.js — MySQL CRUD │
│ │
└──────┬───────────────┬────────────────────────────┘
│ │
│ WebSocket │
▼ ▼
┌───────────────┐ ┌─────────────────┐ ┌──────────────┐
│ 火山 Realtime │ │ MySQL 8 │ │ 方舟知识库 │
│ Dialog 服务 │ │ sessions 表 │ │ (远程 API) │
│ (S2S + LLM) │ │ messages 表 │ └──────────────┘
└───────────────┘ └─────────────────┘
3. 目录结构
test2/
├── client/ # 前端(React + Vite)
│ ├── src/
│ │ ├── App.jsx # 主应用,模式切换 + 会话管理
│ │ ├── components/
│ │ │ ├── VoicePanel.jsx # 语音通话界面
│ │ │ ├── ChatPanel.jsx # 文字对话界面(SSE 流式)
│ │ │ ├── SessionHistoryPanel.jsx # 会话历史侧边栏
│ │ │ ├── SettingsPanel.jsx # 语音参数设置面板
│ │ │ └── SubtitleDisplay.jsx# 实时字幕展示
│ │ ├── hooks/
│ │ │ └── useNativeVoiceChat.js # Native WebSocket 语音 Hook
│ │ └── services/
│ │ ├── nativeVoiceService.js # WebSocket 语音服务(音频采集/播放)
│ │ ├── voiceApi.js # 语音/会话 HTTP 请求
│ │ └── chatApi.js # 文字 HTTP/SSE 请求
│ └── vite.config.js
├── server/ # 后端(Express)
│ ├── app.js # 入口,启动 HTTP + WebSocket 服务
│ ├── routes/
│ │ ├── voice.js # 语音配置、直连会话、知识库查询
│ │ ├── chat.js # 文字对话(Coze SSE 流式)
│ │ └── session.js # 会话列表、历史、删除、模式切换
│ ├── services/
│ │ ├── nativeVoiceGateway.js # WebSocket 语音网关(核心)
│ │ ├── realtimeDialogProtocol.js # 二进制协议编解码
│ │ ├── realtimeDialogRouting.js # 意图路由 + 工具调度
│ │ ├── toolExecutor.js # 工具执行器
│ │ ├── arkChatService.js # 方舟 LLM
│ │ └── cozeChatService.js # Coze Chat API(文字主服务)
│ ├── db/index.js # MySQL CRUD
│ └── .env # 环境变量
└── ecosystem.config.js # PM2 部署配置
4. 语音通话模块(Native WebSocket 方案)
4.1 混合编排模式
S2S 端到端模型处理普通闲聊(低延迟),方舟 LLM 同时决策是否需要调用工具。两者并行运行。
4.2 会话生命周期
客户端 WebSocket 连接 → /ws/realtime-dialog
↓
nativeVoiceGateway 创建会话 → 连接上游 Realtime Dialog 服务
↓
客户端采集麦克风 PCM → 发送音频帧 → 上游 ASR + S2S
↓
上游返回字幕/音频 → realtimeDialogRouting 意图路由
↓
工具调用或闲聊回复 → ChatTTSText 注入语音流 → 客户端播放
↓
客户端断开 WebSocket → 会话结束 → 可切换文字模式
4.3 语音相关端点
| 端点 | 类型 | 说明 |
|---|---|---|
/ws/realtime-dialog |
WebSocket | 核心,Native 语音网关 |
/api/voice/config |
GET | 获取模型、音色列表 |
/api/voice/direct/session |
POST | 创建直连会话 |
/api/voice/direct/message |
POST | 添加消息 |
/api/voice/direct/query |
POST | 知识库直接查询 |
/api/voice/stop |
POST | 停止会话 |
4.4 核心服务文件
| 文件 | 职责 |
|---|---|
nativeVoiceGateway.js |
WebSocket 网关,管理客户端↔上游连接、音频流转发、消息持久化 |
realtimeDialogProtocol.js |
二进制协议编解码(消息类型、标志位、序列化/反序列化) |
realtimeDialogRouting.js |
意图路由(规则+LLM 双层决策)、工具调度、语音播报 |
5. 语音意图路由与工具调用
5.1 数据流
用户语音 ASR 识别文本
│ 上游 Realtime Dialog 服务返回
▼
nativeVoiceGateway 接收字幕 → 持久化用户语音到 DB
▼
realtimeDialogRouting.resolveReply()
│
├─ 规则路由:时间/天气/订单/计算 → 直接工具调用
├─ search_knowledge → 方舟知识库 API
└─ chat → 方舟 LLM 闲聊回复
│
▼
工具结果/LLM回复 → ChatTTSText 注入上游语音流
▼
AI 语音播报 + 持久化到 DB
5.2 关键设计
| 问题 | 解决方案 |
|---|---|
| 意图识别 | 规则路由 + LLM 路由双层决策 |
| S2S 与工具冲突 | ChatTTSText 注入工具结果覆盖 S2S 直连回复 |
| 音频编解码 | realtimeDialogProtocol 自定义二进制协议 |
| 语音文本分段 | 按标点切分,估算播报时长,分段 TTS |
6. 文字对话模块
6.1 架构
通过 Coze v3 Chat API 实现,Coze Bot 内置知识库插件。
用户输入 → POST /api/chat/send-stream
↓
cozeChatService.chatStream()
│ 首次对话注入语音历史作为上下文
│ Coze 自动管理 conversation_id
↓
SSE 流式返回 → 前端逐字展示
6.2 文字 API 端点(chat.js)
| 端点 | 方法 | 说明 |
|---|---|---|
/api/chat/start |
POST | 创建会话,注入语音历史上下文 |
/api/chat/send |
POST | 非流式发送 |
/api/chat/send-stream |
POST | SSE 流式发送 |
/api/chat/history/:id |
GET | 获取会话状态 |
/api/chat/:id |
DELETE | 删除会话 |
7. 会话管理与模式切换
7.1 统一 sessionId
同一个 sessionId 贯穿语音和文字模式,所有消息持久化到 MySQL messages 表。
7.2 消息来源标记
| source 值 | 说明 |
|---|---|
voice_asr |
语音 ASR 识别的用户文本 |
voice_bot |
AI 语音回复字幕 |
voice_tool |
语音场景工具调用结果 |
chat_user |
文字对话用户输入 |
chat_bot |
文字对话 AI 回复 |
7.3 会话管理 API(session.js)
| 端点 | 方法 | 说明 |
|---|---|---|
/api/session/list |
GET | 获取会话列表(带最后消息预览) |
/api/session/:id/history |
GET | 获取完整历史(支持 llm/full 格式) |
/api/session/:id/switch |
POST | 切换模式,返回上下文历史 |
/api/session/:id |
DELETE | 删除会话及其消息 |
7.4 数据库表
sessions:id(PK), user_id, mode(voice/chat), created_at, updated_at
messages:id(AI PK), session_id, role(user/assistant/tool/system), content, source, tool_name, created_at
8. 客户端组件
8.1 组件树
App.jsx # 模式切换 + 全局设置 + 会话管理
├── VoicePanel.jsx # 语音通话 UI(开始/结束/静音/时长)
│ └── SubtitleDisplay # 实时字幕(definite/interim 区分)
├── ChatPanel.jsx # 文字对话 UI(消息列表 + SSE 流式显示)
├── SessionHistoryPanel.jsx # 会话历史侧边栏(新建/切换/删除会话)
└── SettingsPanel.jsx # 设置面板(模型/音色/系统角色/VAD)
8.2 useNativeVoiceChat Hook
管理 Native WebSocket 语音通话完整生命周期:
- start(options):连接 WebSocket → 采集麦克风 PCM → 发送音频帧
- stop():断开 WebSocket → 返回字幕和 sessionId
- toggleMute():静音/取消静音
- 状态:isActive, isMuted, isConnecting, subtitles, duration, error
8.3 nativeVoiceService.js
封装 Native WebSocket 语音连接:
- connect(options):建立 WebSocket 连接,初始化音频采集(getUserMedia + Web Audio API 降采样)
- disconnect():关闭连接、停止音频
- setMuted(muted):控制麦克风
- 事件回调:onSubtitle(字幕)、onConnectionStateChange(连接状态)、onError(错误)
- 音频播放:接收 PCM 音频帧,通过 Web Audio API 播放
9. 环境变量
必需
| 变量 | 说明 |
|---|---|
VOLC_S2S_APP_ID |
S2S 端到端语音 AppID |
VOLC_S2S_TOKEN |
S2S Token |
VOLC_ARK_ENDPOINT_ID |
方舟 LLM 推理接入点 ID |
可选
| 变量 | 说明 |
|---|---|
COZE_API_TOKEN |
Coze 智能体 Token(文字对话) |
COZE_BOT_ID |
Coze Bot ID |
VOLC_ARK_KNOWLEDGE_BASE_IDS |
方舟私域知识库数据集 ID(逗号分隔) |
VOLC_ARK_API_KEY |
方舟 API Key |
VOLC_WEBSEARCH_API_KEY |
联网搜索 Key |
VOLC_S2S_SPEAKER_ID |
自定义音色 ID |
ENABLE_NATIVE_VOICE_GATEWAY |
语音网关开关(默认开启,设 false 关闭) |
MYSQL_HOST/PORT/USER/PASSWORD/DATABASE |
MySQL 配置 |
10. 部署架构
互联网用户
│
▼ HTTPS (443) + WSS
┌──────────────┐
│ Nginx │ ← 宝塔面板管理
│ (反向代理) │
│ SSL 终止 │
└──────┬───────┘
│ http://localhost:3001
▼
┌──────────────┐
│ PM2 │ ← ecosystem.config.js
│ bigwo-server│
│ (Node.js) │
└──────┬───────┘
│
├── MySQL 8 (localhost:3306)
├── 火山 Realtime Dialog (wss://openspeech.bytedance.com)
├── 方舟 LLM API (ark.cn-beijing.volces.com)
└── Coze API (api.coze.cn)
PM2 配置
- 进程名:
bigwo-server - 工作目录:
/www/wwwroot/demo.tensorgrove.com.cn/server - 日志路径:
/var/log/bigwo/server-out.log、server-error.log - 内存限制:512M 自动重启
11. 工具定义(tools.js)
系统定义了 5 个 Function Calling 工具:
| 工具 | 参数 | 说明 |
|---|---|---|
search_knowledge |
query: string | 核心工具,强制优先调用 |
query_weather |
city: string | 天气查询(Mock) |
query_order |
order_id: string | 订单查询(Mock) |
get_current_time |
无 | 当前时间 |
calculate |
expression: string | 数学计算 |
search_knowledge 查询链
方舟私域知识库 (30s 超时)
│ POST https://ark.cn-beijing.volces.com/api/v3/chat/completions
│ metadata.knowledge_base: { dataset_ids, top_k: 3, threshold: 0.5 }
│
│ 失败 ↓
▼
本地知识库 (即时,关键词匹配)
│ 覆盖:退货、退款、配送、保修、会员
12. 安全与限制
- API 签名:所有火山引擎 API 调用使用 AK/SK HMAC 签名
- FC 回调签名:ServerSignature 校验(当前信任模式)
- 计算工具防注入:仅允许
0-9 + - * / ( ) . %字符 - CORS:已开启(
cors()中间件) - Body 限制:1MB
- 会话过期:文字对话 30 分钟自动清理
- 环境变量:敏感信息存于
.env,启动时校验
13. 已知问题与优化方向
- 天气和订单工具为 Mock:queryWeather 和 queryOrder 使用硬编码数据,可接入真实 API
- 本地知识库简陋:searchLocalKnowledge 仅 5 条硬编码记录,需接入真实知识库
- 方舟 LLM Mock 模式:未配置 VOLC_ARK_ENDPOINT_ID 时返回硬编码回复
- 文字对话依赖 Coze:Coze 未配置时文字对话模式不可用,可考虑 fallback 到 arkChatService
- 知识库冷启动:方舟 KB 首次查询较慢(~10s),后续查询 ~3-5s