feat: 添加Docker和部署配置

- 添加Dockerfile用于容器化部署
- 添加docker-compose.yml用于本地开发环境
- 添加build.sh构建脚本
- 添加README.md项目文档
- 添加API文档
This commit is contained in:
徐在坤
2026-01-18 15:58:05 +08:00
parent 8582e88ec2
commit ebfd705b93
7 changed files with 1533 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
# Life Echo WebSocket 快速测试指南
## 🚀 快速开始
### 1. 连接地址
```
ws://localhost:8000/ws/conversation/{conversation_id}
```
### 2. 生成对话ID
```bash
# Python
python -c "import uuid; print(uuid.uuid4())"
# 或使用在线工具https://www.uuidgenerator.net/
```
### 3. 在 Apifox 中操作
1. **新建 WebSocket 请求**
- 协议WebSocket
- URL`ws://localhost:8000/ws/conversation/你的对话ID`
2. **点击连接**
- 应该立即收到 `connect` 消息
3. **发送音频块**
```json
{
"type": "audio_chunk",
"conversation_id": "你的对话ID",
"data": {
"audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA="
}
}
```
4. **接收响应**(按顺序)
- `transcript` - 语音转文字
- `agent_response` - Agent 回应
- `tts_audio` - TTS 音频
5. **结束对话**
```json
{
"type": "end_conversation",
"conversation_id": "你的对话ID"
}
```
---
## 📋 消息类型速查
### 客户端发送
| 类型 | 说明 | JSON 示例 |
|------|------|-----------|
| `audio_chunk` | 发送音频 | `{"type":"audio_chunk","data":{"audio_base64":"..."}}` |
| `end_conversation` | 结束对话 | `{"type":"end_conversation"}` |
### 服务端返回
| 类型 | 说明 | 包含字段 |
|------|------|---------|
| `connect` | 连接确认 | `data.status` |
| `transcript` | 语音转文字 | `data.text` |
| `agent_response` | Agent 回应 | `data.text` |
| `tts_audio` | TTS 音频 | `data.audio_base64` |
| `end_conversation` | 结束确认 | `data.status` |
| `error` | 错误信息 | `data.message` |
---
## 🧪 测试场景
### 场景1基础对话
1. 连接 → 2. 发送音频 → 3. 接收3条响应 → 4. 结束对话
### 场景2多轮对话
重复场景1的步骤2-3多次
### 场景3错误处理
发送无效的 `audio_base64` 数据,查看 `error` 消息
---
## ⚠️ 常见问题
**Q: 连接失败?**
A: 检查后端服务是否运行:`curl http://localhost:8000/health`
**Q: 收不到响应?**
A: 检查消息格式和必需字段,查看后端日志
**Q: 音频处理失败?**
A: 检查音频格式和 Base64 编码,确保 ASR/TTS 服务配置正确
---
## 📝 完整文档
详细测试文档请参考:`WebSocket测试文档.md`

View File

@@ -0,0 +1,618 @@
# 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 开发团队

View File

@@ -0,0 +1,147 @@
# 文字交流模式说明
## 概述
当前系统已配置为**纯文字交流模式**暂时不接通语音模块ASR/TTS。用户可以通过WebSocket发送文字消息与AI进行对话系统会自动将对话记录整理成书的多个章节。
## 功能特性
### 1. 文字对话
- 用户通过WebSocket发送 `TEXT` 类型的消息
- AI Agent 生成文字回应
- 所有对话记录保存到数据库
### 2. 章节自动整理
- 对话结束后,系统自动调用 Memory Agent
- 将对话段落整理成结构化的章节
- 章节按类别分类(童年、教育、职业、家庭、信念、总结等)
### 3. 用户认证
- 所有操作需要用户登录
- 使用JWT访问令牌进行认证
- WebSocket连接需要传递token参数
## WebSocket 消息格式
### 客户端发送
#### 文字消息
```json
{
"type": "text",
"conversation_id": "conversation-id",
"data": {
"text": "我小时候住在北京"
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
```
#### 结束对话
```json
{
"type": "end_conversation",
"conversation_id": "conversation-id"
}
```
### 服务端返回
#### 连接确认
```json
{
"type": "connect",
"conversation_id": "conversation-id",
"data": {
"status": "connected"
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
```
#### Agent 回应
```json
{
"type": "agent_response",
"conversation_id": "conversation-id",
"data": {
"text": "听起来很有趣!能告诉我更多关于你在北京的生活吗?"
},
"timestamp": "2024-01-15T10:30:05.000Z"
}
```
#### 对话结束确认
```json
{
"type": "end_conversation",
"conversation_id": "conversation-id",
"data": {
"status": "ended"
},
"timestamp": "2024-01-15T10:35:00.000Z"
}
```
## 使用流程
### 1. 用户注册/登录
```bash
POST /api/auth/register
{
"phone": "13800138000",
"password": "password123",
"nickname": "用户昵称"
}
# 返回 access_token 和 refresh_token
```
### 2. 创建对话
```bash
POST /api/conversations
Authorization: Bearer {access_token}
# 返回 conversation_id
```
### 3. 连接 WebSocket
```
ws://localhost:8000/ws/conversation/{conversation_id}?token={access_token}
```
### 4. 发送文字消息
发送 `TEXT` 类型消息,接收 `AGENT_RESPONSE` 回应
### 5. 结束对话
发送 `END_CONVERSATION` 消息,系统自动整理章节
### 6. 查看章节
```bash
GET /api/chapters
Authorization: Bearer {access_token}
```
## 已移除的功能
- ❌ 音频块处理(`AUDIO_CHUNK`
- ❌ 语音转文字ASR
- ❌ 文字转语音TTS
- ❌ 转写结果消息(`TRANSCRIPT`
- ❌ TTS音频消息`TTS_AUDIO`
## 保留的功能
- ✅ 文字消息处理(`TEXT`
- ✅ Agent 文字回应(`AGENT_RESPONSE`
- ✅ 对话阶段检测
- ✅ 章节自动整理
- ✅ 用户认证
- ✅ 对话管理
## 注意事项
1. **WebSocket 连接必须提供 token**`ws://.../ws/conversation/{id}?token={access_token}`
2. **所有对话记录都会保存**:用于后续章节整理
3. **章节整理在对话结束时触发**:发送 `END_CONVERSATION` 消息
4. **章节按类别自动分类**:系统会根据内容自动判断章节类别