- 添加Dockerfile用于容器化部署 - 添加docker-compose.yml用于本地开发环境 - 添加build.sh构建脚本 - 添加README.md项目文档 - 添加API文档
15 KiB
15 KiB
Life Echo WebSocket 对话接口测试文档
1. 接口信息
1.1 连接地址
ws://localhost:8000/ws/conversation/{conversation_id}
参数说明:
conversation_id: 对话ID(UUID格式,例如: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)
{
"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)
{
"type": "end_conversation",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2024-01-15T10:35:00.000Z"
}
3.2 服务端消息格式
3.2.1 连接确认 (connect)
{
"type": "connect",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"status": "connected"
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
3.2.2 语音转文字结果 (transcript)
{
"type": "transcript",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"text": "我小时候住在北京"
},
"timestamp": "2024-01-15T10:30:05.000Z"
}
3.2.3 Agent 回应 (agent_response)
{
"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)
{
"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)
{
"type": "end_conversation",
"conversation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"status": "ended"
},
"timestamp": "2024-01-15T10:35:00.000Z"
}
3.2.6 错误信息 (error)
{
"type": "error",
"data": {
"message": "ASR服务暂时不可用,请稍后重试"
},
"timestamp": "2024-01-15T10:30:05.000Z"
}
4. 在 Apifox 中测试步骤
4.1 准备工作
-
启动后端服务
cd api uvicorn main:app --reload --host 0.0.0.0 --port 8000 -
准备测试数据
- 生成一个 UUID 作为
conversation_id(可以使用在线工具或命令行) - 准备一段 Base64 编码的音频数据(用于测试)
- 生成一个 UUID 作为
4.2 创建 WebSocket 连接
-
打开 Apifox
- 创建新请求
- 选择协议类型:WebSocket
-
配置连接地址
ws://localhost:8000/ws/conversation/550e8400-e29b-41d4-a716-446655440000- 将
550e8400-e29b-41d4-a716-446655440000替换为你的对话ID
- 将
-
点击"连接"按钮
- 连接成功后,应该立即收到
connect类型的消息
- 连接成功后,应该立即收到
4.3 测试场景
场景 1:完整对话流程测试
步骤:
-
连接 WebSocket
- 地址:
ws://localhost:8000/ws/conversation/{conversation_id} - 预期收到:
connect消息
- 地址:
-
发送音频块
{ "type": "audio_chunk", "conversation_id": "550e8400-e29b-41d4-a716-446655440000", "data": { "audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA=" } }- 预期收到(按顺序):
transcript- 语音转文字结果agent_response- Agent 回应文本tts_audio- TTS 生成的音频
- 预期收到(按顺序):
-
继续发送多个音频块
- 重复步骤 2,模拟连续对话
-
结束对话
{ "type": "end_conversation", "conversation_id": "550e8400-e29b-41d4-a716-446655440000" }- 预期收到:
end_conversation确认消息 - 连接自动断开
- 预期收到:
场景 2:错误处理测试
测试无效的音频数据:
{
"type": "audio_chunk",
"data": {
"audio_base64": "invalid_base64_data"
}
}
- 预期收到:
error消息,包含错误描述
测试缺少必需字段:
{
"type": "audio_chunk"
}
- 预期收到:
error消息或连接断开
场景 3:连接断开测试
-
正常断开
- 发送
end_conversation消息 - 连接正常关闭
- 发送
-
异常断开
- 直接关闭连接(不发送
end_conversation) - 服务端应清理资源
- 直接关闭连接(不发送
场景 4:多轮对话测试
测试对话阶段切换:
-
发送童年相关话题
{ "type": "audio_chunk", "data": { "audio_base64": "{童年相关音频的base64}" } }- 预期:Agent 回应关于童年的话题
-
发送教育相关话题
{ "type": "audio_chunk", "data": { "audio_base64": "{教育相关音频的base64}" } }- 预期:Agent 自动切换到教育阶段,回应教育相关话题
-
发送工作相关话题
- 预期: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:使用命令行
# Python
python -c "import uuid; print(uuid.uuid4())"
# Node.js
node -e "console.log(require('crypto').randomUUID())"
6.2 准备测试音频
方法1:使用文本转Base64(模拟)
# 创建一个简单的测试音频文件(WAV格式)
# 然后转换为Base64
base64 -i test_audio.wav
方法2:使用在线工具
- 访问:https://base64.guru/converter/encode/audio
- 上传音频文件,获取Base64编码
方法3:使用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 请求
-
新建请求
- 点击"新建" → "WebSocket"
- 或使用快捷键
Ctrl+N(Windows) /Cmd+N(Mac)
-
配置连接
- 名称:Life Echo 对话测试
- URL:
ws://localhost:8000/ws/conversation/{conversation_id} - 方法:WebSocket (自动识别)
-
添加参数
- 在 URL 中直接替换
{conversation_id}为实际值 - 或使用变量:
ws://localhost:8000/ws/conversation/{{conversation_id}}
- 在 URL 中直接替换
7.2 发送消息
-
连接成功后
- 在消息输入框中输入 JSON 格式的消息
- 或使用"消息模板"
-
创建消息模板
{ "type": "audio_chunk", "conversation_id": "{{conversation_id}}", "data": { "audio_base64": "{{audio_base64}}" }, "timestamp": "{{$timestamp}}" } -
发送消息
- 点击"发送"按钮
- 或使用快捷键
Ctrl+Enter
7.3 查看响应
-
实时消息
- 在"消息"面板查看收到的消息
- 消息按时间顺序显示
-
消息详情
- 点击消息查看详细信息
- 可以查看 JSON 格式、时间戳等
-
保存响应
- 右键消息 → "保存为示例"
- 用于后续对比测试
7.4 使用环境变量
-
创建环境
- 点击"环境" → "新建环境"
- 名称:Local Development
-
添加变量
{ "base_url": "ws://localhost:8000", "conversation_id": "550e8400-e29b-41d4-a716-446655440000", "audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA=" } -
在请求中使用
- URL:
{{base_url}}/ws/conversation/{{conversation_id}} - 消息中使用
{{audio_base64}}
- URL:
8. 常见问题排查
8.1 连接失败
问题:无法建立 WebSocket 连接
排查步骤:
- 检查后端服务是否运行:
curl http://localhost:8000/health - 检查端口是否正确:默认 8000
- 检查防火墙设置
- 检查 URL 格式是否正确(
ws://不是http://)
8.2 收不到响应
问题:发送消息后没有收到响应
排查步骤:
- 检查消息格式是否正确(JSON 格式)
- 检查必需字段是否包含(
type,data.audio_base64) - 检查后端日志是否有错误
- 检查 LLM 服务是否配置(DEEPSEEK_API_KEY 或 LLM_API_KEY)
8.3 收到错误消息
问题:收到 error 类型的消息
排查步骤:
- 查看错误消息内容:
data.message - 检查 ASR 服务配置(OPENAI_API_KEY)
- 检查 TTS 服务配置(OPENAI_API_KEY)
- 检查 LLM 服务配置(DEEPSEEK_API_KEY 或 LLM_API_KEY)
8.4 音频处理失败
问题:音频转文字失败
排查步骤:
- 检查音频格式是否支持(WAV、MP3、M4A)
- 检查 Base64 编码是否正确
- 检查音频文件大小(建议 < 10MB)
- 检查 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%
问题记录
- 问题描述:XXX
- 严重程度:高/中/低
- 复现步骤:XXX
- 预期结果:XXX
- 实际结果:XXX
12. 附录
12.1 快速测试脚本
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 开发团队