Files
life-echo/api/docs/WebSocket测试文档.md
徐在坤 ebfd705b93 feat: 添加Docker和部署配置
- 添加Dockerfile用于容器化部署
- 添加docker-compose.yml用于本地开发环境
- 添加build.sh构建脚本
- 添加README.md项目文档
- 添加API文档
2026-01-18 15:58:05 +08:00

619 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Life Echo WebSocket 对话接口测试文档
## 1. 接口信息
### 1.1 连接地址
```
ws://localhost:8000/ws/conversation/{conversation_id}
```
**参数说明:**
- `conversation_id`: 对话IDUUID格式例如`550e8400-e29b-41d4-a716-446655440000`
**示例:**
```
ws://localhost:8000/ws/conversation/550e8400-e29b-41d4-a716-446655440000
```
### 1.2 协议
- 协议类型WebSocket (WS)
- 消息格式JSON
- 编码UTF-8
---
## 2. 消息类型定义
### 2.1 客户端 → 服务端消息类型
| 消息类型 | 说明 | 必需字段 |
|---------|------|---------|
| `audio_chunk` | 发送音频数据块 | `type`, `data.audio_base64` |
| `end_conversation` | 结束对话 | `type` |
### 2.2 服务端 → 客户端消息类型
| 消息类型 | 说明 | 包含字段 |
|---------|------|---------|
| `connect` | 连接确认 | `type`, `conversation_id`, `data.status`, `timestamp` |
| `transcript` | 语音转文字结果 | `type`, `conversation_id`, `data.text`, `timestamp` |
| `agent_response` | Agent 回应文本 | `type`, `conversation_id`, `data.text`, `timestamp` |
| `tts_audio` | TTS 生成的音频 | `type`, `conversation_id`, `data.audio_base64`, `timestamp` |
| `end_conversation` | 对话结束确认 | `type`, `conversation_id`, `data.status`, `timestamp` |
| `error` | 错误信息 | `type`, `data.message`, `timestamp` |
---
## 3. 消息格式规范
### 3.1 客户端消息格式
#### 3.1.1 发送音频块 (audio_chunk)
```json
{
"type": "audio_chunk",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA="
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
```
**字段说明:**
- `type`: 固定值 `"audio_chunk"`
- `conversation_id`: 对话ID可选建议包含
- `data.audio_base64`: Base64编码的音频数据必需
- `timestamp`: ISO 8601格式的时间戳可选
#### 3.1.2 结束对话 (end_conversation)
```json
{
"type": "end_conversation",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2024-01-15T10:35:00.000Z"
}
```
### 3.2 服务端消息格式
#### 3.2.1 连接确认 (connect)
```json
{
"type": "connect",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"status": "connected"
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
```
#### 3.2.2 语音转文字结果 (transcript)
```json
{
"type": "transcript",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"text": "我小时候住在北京"
},
"timestamp": "2024-01-15T10:30:05.000Z"
}
```
#### 3.2.3 Agent 回应 (agent_response)
```json
{
"type": "agent_response",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"text": "听起来很有趣!能告诉我更多关于你在北京的生活吗?比如你最喜欢那里的什么地方?"
},
"timestamp": "2024-01-15T10:30:06.000Z"
}
```
#### 3.2.4 TTS 音频 (tts_audio)
```json
{
"type": "tts_audio",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA="
},
"timestamp": "2024-01-15T10:30:07.000Z"
}
```
#### 3.2.5 对话结束 (end_conversation)
```json
{
"type": "end_conversation",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"status": "ended"
},
"timestamp": "2024-01-15T10:35:00.000Z"
}
```
#### 3.2.6 错误信息 (error)
```json
{
"type": "error",
"data": {
"message": "ASR服务暂时不可用请稍后重试"
},
"timestamp": "2024-01-15T10:30:05.000Z"
}
```
---
## 4. 在 Apifox 中测试步骤
### 4.1 准备工作
1. **启动后端服务**
```bash
cd api
uvicorn main:app --reload --host 0.0.0.0 --port 8000
```
2. **准备测试数据**
- 生成一个 UUID 作为 `conversation_id`(可以使用在线工具或命令行)
- 准备一段 Base64 编码的音频数据(用于测试)
### 4.2 创建 WebSocket 连接
1. **打开 Apifox**
- 创建新请求
- 选择协议类型:**WebSocket**
2. **配置连接地址**
```
ws://localhost:8000/ws/conversation/550e8400-e29b-41d4-a716-446655440000
```
- 将 `550e8400-e29b-41d4-a716-446655440000` 替换为你的对话ID
3. **点击"连接"按钮**
- 连接成功后,应该立即收到 `connect` 类型的消息
### 4.3 测试场景
#### 场景 1完整对话流程测试
**步骤:**
1. **连接 WebSocket**
- 地址:`ws://localhost:8000/ws/conversation/{conversation_id}`
- 预期收到:`connect` 消息
2. **发送音频块**
```json
{
"type": "audio_chunk",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA="
}
}
```
- 预期收到(按顺序):
1. `transcript` - 语音转文字结果
2. `agent_response` - Agent 回应文本
3. `tts_audio` - TTS 生成的音频
3. **继续发送多个音频块**
- 重复步骤 2模拟连续对话
4. **结束对话**
```json
{
"type": "end_conversation",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000"
}
```
- 预期收到:`end_conversation` 确认消息
- 连接自动断开
#### 场景 2错误处理测试
**测试无效的音频数据:**
```json
{
"type": "audio_chunk",
"data": {
"audio_base64": "invalid_base64_data"
}
}
```
- 预期收到:`error` 消息,包含错误描述
**测试缺少必需字段:**
```json
{
"type": "audio_chunk"
}
```
- 预期收到:`error` 消息或连接断开
#### 场景 3连接断开测试
1. **正常断开**
- 发送 `end_conversation` 消息
- 连接正常关闭
2. **异常断开**
- 直接关闭连接(不发送 `end_conversation`
- 服务端应清理资源
#### 场景 4多轮对话测试
**测试对话阶段切换:**
1. **发送童年相关话题**
```json
{
"type": "audio_chunk",
"data": {
"audio_base64": "{童年相关音频的base64}"
}
}
```
- 预期Agent 回应关于童年的话题
2. **发送教育相关话题**
```json
{
"type": "audio_chunk",
"data": {
"audio_base64": "{教育相关音频的base64}"
}
}
```
- 预期Agent 自动切换到教育阶段,回应教育相关话题
3. **发送工作相关话题**
- 预期Agent 切换到职业阶段
---
## 5. 测试用例清单
### 5.1 基础功能测试
| 用例ID | 测试场景 | 输入 | 预期结果 | 状态 |
|--------|---------|------|---------|------|
| TC-001 | 建立连接 | 连接 WebSocket | 收到 `connect` 消息 | ⬜ |
| TC-002 | 发送音频块 | 发送 `audio_chunk` | 收到 `transcript`、`agent_response`、`tts_audio` | ⬜ |
| TC-003 | 结束对话 | 发送 `end_conversation` | 收到 `end_conversation` 确认,连接断开 | ⬜ |
| TC-004 | 多轮对话 | 连续发送多个音频块 | 每轮都收到完整响应 | ⬜ |
### 5.2 异常场景测试
| 用例ID | 测试场景 | 输入 | 预期结果 | 状态 |
|--------|---------|------|---------|------|
| TC-101 | 无效音频数据 | 发送无效 base64 | 收到 `error` 消息 | ⬜ |
| TC-102 | 缺少必需字段 | 发送不完整的消息 | 收到 `error` 或连接断开 | ⬜ |
| TC-103 | 无效对话ID | 使用不存在的 conversation_id | 连接成功但创建新对话 | ⬜ |
| TC-104 | 连接超时 | 长时间不发送消息 | 连接保持或超时断开 | ⬜ |
| TC-105 | 异常断开 | 直接关闭连接 | 服务端清理资源 | ⬜ |
### 5.3 性能测试
| 用例ID | 测试场景 | 输入 | 预期结果 | 状态 |
|--------|---------|------|---------|------|
| TC-201 | 快速连续发送 | 1秒内发送10个音频块 | 所有请求都能正常处理 | ⬜ |
| TC-202 | 大音频块 | 发送较大的音频数据 | 正常处理,响应时间在可接受范围 | ⬜ |
| TC-203 | 长时间连接 | 保持连接30分钟 | 连接稳定,无内存泄漏 | ⬜ |
---
## 6. 测试数据准备
### 6.1 生成对话ID
**方法1使用在线工具**
- 访问https://www.uuidgenerator.net/
- 生成 UUID v4
**方法2使用命令行**
```bash
# Python
python -c "import uuid; print(uuid.uuid4())"
# Node.js
node -e "console.log(require('crypto').randomUUID())"
```
### 6.2 准备测试音频
**方法1使用文本转Base64模拟**
```bash
# 创建一个简单的测试音频文件WAV格式
# 然后转换为Base64
base64 -i test_audio.wav
```
**方法2使用在线工具**
- 访问https://base64.guru/converter/encode/audio
- 上传音频文件获取Base64编码
**方法3使用Python脚本**
```python
import base64
with open("test_audio.wav", "rb") as f:
audio_base64 = base64.b64encode(f.read()).decode('utf-8')
print(audio_base64)
```
### 6.3 测试音频建议
- **格式**WAV、MP3、M4A
- **时长**3-10秒
- **内容**:清晰的中文语音
- **示例话题**
- 童年:"我小时候住在北京"
- 教育:"我在清华大学读书"
- 工作:"我在一家科技公司工作"
- 家庭:"我有一个幸福的家庭"
---
## 7. 在 Apifox 中的详细操作
### 7.1 创建 WebSocket 请求
1. **新建请求**
- 点击"新建" → "WebSocket"
- 或使用快捷键 `Ctrl+N` (Windows) / `Cmd+N` (Mac)
2. **配置连接**
- **名称**Life Echo 对话测试
- **URL**`ws://localhost:8000/ws/conversation/{conversation_id}`
- **方法**WebSocket (自动识别)
3. **添加参数**
- 在 URL 中直接替换 `{conversation_id}` 为实际值
- 或使用变量:`ws://localhost:8000/ws/conversation/{{conversation_id}}`
### 7.2 发送消息
1. **连接成功后**
- 在消息输入框中输入 JSON 格式的消息
- 或使用"消息模板"
2. **创建消息模板**
```json
{
"type": "audio_chunk",
"conversation_id": "{{conversation_id}}",
"data": {
"audio_base64": "{{audio_base64}}"
},
"timestamp": "{{$timestamp}}"
}
```
3. **发送消息**
- 点击"发送"按钮
- 或使用快捷键 `Ctrl+Enter`
### 7.3 查看响应
1. **实时消息**
- 在"消息"面板查看收到的消息
- 消息按时间顺序显示
2. **消息详情**
- 点击消息查看详细信息
- 可以查看 JSON 格式、时间戳等
3. **保存响应**
- 右键消息 → "保存为示例"
- 用于后续对比测试
### 7.4 使用环境变量
1. **创建环境**
- 点击"环境" → "新建环境"
- 名称Local Development
2. **添加变量**
```json
{
"base_url": "ws://localhost:8000",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA="
}
```
3. **在请求中使用**
- URL: `{{base_url}}/ws/conversation/{{conversation_id}}`
- 消息中使用 `{{audio_base64}}`
---
## 8. 常见问题排查
### 8.1 连接失败
**问题**:无法建立 WebSocket 连接
**排查步骤:**
1. 检查后端服务是否运行:`curl http://localhost:8000/health`
2. 检查端口是否正确:默认 8000
3. 检查防火墙设置
4. 检查 URL 格式是否正确(`ws://` 不是 `http://`
### 8.2 收不到响应
**问题**:发送消息后没有收到响应
**排查步骤:**
1. 检查消息格式是否正确JSON 格式)
2. 检查必需字段是否包含(`type`, `data.audio_base64`
3. 检查后端日志是否有错误
4. 检查 LLM 服务是否配置DEEPSEEK_API_KEY 或 LLM_API_KEY
### 8.3 收到错误消息
**问题**:收到 `error` 类型的消息
**排查步骤:**
1. 查看错误消息内容:`data.message`
2. 检查 ASR 服务配置OPENAI_API_KEY
3. 检查 TTS 服务配置OPENAI_API_KEY
4. 检查 LLM 服务配置DEEPSEEK_API_KEY 或 LLM_API_KEY
### 8.4 音频处理失败
**问题**:音频转文字失败
**排查步骤:**
1. 检查音频格式是否支持WAV、MP3、M4A
2. 检查 Base64 编码是否正确
3. 检查音频文件大小(建议 < 10MB
4. 检查 ASR 服务是否可用
---
## 9. 测试检查清单
### 9.1 连接测试
- [ ] 能够成功建立 WebSocket 连接
- [ ] 连接后立即收到 `connect` 消息
- [ ] 连接信息包含正确的 `conversation_id`
### 9.2 消息发送测试
- [ ] 能够发送 `audio_chunk` 消息
- [ ] 能够发送 `end_conversation` 消息
- [ ] 消息格式符合规范
### 9.3 消息接收测试
- [ ] 发送音频后收到 `transcript` 消息
- [ ] 收到 `agent_response` 消息
- [ ] 收到 `tts_audio` 消息
- [ ] 消息顺序正确transcript → agent_response → tts_audio
### 9.4 功能测试
- [ ] 语音转文字功能正常
- [ ] Agent 回应内容合理
- [ ] TTS 音频生成正常
- [ ] 对话阶段自动切换
### 9.5 异常处理测试
- [ ] 无效消息返回错误
- [ ] 连接断开时资源清理
- [ ] 错误消息格式正确
---
## 10. 性能指标
### 10.1 响应时间
| 操作 | 目标响应时间 | 实际响应时间 | 状态 |
|------|------------|------------|------|
| 连接建立 | < 1s | - | ⬜ |
| 音频转文字 | < 3s | - | ⬜ |
| Agent 回应 | < 5s | - | ⬜ |
| TTS 生成 | < 3s | - | ⬜ |
| 完整流程 | < 15s | - | ⬜ |
### 10.2 并发测试
- [ ] 支持 10 个并发连接
- [ ] 支持 50 个并发连接
- [ ] 支持 100 个并发连接
---
## 11. 测试报告模板
### 测试信息
- **测试日期**2024-XX-XX
- **测试人员**XXX
- **测试环境**Local Development
- **后端版本**1.0.0
### 测试结果
- **总用例数**XX
- **通过数**XX
- **失败数**XX
- **通过率**XX%
### 问题记录
1. **问题描述**XXX
- **严重程度**:高/中/低
- **复现步骤**XXX
- **预期结果**XXX
- **实际结果**XXX
---
## 12. 附录
### 12.1 快速测试脚本
**Python 测试脚本示例:**
```python
import asyncio
import websockets
import json
import uuid
import base64
async def test_websocket():
conversation_id = str(uuid.uuid4())
uri = f"ws://localhost:8000/ws/conversation/{conversation_id}"
async with websockets.connect(uri) as websocket:
# 接收连接确认
response = await websocket.recv()
print("收到连接确认:", response)
# 发送音频块(模拟)
message = {
"type": "audio_chunk",
"conversation_id": conversation_id,
"data": {
"audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA="
}
}
await websocket.send(json.dumps(message))
# 接收响应
for i in range(3):
response = await websocket.recv()
print(f"收到响应 {i+1}:", response)
# 结束对话
end_message = {
"type": "end_conversation",
"conversation_id": conversation_id
}
await websocket.send(json.dumps(end_message))
# 接收结束确认
response = await websocket.recv()
print("收到结束确认:", response)
asyncio.run(test_websocket())
```
### 12.2 参考链接
- FastAPI WebSocket 文档https://fastapi.tiangolo.com/advanced/websockets/
- Apifox WebSocket 测试https://apifox.com/help/app/web-socket
- UUID 生成器https://www.uuidgenerator.net/
- Base64 编码工具https://base64.guru/converter/encode/audio
---
**文档版本**v1.0
**最后更新**2024-01-15
**维护人员**Life Echo 开发团队