12 KiB
12 KiB
数字分身接管聊天功能 — 设计文档
1. 概述
1.1 背景
当前数字分身应用中,分身只能与主人一对一聊天。用户希望分身能在主人授权下,接管主人在会会平台上的聊天(单聊和群聊),替主人与他人对话。
1.2 目标
- 主人可在授权管理页面开启"分身接管聊天"功能
- 支持两种接管模式:立即接管、延迟接管(N 秒后)
- 分身回复优先使用知识库(QA 问答对 + 文档向量搜索)
- 支持单聊和群聊两种场景
- 以主人身份发送回复,对方无感知
1.3 技术基础
- 会会平台使用网易云信作为 IM 底层
- 已有接口:
/api/im/netease(获取云信凭证)、/api/v2message/push/record/*(消息推送) - 已有分身聊天接口:
POST /api/avatar/{id}/chat
2. 架构设计
2.1 整体架构
┌─────────────────────────────────────────────────────────┐
│ 会会平台 (网易云信) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ 单聊 P2P │ │ 群聊 Group │ │ 消息推送 Push │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└──────────────────────┬──────────────────────────────────┘
│ HTTP API
──────────────────────▼──────────────────────────────────┐
│ 分身接管服务 (Avatar Takeover Service) │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ 消息监听器 │ │ 接管决策器 │ │ 回复执行器 │ │
│ └──────────────┘ ──────────────┘ └───────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Redis 延迟队列 │ │
│ └──────────────────────────────────────────────────┘ │
└──────────────────────┬──────────────────────────────────┘
│ 调用现有接口
┌──────────────────────▼──────────────────────────────────┐
│ 数字分身应用 │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ 授权管理 UI │ │ 分身聊天 API │ │ 知识库 │ │
│ └──────────────┘ └──────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────────────┘
2.2 模块划分
| 模块 | 位置 | 职责 |
|---|---|---|
| 接管配置 | 授权管理页面 + authorizations 表 | 存储接管开关、模式、延迟秒数 |
| 消息监听器 | 后端定时任务 | 轮询网易云信消息,发现新消息 |
| 接管决策器 | 后端服务 | 判断是否接管、立即还是延迟 |
| 回复执行器 | 后端服务 | 调用分身聊天接口生成回复,以主人身份发送 |
| 延迟队列 | Redis | 存储待处理消息,实现延迟接管 |
3. 数据模型
3.1 扩展 Authorization 表
在现有 authorizations 表基础上新增字段:
| 字段 | 类型 | 说明 |
|---|---|---|
takeover_enabled |
BOOLEAN | 是否开启分身接管聊天 |
takeover_mode |
VARCHAR | 接管模式:immediate(立即)/ delayed(延迟) |
takeover_delay_seconds |
INTEGER | 延迟秒数(仅 delayed 模式有效),默认 30 |
权限关联:
permissions数组中包含"takeover"时,表示该授权允许分身接管target_type = "user"且permissions含"takeover"→ 单聊接管target_type = "organization"或群聊相关 → 群聊接管
3.2 Redis 数据结构
# 延迟消息队列
takeover:delayed:{owner_accid}:{message_id} = {
"avatar_id": "...",
"from_accid": "...",
"content": "...",
"chat_type": "p2p|group",
"chat_id": "...",
"timestamp": 1234567890
}
TTL = takeover_delay_seconds + 10
4. 核心流程
4.1 消息监听流程
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ 定时任务 │────►│ 轮询 Push API │────►│ 获取未读消息 │
└──────────┘ └──────────────┘ └──────┬───────┘
│
┌─────────▼─────────┐
│ 遍历每条新消息 │
└─────────┬─────────┘
│
┌─────────▼─────────┐
│ 查询主人授权配置 │
└─────────┬─────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
┌─────▼─────┐ ┌──────▼────── ┌──────▼──────┐
│ 未开启接管 │ │ 立即接管模式 │ │ 延迟接管模式 │
└───────────┘ └──────┬──────┘ └──────┬──────┘
│ │
┌─────────▼─────────┐ ┌────▼────
│ 立即调用分身回复 │ │ 写入延迟 │
───────────────────┘ │ 队列 │
└─────────┘
4.2 延迟接管流程
┌──────────────────────────────────────────────────────────┐
│ 消息写入 Redis 延迟队列 (TTL = delay_seconds + 10) │
└────────────────────────┬─────────────────────────────────┘
│
│ 延迟期间
│
┌─────────▼─────────┐
│ 主人是否有回复? │
└─────────┬─────────┘
────┴────┐
│ │
┌─────▼──┐ ┌───▼────
│ 有回复 │ │ 无回复 │
└──┬─────┘ └───┬────┘
│ │
┌─────▼─────┐ ───▼──────────────┐
│ 删除队列 │ │ TTL 到期触发 │
│ 不接管 │ │ 调用分身回复 │
───────────┘ └──────────────────
4.3 回复生成流程
┌────────────────────┐
│ 收到他人消息内容 │
└─────────┬──────────┘
│
┌─────────▼──────────┐
│ 查找主人的分身 │
│ (按 owner_id 匹配) │
└─────────┬──────────
│
┌─────────▼──────────┐
│ 调用分身聊天接口 │
│ POST /api/avatar/ │
│ {id}/chat │
│ 优先:QA 问答对 │
│ 其次:知识库文档 │
│ 最后:Qwen 生成 │
└─────────┬──────────┘
│
┌─────────▼──────────
│ 以主人身份发送回复 │
│ 通过网易云信 API │
└────────────────────┘
5. API 设计
5.1 授权管理增强
PUT /api/avatar/{avatar_id}/authorizations/takeover
请求体:
{
"authorization_id": "授权记录ID",
"takeover_enabled": true,
"takeover_mode": "delayed",
"takeover_delay_seconds": 30
}
5.2 消息监听(内部接口)
POST /api/internal/takeover/process
由定时任务调用,无需认证。
请求体:
{
"owner_accid": "主人网易云信账号",
"messages": [
{
"msg_id": "消息ID",
"from_accid": "发送者账号",
"content": "消息内容",
"chat_type": "p2p",
"chat_id": "会话ID",
"timestamp": 1234567890
}
]
}
5.3 网易云信消息发送
复用现有网易云信 API 封装,新增单聊消息发送方法:
POST /im/netease/message/send/p2p
请求体:
{
"from_accid": "主人账号",
"to_accid": "对方账号",
"content": "回复内容",
"msg_type": "text"
}
6. 错误处理
| 场景 | 处理方式 |
|---|---|
| 分身聊天接口调用失败 | 记录日志,不回复,下次继续监听 |
| 网易云信发送失败 | 重试 3 次,失败后记录日志 |
| 主人有多个分身 | 取第一个 active 状态的分身 |
| 知识库无匹配内容 | 使用 Qwen 兜底生成回复 |
| Redis 连接失败 | 降级为立即接管模式 |
7. 配置项
在 SystemConfig 表中新增配置:
| 配置 key | 说明 | 默认值 |
|---|---|---|
takeover_poll_interval |
消息轮询间隔(秒) | 10 |
takeover_default_delay |
默认延迟秒数 | 30 |
takeover_retry_times |
发送重试次数 | 3 |
8. 测试要点
-
功能测试
- 立即接管:收到消息后立即由分身回复
- 延迟接管:主人 N 秒内回复则不分身接管,超时则分身回复
- 知识库优先:QA 问答对精确匹配优先返回
-
边界测试
- 主人有多个分身时的选择逻辑
- 知识库为空时的 Qwen 兜底
- 网易云信 API 异常时的降级
-
性能测试
- 轮询频率对服务器负载的影响
- Redis 延迟队列的内存占用
9. 后续扩展
- Webhook 回调替代轮询(需要会会平台支持)
- 多分身协同接管
- 接管历史记录和统计
- 接管效果评估和优化