# 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. 已知问题与优化方向 1. **天气和订单工具为 Mock**:queryWeather 和 queryOrder 使用硬编码数据,可接入真实 API 2. **本地知识库简陋**:searchLocalKnowledge 仅 5 条硬编码记录,需接入真实知识库 3. **方舟 LLM Mock 模式**:未配置 VOLC_ARK_ENDPOINT_ID 时返回硬编码回复 4. **文字对话依赖 Coze**:Coze 未配置时文字对话模式不可用,可考虑 fallback 到 arkChatService 5. **知识库冷启动**:方舟 KB 首次查询较慢(~10s),后续查询 ~3-5s