Conversation 模块设计文档
1. 模块概述
Conversation 模块负责管理用户的对话会话,包括对话的创建、查询、更新、删除等核心功能。该模块由服务层(services/conversation.py)和路由层(routers/conversation.py)组成,提供完整的对话生命周期管理能力。
1.1 主要组件
- ConversationManager: 对话管理器,提供对话的底层数据操作
- Router: FastAPI 路由层,提供 RESTful API 接口
1.2 核心功能
- 获取用户对话列表
- 创建新对话
- 更新对话信息
- 删除对话及关联资源
- 对话权限验证
- App 使用统计
2. 模块架构
2.1 整体架构图
graph TB
Client[客户端] --> Router[FastAPI Router]
Router --> Middleware[依赖中间件]
Middleware --> SessionVerify[会话验证]
Middleware --> TokenVerify[个人令牌验证]
Router --> ConvMgr[ConversationManager]
ConvMgr --> PostgreSQL[(PostgreSQL)]
ConvMgr --> TaskMgr[TaskManager]
Router --> DocMgr[DocumentManager]
style Client fill:#e1f5ff
style Router fill:#fff4e1
style ConvMgr fill:#e7f5e1
style PostgreSQL fill:#f5e1e1
2.2 数据模型关系
erDiagram
Conversation ||--o{ UserAppUsage : "tracks"
Conversation ||--o{ Task : "contains"
Conversation ||--o{ Document : "contains"
Conversation {
uuid id PK
string userId FK
uuid appId FK
string title
boolean isTemporary
datetime createdAt
}
UserAppUsage {
string userId FK
uuid appId FK
int usageCount
datetime lastUsed
}
Task {
uuid id PK
uuid conversationId FK
}
Document {
uuid id PK
uuid conversationId FK
}
3. 核心流程
3.1 获取对话列表流程
sequenceDiagram
participant C as 客户端
participant R as Router
participant Auth as 认证中间件
participant CM as ConversationManager
participant DM as DocumentManager
participant DB as PostgreSQL
C->>R: GET /api/conversation
R->>Auth: 验证会话和令牌
Auth-->>R: 验证通过
R->>CM: get_conversation_by_user_id(user_id)
CM->>DB: SELECT * FROM Conversation WHERE userId=?
DB-->>CM: 返回对话列表
CM-->>R: 返回Conversation对象列表
loop 遍历每个对话
R->>DM: get_doc_count(conversation_id)
DM-->>R: 返回文档数量
end
R-->>C: 返回ConversationListRsp
流程说明:
- 客户端发起 GET 请求获取对话列表
- 通过认证中间件验证用户身份
- 从数据库查询用户的所有非临时对话
- 按创建时间倒序排列
- 为每个对话获取关联文档数量
- 返回格式化的对话列表响应
3.2 创建对话流程
flowchart TD
Start([开始创建对话]) --> Input[接收参数: title, user_id, app_id, debug]
Input --> CreateObj[创建Conversation对象]
CreateObj --> SaveDB{保存到数据库}
SaveDB -->|失败| Error[记录错误日志]
Error --> ReturnNull[返回None]
SaveDB -->|成功| CheckDebug{是否为调试模式?}
CheckDebug -->|是| ReturnConv[返回对话对象]
CheckDebug -->|否| CheckAppId{app_id是否存在?}
CheckAppId -->|否| ReturnConv
CheckAppId -->|是| QueryUsage[查询UserAppUsage]
QueryUsage --> UsageExists{使用记录存在?}
UsageExists -->|是| UpdateUsage[更新usageCount+1<br/>更新lastUsed时间]
UsageExists -->|否| CreateUsage[创建新的使用记录<br/>usageCount=1]
UpdateUsage --> CommitUsage[提交事务]
CreateUsage --> CommitUsage
CommitUsage --> ReturnConv
ReturnConv --> End([结束])
ReturnNull --> End
style Start fill:#e1f5ff
style End fill:#e1f5ff
style Error fill:#ffe1e1
style ReturnConv fill:#e7f5e1
流程说明:
- 创建 Conversation 对象并设置基本属性
- 尝试保存到数据库
- 如果非调试模式且提供了 app_id,则更新 App 使用统计
- 如果 UserAppUsage 记录存在,增加计数器;否则创建新记录
- 返回创建的对话对象
3.3 更新对话流程
sequenceDiagram
participant C as 客户端
participant R as Router
participant CM as ConversationManager
participant DM as DocumentManager
participant DB as PostgreSQL
C->>R: POST /api/conversation?conversationId=xxx
Note over C,R: Body: {title: "新标题"}
R->>CM: get_conversation_by_conversation_id(user_id, conversation_id)
CM->>DB: SELECT * FROM Conversation WHERE id=? AND userId=?
DB-->>CM: 返回对话对象
CM-->>R: 返回Conversation
alt 对话不存在或权限不足
R-->>C: 400 Bad Request
else 对话存在
R->>CM: update_conversation_by_conversation_id(user_id, id, data)
CM->>DB: UPDATE Conversation SET title=? WHERE id=?
DB-->>CM: 更新成功
CM-->>R: 返回True
R->>DM: get_doc_count(conversation_id)
DM-->>R: 返回文档数量
R-->>C: 200 OK + 更新后的对话信息
end
流程说明:
- 客户端发送更新请求,包含新的标题
- 验证对话是否存在且属于当前用户
- 如果验证失败,返回 400 错误
- 如果验证通过,更新对话信息
- 获取文档数量并返回完整的对话信息
3.4 删除对话流程
sequenceDiagram
participant C as 客户端
participant R as Router
participant CM as ConversationManager
participant DM as DocumentManager
participant TM as TaskManager
participant DB as PostgreSQL
C->>R: DELETE /api/conversation
Note over C,R: Body: {conversation_list: [id1, id2, ...]}
loop 遍历每个conversation_id
R->>CM: delete_conversation_by_conversation_id(user_id, id)
CM->>DB: SELECT * FROM Conversation WHERE id=? AND userId=?
DB-->>CM: 返回对话对象
alt 对话存在
CM->>DB: DELETE FROM Conversation WHERE id=?
DB-->>CM: 删除成功
CM->>TM: delete_tasks_by_conversation_id(id)
TM-->>CM: 任务删除完成
end
CM-->>R: 删除完成
R->>R: auth_header = request.session.session_id || request.state.personal_token
R->>DM: delete_document_by_conversation_id(id, auth_header)
DM-->>R: 文档删除完成
end
R-->>C: 200 OK + 已删除的对话ID列表
流程说明:
- 客户端发送删除请求,包含要删除的对话ID列表
- 遍历每个对话ID
- 从数据库删除对话记录
- 级联删除关联的任务(通过 TaskManager)
- 级联删除关联的文档(通过 DocumentManager)
- 返回成功删除的对话ID列表
3.5 对话权限验证流程
flowchart TD
Start([开始验证]) --> Input[输入: user_id, conversation_id]
Input --> Query[查询数据库]
Query --> SQL["SELECT COUNT(id) FROM Conversation<br/>WHERE id=? AND userId=?"]
SQL --> GetResult[获取查询结果]
GetResult --> CheckCount{count > 0?}
CheckCount -->|是| ReturnTrue[返回 True]
CheckCount -->|否| ReturnFalse[返回 False]
ReturnTrue --> End([结束])
ReturnFalse --> End
style Start fill:#e1f5ff
style End fill:#e1f5ff
style ReturnTrue fill:#e7f5e1
style ReturnFalse fill:#ffe1e1
4. API 接口定义
4.1 获取对话列表
接口: GET /api/conversation
认证: 需要会话验证和个人令牌验证
响应示例:
{
"code": 200,
"message": "success",
"result": {
"conversations": [
{
"conversationId": "uuid",
"title": "对话标题",
"docCount": 5,
"createdTime": "2025-01-15 10:30:00",
"appId": "uuid",
"debug": false
}
]
}
}
4.2 更新对话
接口: POST /api/conversation?conversationId={uuid}
请求体:
{
"title": "新的对话标题"
}
响应示例:
{
"code": 200,
"message": "success",
"result": {
"conversationId": "uuid",
"title": "新的对话标题",
"docCount": 5,
"createdTime": "2025-01-15 10:30:00",
"appId": "uuid",
"debug": false
}
}
4.3 删除对话
接口: DELETE /api/conversation
请求体:
{
"conversation_list": ["uuid1", "uuid2"]
}
响应示例:
{
"code": 200,
"message": "success",
"result": {
"conversationIdList": ["uuid1", "uuid2"]
}
}
5. ConversationManager 类方法
5.1 方法列表
| 方法名 | 功能描述 | 参数 | 返回值 |
|---|---|---|---|
get_conversation_by_user_id |
获取用户的对话列表 | user_id: str |
list[Conversation] |
get_conversation_by_conversation_id |
通过ID获取对话 | user_id: str, conversation_id: UUID |
Conversation | None |
verify_conversation_access |
验证对话访问权限 | user_id: str, conversation_id: UUID |
bool |
add_conversation_by_user_id |
创建新对话 | title: str, user_id: str, app_id: UUID, debug: bool |
Conversation | None |
update_conversation_by_conversation_id |
更新对话信息 | user_id: str, conversation_id: UUID, data: dict |
bool |
delete_conversation_by_conversation_id |
删除指定对话 | user_id: str, conversation_id: UUID |
None |
delete_conversation_by_user_id |
删除用户所有对话 | user_id: str |
None |
verify_conversation_id |
验证对话ID有效性 | user_id: str, conversation_id: UUID |
bool |
5.2 方法调用关系
graph LR
API[API Router] --> Get[get_conversation_by_user_id]
API --> GetById[get_conversation_by_conversation_id]
API --> Add[add_conversation_by_user_id]
API --> Update[update_conversation_by_conversation_id]
API --> Delete[delete_conversation_by_conversation_id]
API --> DeleteUser[delete_conversation_by_user_id]
API --> Verify[verify_conversation_access]
API --> VerifyId[verify_conversation_id]
Delete --> TaskDel[TaskManager.delete_tasks]
DeleteUser --> TaskDel
Add --> Usage[更新UserAppUsage]
style API fill:#fff4e1
style TaskDel fill:#e1f5ff
style Usage fill:#f5e1ff
6. 关键特性
6.1 权限控制
所有操作都基于 user_id 进行权限验证,确保用户只能访问自己的对话:
and_(
Conversation.id == conversation_id,
Conversation.userId == user_id,
)
6.2 临时对话(Debug 模式)
- 通过
isTemporary字段标识调试对话 - 临时对话不会出现在对话列表中
- 临时对话不会更新 App 使用统计
6.3 级联删除
删除对话时,会自动删除关联资源:
- 通过 TaskManager 删除关联任务
- 通过 DocumentManager 删除关联文档
6.4 App 使用统计
创建非调试对话时,会自动维护 App 使用统计:
- 增加
usageCount计数 - 更新
lastUsed时间戳 - 如果记录不存在,则创建新记录
7. 错误处理
7.1 异常捕获
创建对话时使用 try-except 捕获异常:
try:
# 数据库操作
except Exception:
logger.exception("[ConversationManager] 新建对话失败")
return None
7.2 状态码定义
| 状态码 | 场景 | 说明 |
|---|---|---|
| 200 | 成功 | 操作成功完成 |
| 400 | 客户端错误 | 对话不存在或无权限 |
| 500 | 服务器错误 | 数据库操作失败 |