# 数字分身接管聊天功能 — 设计文档 ## 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** 请求体: ```json { "authorization_id": "授权记录ID", "takeover_enabled": true, "takeover_mode": "delayed", "takeover_delay_seconds": 30 } ``` ### 5.2 消息监听(内部接口) **POST /api/internal/takeover/process** 由定时任务调用,无需认证。 请求体: ```json { "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** 请求体: ```json { "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. 测试要点 1. **功能测试** - 立即接管:收到消息后立即由分身回复 - 延迟接管:主人 N 秒内回复则不分身接管,超时则分身回复 - 知识库优先:QA 问答对精确匹配优先返回 2. **边界测试** - 主人有多个分身时的选择逻辑 - 知识库为空时的 Qwen 兜底 - 网易云信 API 异常时的降级 3. **性能测试** - 轮询频率对服务器负载的影响 - Redis 延迟队列的内存占用 --- ## 9. 后续扩展 - Webhook 回调替代轮询(需要会会平台支持) - 多分身协同接管 - 接管历史记录和统计 - 接管效果评估和优化