933 lines
27 KiB
Markdown
933 lines
27 KiB
Markdown
# 小牛群聊 BOT 重构说明
|
||
|
||
## 目标
|
||
|
||
把当前 `ai_auto_response` 从“随机插话的自动回复”升级成一个真正适合微信群长期在线的拟人 BOT `小牛`:
|
||
|
||
- 在群里像一个真实成员,而不是每次都像客服或问答机
|
||
- 能及时回答明确问题,减少“看见了但不接话”的情况
|
||
- 能根据群氛围决定什么时候主动参与,什么时候少说话
|
||
- 能对不同群、不同成员表现出稳定的人设和长期记忆感
|
||
- 能复用项目里已经存在的消息存档、成员画像、群总结、权限控制、后台管理能力
|
||
- 能处理“某个老成员很久不说话,突然回来发言”的场景,不显得失忆
|
||
|
||
这份文档不是泛泛而谈的产品介绍,而是基于当前仓库现状整理的一份可落地实现方案。
|
||
|
||
---
|
||
|
||
## 当前实现现状
|
||
|
||
当前插件入口:
|
||
|
||
- [`plugins/ai_auto_response/main.py`](/d:/learn/abot/plugins/ai_auto_response/main.py)
|
||
- [`plugins/ai_auto_response/bot_ai.py`](/d:/learn/abot/plugins/ai_auto_response/bot_ai.py)
|
||
- [`plugins/ai_auto_response/config.toml`](/d:/learn/abot/plugins/ai_auto_response/config.toml)
|
||
|
||
现有版本已经具备这些基础能力:
|
||
|
||
- 能监听群消息
|
||
- 能缓存最近一段群聊文本
|
||
- 能基于关键词、时间窗口、参与度、体力值决定是否插话
|
||
- 能把最近几条消息拼成上下文后调用大模型 API 生成回复
|
||
|
||
但它目前仍然偏简单,核心问题主要有:
|
||
|
||
1. 回复触发逻辑偏“概率型”
|
||
现在更像“有没有兴致插一句”,而不是“是否有人在明确问它问题”。
|
||
|
||
2. 缺少答疑优先级
|
||
群里一旦出现明确求助、@机器人、连续追问,应该优先快速答复,而不是继续走随机参与逻辑。
|
||
|
||
3. 缺少长期人格
|
||
目前只有 prompt 里的简短口语化约束,还没有稳定的人设、口头习惯、边界感、偏好表达方式。
|
||
|
||
4. 缺少成员级长期记忆
|
||
仓库里已经有成员画像能力,但 `ai_auto_response` 还没有接进去,所以机器人对“这个人平时怎么说话、关注什么、适合怎么回”没有利用起来。
|
||
|
||
5. 缺少群级场景区分
|
||
不同群应该有不同模式,例如技术群偏答疑、闲聊群偏陪聊、交易群偏信息明确、熟人群偏轻松互动。
|
||
|
||
6. 缺少回复分层
|
||
并不是所有回复都应该走同一条 prompt。问答、接梗、安慰、提醒、总结、纠错,生成策略应该分开。
|
||
|
||
---
|
||
|
||
## 可以直接复用的现有技术能力
|
||
|
||
这个项目其实已经有很多“拟人 BOT”需要的基础设施,不需要从零重造:
|
||
|
||
### 1. 消息接入与发送
|
||
|
||
- 主机器人入口:[`robot.py`](/d:/learn/abot/robot.py)
|
||
- 微信客户端:[`wechat_ipad/`](/d:/learn/abot/wechat_ipad)
|
||
|
||
可直接复用消息接收、发群消息、发图片、联系人同步、群成员信息读取能力。
|
||
|
||
### 2. 权限和群功能开关
|
||
|
||
- 群功能控制:`GroupBotManager`
|
||
|
||
这意味着“哪些群启用拟人 BOT”“哪些群仅答疑不闲聊”“哪些群完全关闭”都已经有基础能力。
|
||
|
||
### 3. 消息存档与历史上下文
|
||
|
||
- 消息存储:[`utils/wechat/message_to_db.py`](/d:/learn/abot/utils/wechat/message_to_db.py)
|
||
- 数据表操作:[`db/message_storage.py`](/d:/learn/abot/db/message_storage.py)
|
||
|
||
这部分非常关键,可以让 BOT 不只看最近 10 句话,而是按需回看更长的上下文。
|
||
|
||
### 4. 成员画像与长期交互记忆
|
||
|
||
- 插件:[`plugins/member_context/main.py`](/d:/learn/abot/plugins/member_context/main.py)
|
||
- 服务:[`plugins/member_context/service.py`](/d:/learn/abot/plugins/member_context/service.py)
|
||
- 提示词构建:[`plugins/member_context/prompt_builder.py`](/d:/learn/abot/plugins/member_context/prompt_builder.py)
|
||
|
||
这里已经有:
|
||
|
||
- 成员日 / 周 / 月摘要
|
||
- 兴趣主题
|
||
- 互动风格
|
||
- 回复偏好
|
||
- 群内角色
|
||
- 技能画像
|
||
|
||
这正是“拟人回复”最需要的长期上下文。
|
||
|
||
### 5. 群总结与压缩上下文
|
||
|
||
- 群总结:[`plugins/message_summary/main.py`](/d:/learn/abot/plugins/message_summary/main.py)
|
||
- 对话压缩:[`utils/compress_chat_data.py`](/d:/learn/abot/utils/compress_chat_data.py)
|
||
|
||
长群聊可以先压缩再喂给模型,减少 token 压力。
|
||
|
||
### 6. 管理后台
|
||
|
||
- 后台目录:[`admin/dashboard/`](/d:/learn/abot/admin/dashboard)
|
||
|
||
后续可以把“人设配置、群模式、回复频率、黑名单、禁聊时段、答疑策略”做成后台管理项。
|
||
|
||
---
|
||
|
||
## 新版本插件定位
|
||
|
||
建议把这个插件的定位改成:
|
||
|
||
`小牛:一个有稳定人格、会看场合、能优先答问题、在群里长期在线的虚拟群成员`
|
||
|
||
它不是纯陪聊,也不是纯问答助手,而是两种模式同时存在:
|
||
|
||
### 1. 拟人参与模式
|
||
|
||
适合熟人群、日常聊天群、兴趣群:
|
||
|
||
- 偶尔接话
|
||
- 顺着上下文说话
|
||
- 有自己的语气和偏好
|
||
- 不抢话,不刷屏
|
||
|
||
### 2. 实时答疑模式
|
||
|
||
适合技术群、项目群、问答群:
|
||
|
||
- 发现问题句、求助句、@机器人时优先响应
|
||
- 响应速度快于闲聊逻辑
|
||
- 回答尽量明确、可执行
|
||
- 不懂就直接说不确定,不硬编
|
||
|
||
---
|
||
|
||
## 推荐架构
|
||
|
||
建议把新版本拆成 8 个层次,而不是把所有逻辑都放在 `main.py` 里。
|
||
|
||
### 1. Message Intake
|
||
|
||
负责接收消息、标准化消息结构、过滤无效消息:
|
||
|
||
- 是否群聊
|
||
- 是否自己发的
|
||
- 是否文本 / 图片标题 / 链接卡片
|
||
- 是否命中黑名单
|
||
- 是否命中禁用群
|
||
|
||
### 2. Trigger Router
|
||
|
||
负责判断“为什么这次应该回”。
|
||
|
||
建议至少拆成以下触发源:
|
||
|
||
- `at_trigger`
|
||
`@bot` 或明确点名 BOT
|
||
|
||
- `question_trigger`
|
||
明显的问题句,例如“怎么弄”“有人知道吗”“这个报错啥意思”
|
||
|
||
- `followup_trigger`
|
||
上一轮已经在和 BOT 对话,用户继续追问
|
||
|
||
- `topic_trigger`
|
||
命中 BOT 擅长或关注的话题
|
||
|
||
- `social_trigger`
|
||
打招呼、起哄、接梗、点名、夸它、吐槽它
|
||
|
||
- `silence_break_trigger`
|
||
群里沉默较久后,用很轻的方式恢复气氛
|
||
|
||
其中优先级应为:
|
||
|
||
`@提问 > 明确求助 > 连续追问 > 互动点名 > 普通插话`
|
||
|
||
### 3. Flow Manager
|
||
|
||
心流系统是小牛的“实时参与状态机”。
|
||
|
||
它解决的不是“记不记得人”,而是“现在要不要继续聊、聊多深、聊多久”。
|
||
|
||
建议按群维度维护 `flow_state` 和 `flow_score`,而不是全局只有一个热度值。
|
||
|
||
推荐状态:
|
||
|
||
- `idle`
|
||
低参与,主要观察,除非被点名或明确提问,否则不主动插话
|
||
|
||
- `warming`
|
||
话题开始吸引小牛,可以做轻量接话
|
||
|
||
- `engaged`
|
||
已进入连续互动,优先接住上下文
|
||
|
||
- `deep_engaged`
|
||
正在进行高质量答疑或多人围绕同一主题连续互动
|
||
|
||
- `cooling`
|
||
一轮互动结束后逐步退出,避免刷屏
|
||
|
||
- `silent`
|
||
深夜、敏感话题、连续被忽略、系统限流时进入静默
|
||
|
||
建议影响心流的事件:
|
||
|
||
- 提高心流:
|
||
`@小牛`、明确提问、连续追问、命中擅长话题、老成员回归、机器人发言后有人接话
|
||
|
||
- 降低心流:
|
||
回复后无人接话、话题转移、连续回复过多、深夜、敏感话题、群里进入无关刷屏
|
||
|
||
建议先用简单的事件加减分模型:
|
||
|
||
- `@小牛`:`+40`
|
||
- 明确提问:`+30`
|
||
- 连续追问:`+20`
|
||
- 话题命中:`+15`
|
||
- 回归成员:`+10`
|
||
- 机器人发言后有人接话:`+15`
|
||
- 机器人发言后没人接话:`-20`
|
||
- 连续回复过多:`-15`
|
||
- 深夜:`-30`
|
||
|
||
建议状态阈值:
|
||
|
||
- `<20` -> `idle`
|
||
- `20~39` -> `warming`
|
||
- `40~69` -> `engaged`
|
||
- `>=70` -> `deep_engaged`
|
||
|
||
同时配合自然衰减,让心流值按分钟回落。
|
||
|
||
### 4. Context Builder
|
||
|
||
负责为本次回复准备上下文,建议分四层:
|
||
|
||
- 最近 20~50 条群消息
|
||
- 当天压缩摘要
|
||
- 当前发言人的成员画像
|
||
- 当前群的人设配置和行为模式
|
||
- 当前群的历史推断知识域和长期摘要
|
||
|
||
建议输出统一上下文对象:
|
||
|
||
```python
|
||
{
|
||
"group_profile": {},
|
||
"speaker_profile": {},
|
||
"recent_messages": [],
|
||
"recent_summary": "",
|
||
"trigger_type": "question_trigger",
|
||
"reply_mode": "qa_fast"
|
||
}
|
||
```
|
||
|
||
### 5. Long-Term Memory Engine
|
||
|
||
这是小牛和普通自动回复插件真正拉开差距的地方。
|
||
|
||
建议把记忆拆成四层,而不是只保留最近聊天记录:
|
||
|
||
- `session_memory`
|
||
最近一次连续对话的上下文,生命周期 5~15 分钟
|
||
|
||
- `daily_memory`
|
||
今天这个群在聊什么、谁和谁正在互动、当前气氛如何
|
||
|
||
- `member_memory`
|
||
某个成员长期关注的话题、典型说话风格、历史上经常问的问题、适合的回复方式
|
||
|
||
- `group_memory`
|
||
这个群的长期主题、说话节奏、禁忌、常见梗、对小牛的接受度
|
||
|
||
其中 `member_memory` 和 `group_memory` 是解决“老成员突然回归”最关键的部分。
|
||
|
||
`group_memory` 不只是存档,它还应该反过来影响回答偏向:
|
||
|
||
- 如果群已手工配置 `knowledge_domain`,优先使用配置
|
||
- 如果群没有明显配置,或者只是默认通用群,则允许用历史消息和群总结推断 `inferred_domain`
|
||
- 推断出的知识域只用于“理解问题时优先往哪边靠”,不是强制把任何话题都答成那个领域
|
||
|
||
例如:
|
||
|
||
- 一个没手工配置的群,最近长期都在聊机器人、插件、部署、接口,那小牛应自然偏向 `robotics`
|
||
- 一个群名没有 `openclaw`,但历史总结反复出现 OpenClaw 节点、接入、联调,那回答也可以优先从 OpenClaw 视角切入
|
||
- 如果只是普通闲聊群,哪怕偶尔有人发一条技术消息,也不应该立刻把整个群永久判成技术群
|
||
|
||
同样的逻辑也可以用于“社交风格推断”:
|
||
|
||
- 最近群消息长期偏玩梗、调侃、短句,小牛就可以更松一点
|
||
- 最近群消息长期偏项目推进、报错排查、接口联调,小牛就该明显收敛幽默感和毒舌度
|
||
- 这种推断只建议作为默认群画像的轻微偏置,不要覆盖明确手工配置
|
||
|
||
当某个成员很久没发言又突然出现时,不应该只看他刚发的这一句,而应该补充这些信息:
|
||
|
||
- 这个人上次活跃是什么时候
|
||
- 过去常聊什么
|
||
- 过去在群里的角色更像提问者、答疑者还是气氛组
|
||
- 过去和小牛是否有连续互动
|
||
- 这次回归是轻松冒泡、直接求助、还是延续旧话题
|
||
|
||
建议为这类场景增加专门状态:
|
||
|
||
- `returning_member`
|
||
7 天以上未发言后再次出现
|
||
|
||
- `long_absent_member`
|
||
30 天以上未发言后再次出现
|
||
|
||
- `reactivated_topic`
|
||
当前话题与该成员历史关注主题高度相关
|
||
|
||
针对这类状态,小牛的回复要遵循两个原则:
|
||
|
||
1. 记得这个人,但不要过度热情到像监控
|
||
可以自然表现出“你又出现了”“这个话题你之前也挺关注”,但不要直接说出太细的时间和行为记录。
|
||
|
||
2. 优先续接熟悉话题
|
||
如果该成员回归后直接提问,优先用他的长期主题和历史偏好组织答案,这样会更像“真的认识这个人”。
|
||
|
||
### 6. Persona Engine
|
||
|
||
这里是“拟人感”的核心,不应该只靠一句 prompt。
|
||
|
||
建议把人格拆成结构化配置:
|
||
|
||
- 名字
|
||
- 年龄感
|
||
- 说话风格
|
||
- 常用语气词
|
||
- 擅长话题
|
||
- 不擅长话题
|
||
- 回避边界
|
||
- 幽默程度
|
||
- 主动程度
|
||
- 回复长度偏好
|
||
- 是否喜欢反问
|
||
- 是否会使用表情
|
||
- 幽默强度
|
||
- 嘴硬 / 毒舌强度
|
||
- 表达松弛度
|
||
|
||
而且这些不应该全局固定,还应该允许按群覆盖。
|
||
|
||
也就是说,小牛的人设分两层:
|
||
|
||
- 底层稳定人格:技术宅、短句、嘴硬心软、懂代码硬件网络自动化,也懂一点 Dota
|
||
- 群内人格偏置:这个群里要不要更幽默、能不能更毒舌、是更认真还是更松弛
|
||
|
||
例如:
|
||
|
||
- 机器人群 / 项目群:幽默感压低,毒舌压低,优先认真答问题
|
||
- 闲聊群:允许多一点冷幽默和松弛感
|
||
- Dota 群:允许更自然的调侃和一点老玩家嘴臭味,但不能变成攻击性输出
|
||
|
||
建议新增独立人设文件,例如:
|
||
|
||
- `persona_name`
|
||
- `core_identity`
|
||
- `tone_rules`
|
||
- `reply_rules`
|
||
- `taboo_rules`
|
||
- `example_replies`
|
||
|
||
目录下现有的 [`plugins/ai_auto_response/瑞依.txt`](/d:/learn/abot/plugins/ai_auto_response/瑞依.txt) 只作为参考语料,不直接作为最终人格文件。
|
||
|
||
新版本应建立 `小牛` 的独立人格设定,建议固定为:
|
||
|
||
- 名字:小牛
|
||
- 角色感:群里常驻、靠谱、自然、不端着
|
||
- 回答风格:先解决问题,再决定要不要延伸
|
||
- 社交风格:熟人感轻一点,不装熟,不过分卖萌
|
||
- 记忆风格:对老成员有熟悉感,但不过度暴露“系统知道很多”
|
||
|
||
### 7. Response Planner
|
||
|
||
不要让模型每次自由发挥,先确定回复策略,再生成内容。
|
||
|
||
推荐回复模式:
|
||
|
||
- `qa_fast`
|
||
用于明确问题,答案优先,少废话
|
||
|
||
- `qa_with_context`
|
||
用于结合群聊历史、成员长期记忆或旧话题回答
|
||
|
||
- `social_short`
|
||
用于轻量接话,1 句就够
|
||
|
||
- `comfort_mode`
|
||
用于安慰、缓和、给建议
|
||
|
||
- `humor_mode`
|
||
用于熟人群轻松互动
|
||
|
||
- `refuse_or_skip`
|
||
不适合接话时直接不回,或仅给非常短的反馈
|
||
|
||
心流状态会直接影响回复策略:
|
||
|
||
- `idle`
|
||
只处理 `@bot`、明确问题、强触发事件
|
||
|
||
- `warming`
|
||
允许 `social_short`
|
||
|
||
- `engaged`
|
||
提高 `qa_with_context` 和连续追问的响应率
|
||
|
||
- `deep_engaged`
|
||
允许更完整的答疑和多轮连续互动
|
||
|
||
- `cooling`
|
||
优先短回复或收口
|
||
|
||
- `silent`
|
||
除非强触发,否则不回复
|
||
|
||
### 8. Safety and Rate Control
|
||
|
||
拟人 BOT 最大的风险不是“答不出来”,而是“太像人却太爱说话”。
|
||
|
||
所以必须保留这些机制:
|
||
|
||
- 每群独立冷却
|
||
- 连续回复衰减
|
||
- 被人无视后降低主动率
|
||
- 深夜低活跃模式
|
||
- 敏感词 / 风险话题降级
|
||
- 管理员强制关闭
|
||
|
||
当前 `bot_ai.py` 里的“体力值 + 参与度”可以保留,但应降级为“主动聊天限流器”,而不是总入口。
|
||
|
||
---
|
||
|
||
## 向量记忆设计
|
||
|
||
当前环境里已经有可用的向量能力:
|
||
|
||
- 向量库:`Qdrant`
|
||
- 向量模型服务:`Ollama`
|
||
- 适合接入位置:`Long-Term Memory Engine`
|
||
|
||
这里的设计原则不是“所有回复都查向量库”,而是:
|
||
|
||
`Qdrant 作为长期记忆召回层,member_context 和消息摘要作为稳定记忆层`
|
||
|
||
也就是说:
|
||
|
||
- `member_context`
|
||
负责回答“这个人是谁,长期是什么风格”
|
||
|
||
- `Qdrant`
|
||
负责回答“这个人以前聊过什么类似内容”
|
||
|
||
### 什么时候介入最合适
|
||
|
||
最合适的方式是第二阶段开始接入,但只用于特定场景,不作为所有回复的必经链路。
|
||
|
||
优先介入以下场景:
|
||
|
||
- `returning_member`
|
||
用户很久没发言后重新出现
|
||
|
||
- `long_absent_member`
|
||
用户长期沉默后突然出现
|
||
|
||
- `qa_with_context`
|
||
当前问题可能和历史问答或长期兴趣相关
|
||
|
||
- `reactivated_topic`
|
||
当前话题和用户过去长期关注主题高度相关
|
||
|
||
普通闲聊、轻量接话、气氛互动不建议默认查向量库。
|
||
|
||
### 为什么不建议一开始全量依赖向量库
|
||
|
||
因为群聊拟人 BOT 最怕的不是“想不起来”,而是“乱想起来”。
|
||
|
||
如果每次都查向量库,容易出现:
|
||
|
||
- 回复变慢
|
||
- 召回结果不稳定
|
||
- 机器人突然提旧事,像在翻聊天记录
|
||
- 轻松闲聊也被过度结构化
|
||
|
||
所以更合理的方式是:
|
||
|
||
- 平时主要依赖最近上下文和成员画像
|
||
- 需要“找回记忆”时再触发向量召回
|
||
|
||
### 最适合写入 Qdrant 的内容
|
||
|
||
不建议先把全部原始聊天消息无差别写进向量库。
|
||
|
||
更推荐写入“记忆单元”:
|
||
|
||
- 成员日摘要
|
||
- 成员周摘要
|
||
- 成员月摘要
|
||
- 群日摘要
|
||
- 重要问答对
|
||
- 用户长期偏好卡片
|
||
- 小牛与某成员的关键互动片段
|
||
|
||
这样做有几个好处:
|
||
|
||
- 噪音更少
|
||
- 召回更稳定
|
||
- Token 更省
|
||
- 更适合长期维护
|
||
|
||
### 推荐的 Qdrant Payload
|
||
|
||
每条向量建议至少带这些字段:
|
||
|
||
- `chatroom_id`
|
||
- `wxid`
|
||
- `memory_type`
|
||
- `topic_tags`
|
||
- `created_at`
|
||
- `last_active_at`
|
||
- `source_id`
|
||
- `content_summary`
|
||
|
||
建议的 `memory_type` 包括:
|
||
|
||
- `member_daily_digest`
|
||
- `member_weekly_digest`
|
||
- `member_monthly_digest`
|
||
- `group_daily_digest`
|
||
- `qa_pair`
|
||
- `interaction_memory`
|
||
- `preference_card`
|
||
|
||
### 推荐查询策略
|
||
|
||
建议按下面顺序查,而不是直接全库语义搜:
|
||
|
||
1. 先按 `chatroom_id` 过滤
|
||
2. 如果目标明确,再按 `wxid` 过滤
|
||
3. 再按 `memory_type` 过滤
|
||
4. 最后做语义相似度检索
|
||
5. `top_k` 建议先控制在 `3~5`
|
||
|
||
这能显著降低错召回。
|
||
|
||
### 与 Ollama 向量模型的配合方式
|
||
|
||
你现有的 Ollama 小向量模型是可以直接用的,只要满足一个原则:
|
||
|
||
`写入和查询必须使用同一个 embedding 模型`
|
||
|
||
对“小牛”这种群聊记忆系统来说,小型 embedding 模型反而通常更合适,因为需要的是:
|
||
|
||
- 响应快
|
||
- 成本低
|
||
- 稳定检索成员历史主题和问答片段
|
||
|
||
而不是做极重的通用语义推理。
|
||
|
||
### 推荐的接入方式
|
||
|
||
建议新增一个独立的记忆召回模块,例如:
|
||
|
||
- `memory_store.py`
|
||
负责写入、查询、过滤、召回排序
|
||
|
||
它的职责建议分成四块:
|
||
|
||
- `upsert_memory`
|
||
把摘要、问答、关键互动写入 Qdrant
|
||
|
||
- `search_member_memory`
|
||
查询某个成员的长期相关记忆
|
||
|
||
- `search_group_memory`
|
||
查询当前群的历史相关记忆
|
||
|
||
- `build_memory_prompt`
|
||
把召回结果压缩成可以送给模型的 prompt 片段
|
||
|
||
向量召回和心流系统的配合建议是:
|
||
|
||
- 长期记忆负责“这个人以前是谁、聊过什么”
|
||
- 心流系统负责“这次值不值得进入连续互动”
|
||
|
||
两者一起工作时,小牛才会既像“记得人”,又像“会看场合”。
|
||
|
||
### 小牛里最适合触发向量召回的时机
|
||
|
||
推荐在这些判断通过后才查 Qdrant:
|
||
|
||
- 用户超过 `7` 天未发言重新出现
|
||
- 用户超过 `30` 天未发言后提问
|
||
- 当前问题命中“历史上经常问的主题”
|
||
- 最近上下文不够,但成员长期画像显示该用户过去反复讨论过此类话题
|
||
- BOT 判断这是“旧话题延续”而不是新话题
|
||
|
||
### 记忆使用边界
|
||
|
||
向量召回的结果只应该作为“小牛知道哪些历史背景”的参考,而不是原样往外说。
|
||
|
||
生成回复时建议遵守:
|
||
|
||
- 不直接暴露精确历史记录
|
||
- 不直接说“你上次在几月几号说过”
|
||
- 不在轻量闲聊里强行提旧事
|
||
- 只在确实有帮助时,让回复带一点自然熟悉感
|
||
|
||
理想效果是:
|
||
|
||
- 用户觉得“小牛记得我”
|
||
- 但不会觉得“小牛在翻档案”
|
||
|
||
---
|
||
|
||
## 推荐实现方案
|
||
|
||
### 第一阶段:把“随机插话”升级成“有优先级的触发回复”
|
||
|
||
先不追求复杂人格,先解决“及时回答问题”:
|
||
|
||
1. 新增问题检测
|
||
识别问号、求助句式、报错句式、`有人知道`、`怎么`、`为啥`、`?`、`??`
|
||
|
||
2. 新增 `@bot` 强制响应
|
||
只要被明确点名,优先进入快速答疑链路
|
||
|
||
3. 新增会话延续窗口
|
||
机器人回复后 2~5 分钟内,如果同一人继续追问,应提高响应概率甚至直接响应
|
||
|
||
4. 闲聊逻辑与答疑逻辑分离
|
||
闲聊继续走拟人策略,答疑直接走高优先级策略
|
||
|
||
5. 引入群级心流系统
|
||
用 `flow_state` 替代旧的随机插话感,让小牛知道什么时候进入、什么时候退出对话
|
||
|
||
这一阶段完成后,体验会立刻提升很多。
|
||
|
||
### 第二阶段:接入长期记忆、成员画像和群模式
|
||
|
||
把仓库现有能力接进来:
|
||
|
||
1. 从 `member_context` 读取当前发言人的画像
|
||
2. 为每个成员建立最近会话缓存和长期记忆快照
|
||
3. 给“久未发言再次出现”的成员增加回归识别逻辑
|
||
4. 给不同群配置不同模式
|
||
5. 在 prompt 中加入“这个人平时更喜欢什么风格的回复”
|
||
6. 在技术群中提高问题响应率,在闲聊群中降低长篇回答频率
|
||
7. 在 `returning_member` 和 `qa_with_context` 场景接入 Qdrant 召回
|
||
8. 让回归成员和旧话题召回同时提升群级心流,进入更自然的连续互动状态
|
||
|
||
### 第三阶段:做人设稳定化
|
||
|
||
这一阶段重点不是“更聪明”,而是“像同一个人”:
|
||
|
||
1. 固化角色设定
|
||
2. 固化用词习惯
|
||
3. 固化情绪边界
|
||
4. 固化“知道什么 / 不知道什么”的表达方式
|
||
5. 给出少量 few-shot 回复样例
|
||
|
||
### 长期记忆专项:解决“很久不说话突然出现”的问题
|
||
|
||
这是新版本必须明确支持的场景。
|
||
|
||
推荐处理流程:
|
||
|
||
1. 识别用户是否为回归成员
|
||
根据消息库和成员画像判断其最近一次活跃时间
|
||
|
||
2. 如果是回归成员,额外加载长期记忆
|
||
包括历史关注主题、常见问题类型、群内角色、和小牛过去互动风格
|
||
|
||
3. 生成时增加“轻微熟悉感”
|
||
回复表现得像“记得这个人”,但不要像读档案
|
||
|
||
4. 如果该成员这次是来提问
|
||
则优先进入 `qa_with_context`,让回答带上他历史关注方向
|
||
|
||
5. 如果该成员只是冒泡
|
||
则只做轻量社交回应,不强行提旧事
|
||
|
||
一个好的感觉是:
|
||
|
||
- 用户会觉得“小牛好像一直在群里”
|
||
- 但不会觉得“小牛在偷偷监控每个人”
|
||
|
||
### 第四阶段:做后台配置化
|
||
|
||
建议把这些项做成可配置:
|
||
|
||
- 每个群是否启用
|
||
- 群模式
|
||
- 人设模板
|
||
- 回复频率
|
||
- 工作时间 / 静默时间
|
||
- 是否允许主动插话
|
||
- 是否允许使用表情
|
||
- 是否允许引用长期记忆
|
||
- 回归成员识别阈值
|
||
- 长期记忆回看天数
|
||
- 回归成员的回复热度上限
|
||
|
||
---
|
||
|
||
## 群聊 BOT 的最小落地版本
|
||
|
||
如果你希望先做一个能用的版本,而不是一次性重构太大,推荐最小实现如下:
|
||
|
||
### 必做
|
||
|
||
- 保留当前插件入口不变
|
||
- 新增 `trigger_type` 判定
|
||
- 新增 `flow_state` / `flow_score` 判定
|
||
- 新增 `reply_mode` 判定
|
||
- `@bot` / 提问类消息直接优先回复
|
||
- 上下文从最近 10 条提升到最近 20~30 条
|
||
- 人设文件从单段 prompt 改成结构化配置
|
||
|
||
### 优先做
|
||
|
||
- 接 `member_context`
|
||
- 给群配置模式
|
||
- 给回复加冷却和连续会话窗口
|
||
- 给回归成员场景接 Qdrant 召回
|
||
- 给不同心流状态配置不同回复强度
|
||
|
||
### 后续再做
|
||
|
||
- 后台管理页
|
||
- 不同人格模板
|
||
- 记忆纠偏
|
||
- 多模型路由
|
||
|
||
---
|
||
|
||
## 建议目录演进
|
||
|
||
建议把 `plugins/ai_auto_response/` 逐步整理成下面这种结构:
|
||
|
||
```text
|
||
plugins/ai_auto_response/
|
||
├── __init__.py
|
||
├── main.py # 插件入口,只做调度
|
||
├── config.toml # 插件配置
|
||
├── README.md # 本文档
|
||
├── persona/
|
||
│ ├── xiaoniu.txt
|
||
│ └── tech_helper.txt
|
||
├── flow_manager.py # 群级心流状态机
|
||
├── memory_store.py # 长期记忆读取与装配
|
||
├── vector_memory.py # Qdrant / Ollama 召回层
|
||
├── triggers.py # 触发判定
|
||
├── context_builder.py # 上下文构建
|
||
├── persona_engine.py # 人设装配
|
||
├── response_planner.py # 回复策略选择
|
||
├── llm_client.py # OpenAI兼容 API / 其他模型调用
|
||
└── rate_control.py # 冷却、频率、主动度控制
|
||
```
|
||
|
||
这样以后维护会比现在轻松很多。
|
||
|
||
---
|
||
|
||
## 建议配置项
|
||
|
||
建议在 `config.toml` 后续补充这些内容:
|
||
|
||
```toml
|
||
enable = true
|
||
|
||
[mode]
|
||
group_default_mode = "social"
|
||
question_reply_timeout_sec = 12
|
||
followup_session_window_sec = 300
|
||
recent_context_size = 30
|
||
allow_proactive_reply = true
|
||
returning_member_days = 7
|
||
long_absent_member_days = 30
|
||
memory_lookback_days = 180
|
||
|
||
[flow]
|
||
enable_flow_state = true
|
||
flow_decay_per_minute = 8
|
||
idle_threshold = 20
|
||
warming_threshold = 40
|
||
engaged_threshold = 70
|
||
at_bot_boost = 40
|
||
question_boost = 30
|
||
followup_boost = 20
|
||
topic_boost = 15
|
||
returning_member_boost = 10
|
||
response_accepted_boost = 15
|
||
ignored_reply_penalty = 20
|
||
over_reply_penalty = 15
|
||
night_penalty = 30
|
||
|
||
[persona]
|
||
name = "小牛"
|
||
style = "自然、口语化、像群友"
|
||
emoji_probability = 0.25
|
||
max_reply_sentences = 3
|
||
|
||
[memory]
|
||
enable_vector_memory = true
|
||
vector_provider = "qdrant"
|
||
embedding_provider = "ollama"
|
||
qdrant_url = "http://127.0.0.1:6333"
|
||
qdrant_collection = "abot_xiaoniu_memory"
|
||
ollama_base_url = "http://192.168.2.50:11434"
|
||
embedding_model = "your_embedding_model"
|
||
vector_top_k = 5
|
||
vector_min_score = 0.65
|
||
vector_trigger_modes = ["returning_member", "long_absent_member", "qa_with_context", "reactivated_topic"]
|
||
|
||
[priority]
|
||
at_bot = 1.0
|
||
explicit_question = 0.95
|
||
followup = 0.9
|
||
social_call = 0.65
|
||
casual_topic = 0.35
|
||
|
||
[cooldown]
|
||
group_reply_cooldown_sec = 45
|
||
same_user_followup_cooldown_sec = 10
|
||
night_silent_hours = ["01:00-07:30"]
|
||
```
|
||
|
||
---
|
||
|
||
## Prompt 设计建议
|
||
|
||
新版本 prompt 不建议再只写“简短、口语化”这种通用要求,而要明确四件事:
|
||
|
||
1. 你是谁
|
||
你在这个群里的身份、语气、边界、说话节奏
|
||
|
||
2. 你为什么这次要回复
|
||
是因为被 @、被提问、正在连续对话、还是轻微接话,以及当前心流状态是否支持继续参与
|
||
|
||
3. 你现在掌握了什么上下文
|
||
最近群聊、成员画像、长期记忆、群模式、心流状态、历史摘要
|
||
|
||
4. 这次回复的目标
|
||
是回答问题、接一句、安慰、澄清、提醒,还是保持沉默
|
||
|
||
建议最终 prompt 由以下片段拼装:
|
||
|
||
- `system_persona`
|
||
- `memory_prompt`
|
||
- `group_mode_prompt`
|
||
- `flow_prompt`
|
||
- `speaker_profile_prompt`
|
||
- `trigger_prompt`
|
||
- `recent_context_prompt`
|
||
- `response_rule_prompt`
|
||
|
||
其中:
|
||
|
||
- `memory_prompt`
|
||
优先来自 `member_context` 的稳定画像
|
||
|
||
- `vector_memory_prompt`
|
||
只在命中特定场景时从 Qdrant 召回并追加
|
||
|
||
---
|
||
|
||
## 成功标准
|
||
|
||
如果这个插件升级成功,应该能达到下面这些效果:
|
||
|
||
### 拟人感
|
||
|
||
- 说话前后风格一致
|
||
- 不会每次都像在写标准答案
|
||
- 会看群气氛,不乱抢话
|
||
- 被调侃时能自然接住
|
||
- 会自然进入和退出对话,不会像开关一样突兀
|
||
|
||
### 答疑能力
|
||
|
||
- 被 @ 时基本能及时回复
|
||
- 明确问题能优先答复
|
||
- 回答比现在更聚焦、更短、更有执行性
|
||
- 不确定时会明确说明
|
||
|
||
### 长期记忆
|
||
|
||
- 对活跃成员和沉默很久后回归的成员都能保持连续感
|
||
- 不会把短期状态误认为长期人格
|
||
- 能识别老成员的长期关注主题
|
||
- 回归成员发言时,小牛的回复会有自然熟悉感
|
||
- Qdrant 召回只在需要时介入,不会让普通闲聊变得迟钝和奇怪
|
||
|
||
### 工程可维护性
|
||
|
||
- 触发逻辑、上下文逻辑、生成逻辑分层
|
||
- 心流逻辑独立成层,不和长期记忆混在一起
|
||
- 可接入成员画像
|
||
- 可配置不同群模式
|
||
- 可通过后台持续调参
|
||
|
||
---
|
||
|
||
## 推荐开发顺序
|
||
|
||
1. 保留当前插件名和入口,先完成触发路由重构
|
||
2. 把群级心流系统做出来,替换旧的随机插话逻辑
|
||
3. 把“答疑优先”做出来,解决及时回复问题
|
||
4. 把长期记忆层接进来,先解决回归成员场景
|
||
5. 把人设配置从自由文本升级成结构化配置,并固定为小牛
|
||
6. 接入 `member_context` 做成员级回复优化
|
||
7. 接入 Qdrant + Ollama,先只服务回归成员和旧话题召回
|
||
8. 增加群模式配置
|
||
9. 最后再做后台配置和更细的人格控制
|
||
|
||
---
|
||
|
||
## 一句话结论
|
||
|
||
你现在这个 `ai_auto_response` 已经有“群里自动说话”的雏形了,但如果目标是“小牛”这种真正长期在线的群聊拟人 BOT,核心不在于继续调概率,而在于把它升级成:
|
||
|
||
`触发有优先级、心流会收放、上下文有层次、长期记忆可用、人格固定为小牛、答疑能优先、群模式可配置`
|
||
|
||
这样它才会既像群友,又真的有用。
|