Files
bigwo/test2/ARCHITECTURE.md

400 lines
16 KiB
Markdown
Raw Permalink Normal View History

2026-03-12 12:47:56 +08:00
# BigWo 智能语音对话系统 — 系统架构文档
> 版本2.0 | 更新日期2026-03-13
2026-03-12 12:47:56 +08:00
---
## 1. 系统概述
BigWo 是一个**企业级智能客服对话系统**,支持**语音通话**和**文字对话**两种交互模式,可无缝切换且保持上下文连续。
### 核心能力
| 能力 | 说明 |
|------|------|
| 实时语音对话 | Native WebSocket + S2S 端到端语音大模型,混合编排模式 |
2026-03-12 12:47:56 +08:00
| 知识库问答 | 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
2026-03-12 12:47:56 +08:00
- **文字**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 表 │ └──────────────┘
└───────────────┘ └─────────────────┘
2026-03-12 12:47:56 +08:00
```
---
## 3. 目录结构
```
test2/
├── client/ # 前端React + Vite
│ ├── src/
│ │ ├── App.jsx # 主应用,模式切换 + 会话管理
2026-03-12 12:47:56 +08:00
│ │ ├── components/
│ │ │ ├── VoicePanel.jsx # 语音通话界面
│ │ │ ├── ChatPanel.jsx # 文字对话界面SSE 流式)
│ │ │ ├── SessionHistoryPanel.jsx # 会话历史侧边栏
2026-03-12 12:47:56 +08:00
│ │ │ ├── SettingsPanel.jsx # 语音参数设置面板
│ │ │ └── SubtitleDisplay.jsx# 实时字幕展示
│ │ ├── hooks/
│ │ │ └── useNativeVoiceChat.js # Native WebSocket 语音 Hook
2026-03-12 12:47:56 +08:00
│ │ └── services/
│ │ ├── nativeVoiceService.js # WebSocket 语音服务(音频采集/播放)
│ │ ├── voiceApi.js # 语音/会话 HTTP 请求
2026-03-12 12:47:56 +08:00
│ │ └── chatApi.js # 文字 HTTP/SSE 请求
│ └── vite.config.js
├── server/ # 后端Express
│ ├── app.js # 入口,启动 HTTP + WebSocket 服务
2026-03-12 12:47:56 +08:00
│ ├── routes/
│ │ ├── voice.js # 语音配置、直连会话、知识库查询
│ │ ├── chat.js # 文字对话Coze SSE 流式)
│ │ └── session.js # 会话列表、历史、删除、模式切换
2026-03-12 12:47:56 +08:00
│ ├── services/
│ │ ├── nativeVoiceGateway.js # WebSocket 语音网关(核心)
│ │ ├── realtimeDialogProtocol.js # 二进制协议编解码
│ │ ├── realtimeDialogRouting.js # 意图路由 + 工具调度
2026-03-12 12:47:56 +08:00
│ │ ├── toolExecutor.js # 工具执行器
│ │ ├── arkChatService.js # 方舟 LLM
2026-03-12 12:47:56 +08:00
│ │ └── cozeChatService.js # Coze Chat API文字主服务
│ ├── db/index.js # MySQL CRUD
│ └── .env # 环境变量
└── ecosystem.config.js # PM2 部署配置
```
---
## 4. 语音通话模块Native WebSocket 方案)
2026-03-12 12:47:56 +08:00
### 4.1 混合编排模式
2026-03-12 12:47:56 +08:00
S2S 端到端模型处理普通闲聊(低延迟),方舟 LLM 同时决策是否需要调用工具。两者并行运行。
2026-03-12 12:47:56 +08:00
### 4.2 会话生命周期
```
客户端 WebSocket 连接 → /ws/realtime-dialog
2026-03-12 12:47:56 +08:00
nativeVoiceGateway 创建会话 → 连接上游 Realtime Dialog 服务
2026-03-12 12:47:56 +08:00
客户端采集麦克风 PCM → 发送音频帧 → 上游 ASR + S2S
2026-03-12 12:47:56 +08:00
上游返回字幕/音频 → realtimeDialogRouting 意图路由
2026-03-12 12:47:56 +08:00
工具调用或闲聊回复 → ChatTTSText 注入语音流 → 客户端播放
客户端断开 WebSocket → 会话结束 → 可切换文字模式
2026-03-12 12:47:56 +08:00
```
### 4.3 语音相关端点
2026-03-12 12:47:56 +08:00
| 端点 | 类型 | 说明 |
2026-03-12 12:47:56 +08:00
|------|------|------|
| `/ws/realtime-dialog` | WebSocket | **核心**Native 语音网关 |
2026-03-12 12:47:56 +08:00
| `/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 双层决策)、工具调度、语音播报 |
2026-03-12 12:47:56 +08:00
---
## 5. 语音意图路由与工具调用
2026-03-12 12:47:56 +08:00
### 5.1 数据流
```
用户语音 ASR 识别文本
│ 上游 Realtime Dialog 服务返回
2026-03-12 12:47:56 +08:00
nativeVoiceGateway 接收字幕 → 持久化用户语音到 DB
2026-03-12 12:47:56 +08:00
realtimeDialogRouting.resolveReply()
2026-03-12 12:47:56 +08:00
├─ 规则路由:时间/天气/订单/计算 → 直接工具调用
├─ search_knowledge → 方舟知识库 API
└─ chat → 方舟 LLM 闲聊回复
2026-03-12 12:47:56 +08:00
工具结果/LLM回复 → ChatTTSText 注入上游语音流
2026-03-12 12:47:56 +08:00
AI 语音播报 + 持久化到 DB
2026-03-12 12:47:56 +08:00
```
### 5.2 关键设计
2026-03-12 12:47:56 +08:00
| 问题 | 解决方案 |
|------|----------|
| 意图识别 | 规则路由 + LLM 路由双层决策 |
| S2S 与工具冲突 | ChatTTSText 注入工具结果覆盖 S2S 直连回复 |
| 音频编解码 | realtimeDialogProtocol 自定义二进制协议 |
| 语音文本分段 | 按标点切分,估算播报时长,分段 TTS |
2026-03-12 12:47:56 +08:00
---
## 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 会话管理 APIsession.js
2026-03-12 12:47:56 +08:00
| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/session/list` | GET | 获取会话列表(带最后消息预览) |
2026-03-12 12:47:56 +08:00
| `/api/session/:id/history` | GET | 获取完整历史(支持 llm/full 格式) |
| `/api/session/:id/switch` | POST | 切换模式,返回上下文历史 |
| `/api/session/:id` | DELETE | 删除会话及其消息 |
2026-03-12 12:47:56 +08:00
### 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 # 模式切换 + 全局设置 + 会话管理
2026-03-12 12:47:56 +08:00
├── VoicePanel.jsx # 语音通话 UI开始/结束/静音/时长)
│ └── SubtitleDisplay # 实时字幕definite/interim 区分)
├── ChatPanel.jsx # 文字对话 UI消息列表 + SSE 流式显示)
├── SessionHistoryPanel.jsx # 会话历史侧边栏(新建/切换/删除会话)
2026-03-12 12:47:56 +08:00
└── SettingsPanel.jsx # 设置面板(模型/音色/系统角色/VAD
```
### 8.2 useNativeVoiceChat Hook
2026-03-12 12:47:56 +08:00
管理 Native WebSocket 语音通话完整生命周期:
2026-03-12 12:47:56 +08:00
- **start(options)**:连接 WebSocket → 采集麦克风 PCM → 发送音频帧
- **stop()**:断开 WebSocket → 返回字幕和 sessionId
2026-03-12 12:47:56 +08:00
- **toggleMute()**:静音/取消静音
- **状态**isActive, isMuted, isConnecting, subtitles, duration, error
### 8.3 nativeVoiceService.js
2026-03-12 12:47:56 +08:00
封装 Native WebSocket 语音连接:
2026-03-12 12:47:56 +08:00
- **connect(options)**:建立 WebSocket 连接初始化音频采集getUserMedia + Web Audio API 降采样)
- **disconnect()**:关闭连接、停止音频
- **setMuted(muted)**:控制麦克风
- **事件回调**onSubtitle字幕、onConnectionStateChange连接状态、onError错误
- **音频播放**:接收 PCM 音频帧,通过 Web Audio API 播放
2026-03-12 12:47:56 +08:00
---
## 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 关闭) |
2026-03-12 12:47:56 +08:00
| `MYSQL_HOST/PORT/USER/PASSWORD/DATABASE` | MySQL 配置 |
---
## 10. 部署架构
```
互联网用户
▼ HTTPS (443) + WSS
2026-03-12 12:47:56 +08:00
┌──────────────┐
│ Nginx │ ← 宝塔面板管理
│ (反向代理) │
│ SSL 终止 │
└──────┬───────┘
│ http://localhost:3001
2026-03-12 12:47:56 +08:00
┌──────────────┐
│ PM2 │ ← ecosystem.config.js
│ bigwo-server│
│ (Node.js) │
└──────┬───────┘
├── MySQL 8 (localhost:3306)
├── 火山 Realtime Dialog (wss://openspeech.bytedance.com)
2026-03-12 12:47:56 +08:00
├── 方舟 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
2026-03-12 12:47:56 +08:00
5. **知识库冷启动**:方舟 KB 首次查询较慢(~10s后续查询 ~3-5s