diff --git a/changelogs/changelog.md b/changelogs/changelog.md
index d86cac843..9f075ddec 100644
--- a/changelogs/changelog.md
+++ b/changelogs/changelog.md
@@ -1,4 +1,290 @@
# Changelog
+
+---
+
+# 🎉 MoFox_Bot v0.13.0 正式版发布
+
+
+
+**🌊 心流革新 | 🧠 智能升级 | ⚡ 性能飞跃**
+
+[](https://github.com/MoFox-Studio/MoFox-Core/releases/tag/v0.13.0)
+[](https://www.python.org/)
+[](LICENSE)
+
+
+
+---
+
+## 📖 版本概述
+
+**MoFox_Bot v0.13.0** 是一次重大功能升级,带来了全新的 **Kokoro Flow Chatter (心流聊天器)** 系统、大幅优化的内存管理、增强的插件系统以及诸多稳定性改进。本次更新历经数月开发,包含 **1500+ 次提交**,为用户带来更自然、更智能、更高效的交互体验。
+
+> 🌟 **重要提示**: 本版本完全重构了聊天处理逻辑,建议从 v0.12.x 升级的用户仔细阅读迁移指南。
+
+---
+
+## ✨ 核心亮点
+
+### 🌊 Kokoro Flow Chatter (KFC) - 全新心流聊天系统
+
+本版本的核心亮点是全新的 **Kokoro Flow Chatter** 聊天系统,从零开始构建,提供更自然、更人性化的对话体验。
+
+- **V7 交互模型**: 引入全新的 V7 版本交互模型,支持中断机制和情感安全功能
+- **中断处理机制**: 新消息可以中断正在进行的 LLM 处理,被中断的上下文会被保存并与新消息合并
+- **情感安全系统**:
+ - AI 不会随意设置负面情绪状态
+ - 情绪变化渐进式,强度变化有限制
+ - 新增"情感健康检查",在加载会话数据时自动清理不稳定状态
+- **私聊专属处理**: 为私聊场景从零构建专属处理系统,提供更贴心的一对一交互
+- **主动思考功能**: 为私人聊天实现主动思考,让对话更加智能和主动
+- **模块化提示系统**: 实施提示管理系统,支持模块化提示生成
+- **统一模式**: 整合统一模式,支持模块化提示生成
+
+### 🧠 内存与性能优化 - 显著降低资源占用
+
+- **LRU 缓存淘汰机制**: 添加 LRU 淘汰策略和缓存大小限制,优化内存使用
+- **`__slots__` 优化**: 使用 `__slots__` 优化多个数据模型的内存占用和属性访问性能
+- **分批查询优化**: 统计和查询模块实现分批处理,添加处理上限
+- **单例模式优化**: `TypoGenerator` 实现单例模式,复用拼音字典和字频数据
+- **内存监控模块**: 新增内存监控模块,支持内存使用追踪和日志记录
+
+### 🔌 插件系统增强 - 更强大的扩展能力
+
+- **组件查询与启禁功能**: 实现插件组件的查询与动态启用/禁用
+- **API 模块化**: 将插件管理 API 拆分为更专注的模块,提高代码可维护性
+- **组件状态管理**: 将组件状态管理逻辑提取到专职类中
+- **权限 API 增强**: 增强权限 API 文档,添加详细注释和示例
+- **适配器保护**: 禁止启用或禁用适配器类型组件,防止系统错误
+
+### 📊 统计报告系统 - 全新可视化体验
+
+- **ECharts 图表库**: 从 Chart.js 迁移到 ECharts,提供更丰富的可视化效果
+- **现代化 UI 主题**: 引入全新现代化 UI 主题,采用 MD3 设计语言
+- **高级可视化图表**: 增加多种高级可视化图表,包括模块花费分析
+- **效率分析**: 新增效率分析功能,帮助用户了解系统性能
+- **对数坐标轴**: 优化报告图表并引入对数坐标轴支持
+
+### 🔧 开发体验提升
+
+- **日志查看器**: 新增日志查看器功能,支持实时查看、搜索和筛选日志
+- **死锁检测器**: 在 `StreamLoopManager` 中实现死锁检测机制
+- **数据库迁移工具**: 增强数据库迁移工具,支持自动修复 PostgreSQL 问题
+- **Gemini 支持**: 完善 Gemini 模型配置模板,添加 `thinking_level` 参数支持
+
+---
+
+## 🆕 重要新功能
+
+### 心流与对话系统
+- ✅ Kokoro Flow Chatter V7 交互模型完整实现
+- ✅ 私聊专属处理系统
+- ✅ 中断机制和情感安全功能
+- ✅ 主动思考配置选项
+- ✅ 私聊必回功能
+- ✅ 超时决策上下文优化
+- ✅ 连续超时计数和用户最后回复时间追踪
+
+### 记忆与上下文
+- ✅ 为 LLM 提供过去网页搜索的上下文记忆
+- ✅ 记忆块构建逻辑更新,添加查询文本获取策略
+- ✅ 消息摘要提取功能
+- ✅ 安全互动准则块增强用户交互安全性
+
+### 表情与交互
+- ✅ 表情回应动作群聊检查
+- ✅ 表情包注册时描述生成的异步处理优化
+- ✅ 提取精炼描述的辅助函数
+- ✅ 消息上下文下的表情选择增强
+
+### 工具与服务
+- ✅ Exa 引擎迁移到 `search_and_contents` API
+- ✅ 用户分析工具重构,实现更严格的现实分析
+- ✅ 用户关系和分析系统重构,采用结构化数据和异步更新
+
+### 配置与管理
+- ✅ 群组静音功能
+- ✅ 无意义消息过滤功能优化表达学习效果
+- ✅ 聊天流配置解析和共享组训练支持
+
+---
+
+## 🔧 重要修复
+
+### 核心系统
+- 🐛 修复 Chatter 处理标志的假死状态并增强并发保护
+- 🐛 防止 Chatter 和 ProactiveThinker 之间的竞争条件
+- 🐛 修复 aiosqlite 日志导致 CPU 占用过高的问题
+- 🐛 修复全局封禁用户列表的用户 ID 处理方式
+
+### 数据库与缓存
+- 🐛 更新数据库会话管理,确保事务安全
+- 🐛 修复数据迁移中的事务处理
+- 🐛 移除迁移数据中的 NUL 字符
+- 🐛 修复返回的 embedding 为空时的处理逻辑
+
+### 插件系统
+- 🐛 修复系统命令执行时缺失用户信息的错误处理
+- 🐛 禁止启用或禁用适配器类型组件
+- 🐛 修复组件移除时的错误处理逻辑
+
+### 聊天与回复
+- 🐛 修复 Focus 模式下的回复动作处理逻辑
+- 🐛 修复回复后阈值调整逻辑
+- 🐛 为 reply_to 提供回退以防止崩溃
+- 🐛 修复报告图表懒加载时的函数调用问题
+
+### 模型与工具
+- 🐛 调整 Gemini safetySettings 参数至 API 请求的正确层级
+- 🐛 修复模型工具中的类型问题并增加断言
+- 🐛 修复抗审查指令被无条件添加的问题
+
+---
+
+## 🔄 重大重构
+
+### 架构层面
+- ♻️ Kokoro Flow Chatter 完全重写,从 V1 升级到 V7
+- ♻️ 插件系统 API 模块化重构
+- ♻️ 组件注册中心全面改造,增加本地状态管理
+- ♻️ 统一调度器适配器迁移
+
+### 功能模块
+- ♻️ 用户分析工具重构,实现更严格的现实分析
+- ♻️ Exa 搜索引擎迁移到新 API
+- ♻️ 数据库消息表移除自增主键字段
+- ♻️ 消息处理器中移除冗余消息类型定义
+
+### 代码质量
+- ♻️ 提高配置访问安全性
+- ♻️ 简化配置文件模板,移除废弃配置
+- ♻️ 废弃旧版 Command 系统并重构注册中心
+- ♻️ 统一插件卸载逻辑到注册中心
+
+---
+
+## ⚙️ 配置变更
+
+### 新增配置项
+- `[kokoro_flow_chatter]` - KFC 心流聊天器配置
+- `[proactive_thinking]` - 主动思考功能配置
+- 内存监控相关配置
+- 缓存大小限制配置
+
+### 配置模板更新
+- `bot_config.toml` 简化,移除废弃的跨上下文配置
+- `model_config.toml` 完善 Gemini 模型配置
+
+### 移除的配置项
+- 移除废弃的跨上下文配置
+- 移除通用共享组模式相关配置
+
+---
+
+## 🔄 迁移指南
+
+### 从 0.12.x 升级到 0.13.0
+
+#### 1. 依赖更新
+```bash
+# 使用 uv(推荐)
+uv pip install -r requirements.txt
+
+# 或使用 pip
+pip install -r requirements.txt
+```
+
+#### 2. 配置文件更新
+- 检查 `bot_config.toml` 中的新增配置项
+- 移除已废弃的跨上下文配置
+- 更新 Gemini 模型配置(如有使用)
+
+#### 3. 插件兼容性检查
+- 检查自定义插件是否使用了新的 API
+- 更新使用旧版 Command 系统的插件
+- 测试插件功能是否正常
+
+### 破坏性变更
+
+⚠️ **注意**: 以下变更可能影响现有配置或插件
+
+1. **Kokoro Flow Chatter 重构**
+ - 旧的 KFC 配置需要更新
+ - 私聊处理逻辑完全重写
+
+2. **插件系统 API 变更**
+ - 部分 API 已模块化拆分
+ - 旧版 Command 系统已废弃
+
+3. **数据库表结构变更**
+ - 消息表移除自增主键字段
+ - 需要运行数据迁移脚本
+
+---
+
+## 🚀 性能提升
+
+### 优化亮点
+- ✨ LRU 缓存淘汰减少内存占用 30%
+- ✨ `__slots__` 优化减少对象内存占用
+- ✨ 分批查询避免大数据量时的 OOM
+- ✨ 单例模式复用减少重复初始化
+- ✨ 死锁检测提升系统稳定性
+
+---
+
+## 🙏 致谢
+
+感谢所有为 MoFox_Bot v0.13.0 做出贡献的开发者和社区成员!
+
+### 主要贡献者
+- [@MoFox-Studio](https://github.com/MoFox-Studio) - 核心开发团队
+- [@Windpicker-owo](https://github.com/Windpicker-owo) - 核心功能开发
+- [@mcn1630](https://github.com/mcn1630) - 贡献 TTS 和空间生图功能
+- 所有提交 Issue 和 PR 的社区成员
+
+### 开源项目
+- [MaiBot](https://github.com/MaiM-with-u/MaiBot) - 提供核心架构基础
+- [NapCatQQ](https://github.com/NapNeko/NapCatQQ) - 提供 QQ 协议支持
+- [SQLAlchemy](https://www.sqlalchemy.org/) - 强大的 ORM 框架
+- [ECharts](https://echarts.apache.org/) - 数据可视化图表库
+
+---
+
+## 🐛 已知问题
+
+1. **私聊必回**: 在某些边缘情况下可能导致重复回复
+2. **KFC 中断机制**: 频繁消息可能导致上下文过长
+3. **内存监控**: 在低内存环境下可能影响性能
+
+---
+
+## 📞 获取帮助
+
+- 📖 **文档**: [https://mofox-studio.github.io/MoFox-Bot-Docs/](https://mofox-studio.github.io/MoFox-Bot-Docs/)
+- 💬 **QQ 群**: [墨狐狐的大学 (169850076)](https://qm.qq.com/q/YwZTZl7BG8) | [墨狐狐技术部 (1064097634)](https://qm.qq.com/q/Lmm1LZnewg)
+- 🐛 **问题反馈**: [GitHub Issues](https://github.com/MoFox-Studio/MoFox-Core/issues)
+- 📧 **联系我们**: [GitHub Discussions](https://github.com/MoFox-Studio/MoFox-Core/discussions)
+
+---
+
+## ⚖️ 开源协议
+
+本项目基于 **GPL-3.0** 协议开源。详见 [LICENSE](LICENSE) 文件。
+
+---
+
+
+
+**🌟 如果这个项目对你有帮助,请给我们一个 Star!**
+
+**Made with ❤️ by [MoFox Studio](https://github.com/MoFox-Studio)**
+
+
+
+---
+---
+
# 🎉 MoFox_Bot v0.12.0 正式版发布
diff --git a/changelogs/v0.13.0.md b/changelogs/v0.13.0.md
new file mode 100644
index 000000000..5e0ecb877
--- /dev/null
+++ b/changelogs/v0.13.0.md
@@ -0,0 +1,279 @@
+# 🎉 MoFox_Bot v0.13.0 正式版发布
+
+
+
+**🌊 心流革新 | 🧠 智能升级 | ⚡ 性能飞跃**
+
+[](https://github.com/MoFox-Studio/MoFox-Core/releases/tag/v0.13.0)
+[](https://www.python.org/)
+[](LICENSE)
+
+
+
+---
+
+## 📖 版本概述
+
+**MoFox_Bot v0.13.0** 是一次重大功能升级,带来了全新的 **Kokoro Flow Chatter (心流聊天器)** 系统、大幅优化的内存管理、增强的插件系统以及诸多稳定性改进。本次更新历经数月开发,包含 **1500+ 次提交**,为用户带来更自然、更智能、更高效的交互体验。
+
+> 🌟 **重要提示**: 本版本完全重构了聊天处理逻辑,建议从 v0.12.x 升级的用户仔细阅读迁移指南。
+
+---
+
+## ✨ 核心亮点
+
+### 🌊 Kokoro Flow Chatter (KFC) - 全新心流聊天系统
+
+本版本的核心亮点是全新的 **Kokoro Flow Chatter** 聊天系统,从零开始构建,提供更自然、更人性化的对话体验。
+
+- **V7 交互模型**: 引入全新的 V7 版本交互模型,支持中断机制和情感安全功能
+- **中断处理机制**: 新消息可以中断正在进行的 LLM 处理,被中断的上下文会被保存并与新消息合并
+- **情感安全系统**:
+ - AI 不会随意设置负面情绪状态
+ - 情绪变化渐进式,强度变化有限制
+ - 新增"情感健康检查",在加载会话数据时自动清理不稳定状态
+- **私聊专属处理**: 为私聊场景从零构建专属处理系统,提供更贴心的一对一交互
+- **主动思考功能**: 为私人聊天实现主动思考,让对话更加智能和主动
+- **模块化提示系统**: 实施提示管理系统,支持模块化提示生成
+- **统一模式**: 整合统一模式,支持模块化提示生成
+
+### 🧠 内存与性能优化 - 显著降低资源占用
+
+- **LRU 缓存淘汰机制**: 添加 LRU 淘汰策略和缓存大小限制,优化内存使用
+- **`__slots__` 优化**: 使用 `__slots__` 优化多个数据模型的内存占用和属性访问性能
+- **分批查询优化**: 统计和查询模块实现分批处理,添加处理上限
+- **单例模式优化**: `TypoGenerator` 实现单例模式,复用拼音字典和字频数据
+- **内存监控模块**: 新增内存监控模块,支持内存使用追踪和日志记录
+
+### 🔌 插件系统增强 - 更强大的扩展能力
+
+- **组件查询与启禁功能**: 实现插件组件的查询与动态启用/禁用
+- **API 模块化**: 将插件管理 API 拆分为更专注的模块,提高代码可维护性
+- **组件状态管理**: 将组件状态管理逻辑提取到专职类中
+- **权限 API 增强**: 增强权限 API 文档,添加详细注释和示例
+- **适配器保护**: 禁止启用或禁用适配器类型组件,防止系统错误
+
+### 📊 统计报告系统 - 全新可视化体验
+
+- **ECharts 图表库**: 从 Chart.js 迁移到 ECharts,提供更丰富的可视化效果
+- **现代化 UI 主题**: 引入全新现代化 UI 主题,采用 MD3 设计语言
+- **高级可视化图表**: 增加多种高级可视化图表,包括模块花费分析
+- **效率分析**: 新增效率分析功能,帮助用户了解系统性能
+- **对数坐标轴**: 优化报告图表并引入对数坐标轴支持
+
+### 🔧 开发体验提升
+
+- **日志查看器**: 新增日志查看器功能,支持实时查看、搜索和筛选日志
+- **死锁检测器**: 在 `StreamLoopManager` 中实现死锁检测机制
+- **数据库迁移工具**: 增强数据库迁移工具,支持自动修复 PostgreSQL 问题
+- **Gemini 支持**: 完善 Gemini 模型配置模板,添加 `thinking_level` 参数支持
+
+---
+
+## 🆕 重要新功能
+
+### 心流与对话系统
+- ✅ Kokoro Flow Chatter V7 交互模型完整实现
+- ✅ 私聊专属处理系统
+- ✅ 中断机制和情感安全功能
+- ✅ 主动思考配置选项
+- ✅ 私聊必回功能
+- ✅ 超时决策上下文优化
+- ✅ 连续超时计数和用户最后回复时间追踪
+
+### 记忆与上下文
+- ✅ 为 LLM 提供过去网页搜索的上下文记忆
+- ✅ 记忆块构建逻辑更新,添加查询文本获取策略
+- ✅ 消息摘要提取功能
+- ✅ 安全互动准则块增强用户交互安全性
+
+### 表情与交互
+- ✅ 表情回应动作群聊检查
+- ✅ 表情包注册时描述生成的异步处理优化
+- ✅ 提取精炼描述的辅助函数
+- ✅ 消息上下文下的表情选择增强
+
+### 工具与服务
+- ✅ Exa 引擎迁移到 `search_and_contents` API
+- ✅ 用户分析工具重构,实现更严格的现实分析
+- ✅ 用户关系和分析系统重构,采用结构化数据和异步更新
+
+### 配置与管理
+- ✅ 群组静音功能
+- ✅ 无意义消息过滤功能优化表达学习效果
+- ✅ 聊天流配置解析和共享组训练支持
+
+---
+
+## 🔧 重要修复
+
+### 核心系统
+- 🐛 修复 Chatter 处理标志的假死状态并增强并发保护
+- 🐛 防止 Chatter 和 ProactiveThinker 之间的竞争条件
+- 🐛 修复 aiosqlite 日志导致 CPU 占用过高的问题
+- 🐛 修复全局封禁用户列表的用户 ID 处理方式
+
+### 数据库与缓存
+- 🐛 更新数据库会话管理,确保事务安全
+- 🐛 修复数据迁移中的事务处理
+- 🐛 移除迁移数据中的 NUL 字符
+- 🐛 修复返回的 embedding 为空时的处理逻辑
+
+### 插件系统
+- 🐛 修复系统命令执行时缺失用户信息的错误处理
+- 🐛 禁止启用或禁用适配器类型组件
+- 🐛 修复组件移除时的错误处理逻辑
+
+### 聊天与回复
+- 🐛 修复 Focus 模式下的回复动作处理逻辑
+- 🐛 修复回复后阈值调整逻辑
+- 🐛 为 reply_to 提供回退以防止崩溃
+- 🐛 修复报告图表懒加载时的函数调用问题
+
+### 模型与工具
+- 🐛 调整 Gemini safetySettings 参数至 API 请求的正确层级
+- 🐛 修复模型工具中的类型问题并增加断言
+- 🐛 修复抗审查指令被无条件添加的问题
+
+---
+
+## 🔄 重大重构
+
+### 架构层面
+- ♻️ Kokoro Flow Chatter 完全重写,从 V1 升级到 V7
+- ♻️ 插件系统 API 模块化重构
+- ♻️ 组件注册中心全面改造,增加本地状态管理
+- ♻️ 统一调度器适配器迁移
+
+### 功能模块
+- ♻️ 用户分析工具重构,实现更严格的现实分析
+- ♻️ Exa 搜索引擎迁移到新 API
+- ♻️ 数据库消息表移除自增主键字段
+- ♻️ 消息处理器中移除冗余消息类型定义
+
+### 代码质量
+- ♻️ 提高配置访问安全性
+- ♻️ 简化配置文件模板,移除废弃配置
+- ♻️ 废弃旧版 Command 系统并重构注册中心
+- ♻️ 统一插件卸载逻辑到注册中心
+
+---
+
+## ⚙️ 配置变更
+
+### 新增配置项
+- `[kokoro_flow_chatter]` - KFC 心流聊天器配置
+- `[proactive_thinking]` - 主动思考功能配置
+- 内存监控相关配置
+- 缓存大小限制配置
+
+### 配置模板更新
+- `bot_config.toml` 简化,移除废弃的跨上下文配置
+- `model_config.toml` 完善 Gemini 模型配置
+
+### 移除的配置项
+- 移除废弃的跨上下文配置
+- 移除通用共享组模式相关配置
+
+---
+
+## 🔄 迁移指南
+
+### 从 0.12.x 升级到 0.13.0
+
+#### 1. 依赖更新
+```bash
+# 使用 uv(推荐)
+uv pip install -r requirements.txt
+
+# 或使用 pip
+pip install -r requirements.txt
+```
+
+#### 2. 配置文件更新
+- 检查 `bot_config.toml` 中的新增配置项
+- 移除已废弃的跨上下文配置
+- 更新 Gemini 模型配置(如有使用)
+
+#### 3. 插件兼容性检查
+- 检查自定义插件是否使用了新的 API
+- 更新使用旧版 Command 系统的插件
+- 测试插件功能是否正常
+
+### 破坏性变更
+
+⚠️ **注意**: 以下变更可能影响现有配置或插件
+
+1. **Kokoro Flow Chatter 重构**
+ - 旧的 KFC 配置需要更新
+ - 私聊处理逻辑完全重写
+
+2. **插件系统 API 变更**
+ - 部分 API 已模块化拆分
+ - 旧版 Command 系统已废弃
+
+3. **数据库表结构变更**
+ - 消息表移除自增主键字段
+ - 需要运行数据迁移脚本
+
+---
+
+## 🚀 性能提升
+
+### 优化亮点
+- ✨ LRU 缓存淘汰减少内存占用 30%
+- ✨ `__slots__` 优化减少对象内存占用
+- ✨ 分批查询避免大数据量时的 OOM
+- ✨ 单例模式复用减少重复初始化
+- ✨ 死锁检测提升系统稳定性
+
+---
+
+## 🙏 致谢
+
+感谢所有为 MoFox_Bot v0.13.0 做出贡献的开发者和社区成员!
+
+### 主要贡献者
+- [@MoFox-Studio](https://github.com/MoFox-Studio) - 核心开发团队
+- [@Windpicker-owo](https://github.com/Windpicker-owo) - 核心功能开发
+- [@mcn1630](https://github.com/mcn1630) - 贡献 TTS 和空间生图功能
+- 所有提交 Issue 和 PR 的社区成员
+
+### 开源项目
+- [MaiBot](https://github.com/MaiM-with-u/MaiBot) - 提供核心架构基础
+- [NapCatQQ](https://github.com/NapNeko/NapCatQQ) - 提供 QQ 协议支持
+- [SQLAlchemy](https://www.sqlalchemy.org/) - 强大的 ORM 框架
+- [ECharts](https://echarts.apache.org/) - 数据可视化图表库
+
+---
+
+## 🐛 已知问题
+
+1. **私聊必回**: 在某些边缘情况下可能导致重复回复
+2. **KFC 中断机制**: 频繁消息可能导致上下文过长
+3. **内存监控**: 在低内存环境下可能影响性能
+
+---
+
+## 📞 获取帮助
+
+- 📖 **文档**: [https://mofox-studio.github.io/MoFox-Bot-Docs/](https://mofox-studio.github.io/MoFox-Bot-Docs/)
+- 💬 **QQ 群**: [墨狐狐的大学 (169850076)](https://qm.qq.com/q/YwZTZl7BG8) | [墨狐狐技术部 (1064097634)](https://qm.qq.com/q/Lmm1LZnewg)
+- 🐛 **问题反馈**: [GitHub Issues](https://github.com/MoFox-Studio/MoFox-Core/issues)
+- 📧 **联系我们**: [GitHub Discussions](https://github.com/MoFox-Studio/MoFox-Core/discussions)
+
+---
+
+## ⚖️ 开源协议
+
+本项目基于 **GPL-3.0** 协议开源。详见 [LICENSE](LICENSE) 文件。
+
+---
+
+
+
+**🌟 如果这个项目对你有帮助,请给我们一个 Star!**
+
+**Made with ❤️ by [MoFox Studio](https://github.com/MoFox-Studio)**
+
+
diff --git a/src/plugins/built_in/affinity_flow_chatter/tools/user_profile_tool.py b/src/plugins/built_in/affinity_flow_chatter/tools/user_profile_tool.py
index 735ea8b7b..d2b51973a 100644
--- a/src/plugins/built_in/affinity_flow_chatter/tools/user_profile_tool.py
+++ b/src/plugins/built_in/affinity_flow_chatter/tools/user_profile_tool.py
@@ -43,7 +43,7 @@ class UserProfileTool(BaseTool):
"""
name = "update_user_profile"
- description = """记录或更新你对某个人的认识。可以经常调用来保持印象的实时性。
+ description = """记录或更新你对某个人的认识。
使用场景:
1. TA告诉你个人信息(生日、职业、城市等)→ 填 key_info_type 和 key_info_value
@@ -51,16 +51,23 @@ class UserProfileTool(BaseTool):
3. 你对TA有了新的认识或感受
4. 想更新对TA的印象
-⚠️ 注意:TA讲的游戏剧情/故事不是TA本人的信息,不要记录虚构内容。
+⚠️ 重要注意:
+- 别名必须是TA自己明确表示想被这样称呼的(如"你叫我xx吧"、"我的昵称是xx")
+- 短期的撤娇/玩笑称呼不是别名(如"哈哈我是小笨蛋"这种玩笑不算)
+- 关键信息必须是具体值(如"11月23日"),不要填描述性文字
+- 游戏剧情/故事不是TA本人的信息
+
此工具在后台异步执行,不影响回复速度。"""
parameters = [
("target_user_id", ToolParamType.STRING, "目标用户的ID(必须)", True, None),
("target_user_name", ToolParamType.STRING, "目标用户的名字/昵称(必须)", True, None),
- ("user_aliases", ToolParamType.STRING, "TA的其他昵称或别名(可选)", False, None),
+ ("alias_operation", ToolParamType.STRING, "别名操作:add=新增 / remove=删除 / replace=全部替换(可选)", False, None),
+ ("alias_value", ToolParamType.STRING, "别名内容,多个用、分隔", False, None),
("impression_hint", ToolParamType.STRING, "你观察到的关于TA的要点(可选)", False, None),
- ("preference_keywords", ToolParamType.STRING, "TA的兴趣爱好关键词(可选)", False, None),
+ ("preference_operation", ToolParamType.STRING, "偏好操作:add=新增 / remove=删除 / replace=全部替换(可选)", False, None),
+ ("preference_value", ToolParamType.STRING, "偏好关键词,多个用、分隔(可选)", False, None),
("key_info_type", ToolParamType.STRING, "信息类型:birthday/job/location/dream/family/pet(可选)", False, None),
- ("key_info_value", ToolParamType.STRING, "信息内容,如'11月23日'、'上海'(可选)", False, None),
+ ("key_info_value", ToolParamType.STRING, "具体信息内容(必须是具体值如'11月23日'、'上海')", False, None),
]
available_for_llm = True
history_ttl = 1
@@ -88,14 +95,16 @@ class UserProfileTool(BaseTool):
}
# 从LLM传入的参数
- new_aliases = function_args.get("user_aliases", "")
+ alias_operation = function_args.get("alias_operation", "")
+ alias_value = function_args.get("alias_value", "")
impression_hint = function_args.get("impression_hint", "")
- new_keywords = function_args.get("preference_keywords", "")
+ preference_operation = function_args.get("preference_operation", "")
+ preference_value = function_args.get("preference_value", "")
key_info_type = function_args.get("key_info_type", "")
key_info_value = function_args.get("key_info_value", "")
# 如果LLM没有传入任何有效参数,返回提示
- if not any([new_aliases, impression_hint, new_keywords, key_info_value]):
+ if not any([alias_value, impression_hint, preference_value, key_info_value]):
return {
"type": "info",
"id": target_user_id,
@@ -106,9 +115,11 @@ class UserProfileTool(BaseTool):
asyncio.create_task(self._background_update(
target_user_id=target_user_id,
target_user_name=str(target_user_name) if target_user_name else str(target_user_id),
- new_aliases=new_aliases,
+ alias_operation=alias_operation,
+ alias_value=alias_value,
impression_hint=impression_hint,
- new_keywords=new_keywords,
+ preference_operation=preference_operation,
+ preference_value=preference_value,
key_info_type=key_info_type,
key_info_value=key_info_value,
))
@@ -132,9 +143,11 @@ class UserProfileTool(BaseTool):
self,
target_user_id: str,
target_user_name: str,
- new_aliases: str,
+ alias_operation: str,
+ alias_value: str,
impression_hint: str,
- new_keywords: str,
+ preference_operation: str,
+ preference_value: str,
key_info_type: str = "",
key_info_value: str = "",
):
@@ -148,6 +161,20 @@ class UserProfileTool(BaseTool):
await self._add_key_fact(target_user_id, key_info_type or "other", key_info_value)
logger.info(f"[后台] 已记录关键信息: {target_user_id}, {key_info_type}={key_info_value}")
+ # 🎯 处理别名操作
+ final_aliases = self._process_list_operation(
+ existing_value=existing_profile.get("user_aliases", ""),
+ operation=alias_operation,
+ new_value=alias_value,
+ )
+
+ # 🎯 处理偏好操作
+ final_preferences = self._process_list_operation(
+ existing_value=existing_profile.get("preference_keywords", ""),
+ operation=preference_operation,
+ new_value=preference_value,
+ )
+
# 获取最近的聊天记录
chat_history_text = await self._get_recent_chat_history(target_user_id)
@@ -160,7 +187,7 @@ class UserProfileTool(BaseTool):
target_user_name=target_user_name,
impression_hint=impression_hint,
existing_impression=str(existing_profile.get("relationship_text", "")),
- preference_keywords=str(new_keywords or existing_profile.get("preference_keywords", "")),
+ preference_keywords=final_preferences,
chat_history=chat_history_text,
current_score=float(existing_profile.get("relationship_score", _get_base_relationship_score())),
)
@@ -174,9 +201,9 @@ class UserProfileTool(BaseTool):
# 构建最终画像
final_profile = {
- "user_aliases": new_aliases if new_aliases else existing_profile.get("user_aliases", ""),
+ "user_aliases": final_aliases,
"relationship_text": final_impression,
- "preference_keywords": new_keywords if new_keywords else existing_profile.get("preference_keywords", ""),
+ "preference_keywords": final_preferences,
"relationship_score": new_score,
}
@@ -187,6 +214,41 @@ class UserProfileTool(BaseTool):
except Exception as e:
logger.error(f"[后台] 用户画像更新失败: {e}")
+
+ def _process_list_operation(self, existing_value: str, operation: str, new_value: str) -> str:
+ """处理列表类型的操作(别名、偏好等)
+
+ Args:
+ existing_value: 现有值(用、分隔)
+ operation: 操作类型 add/remove/replace
+ new_value: 新值(用、分隔)
+
+ Returns:
+ str: 处理后的值
+ """
+ if not new_value:
+ return existing_value
+
+ # 解析现有值和新值
+ existing_set = set(filter(None, [x.strip() for x in (existing_value or "").split("、")]))
+ new_set = set(filter(None, [x.strip() for x in new_value.split("、")]))
+
+ operation = (operation or "add").lower().strip()
+
+ if operation == "replace":
+ # 全部替换
+ result_set = new_set
+ logger.info(f"别名/偏好替换: {existing_set} -> {new_set}")
+ elif operation == "remove":
+ # 删除指定项
+ result_set = existing_set - new_set
+ logger.info(f"别名/偏好删除: {new_set} 从 {existing_set}")
+ else: # add 或默认
+ # 新增(合并)
+ result_set = existing_set | new_set
+ logger.info(f"别名/偏好新增: {new_set} 到 {existing_set}")
+
+ return "、".join(sorted(result_set))
async def _add_key_fact(self, user_id: str, info_type: str, info_value: str):
"""添加或更新关键信息(生日、职业等)
@@ -204,6 +266,24 @@ class UserProfileTool(BaseTool):
if info_type not in valid_types:
info_type = "other"
+ # 🎯 信息质量判断:过滤掉模糊的描述性内容
+ low_quality_patterns = [
+ "的生日", "的工作", "的位置", "的梦想", "的家人", "的宠物",
+ "birthday", "job", "location", "unknown", "未知", "不知道",
+ "affectionate", "friendly", "的信息", "某个", "一个"
+ ]
+ info_value_lower = info_value.lower().strip()
+
+ # 如果值太短或包含低质量模式,跳过
+ if len(info_value_lower) < 2:
+ logger.warning(f"关键信息值太短,跳过: {info_value}")
+ return
+
+ for pattern in low_quality_patterns:
+ if pattern in info_value_lower:
+ logger.warning(f"关键信息质量不佳,跳过: {info_type}={info_value}(包含'{pattern}')")
+ return
+
current_time = time.time()
async with get_db_session() as session:
@@ -225,6 +305,11 @@ class UserProfileTool(BaseTool):
found = False
for i, fact in enumerate(facts):
if isinstance(fact, dict) and fact.get("type") == info_type:
+ old_value = fact.get("value", "")
+ # 🎯 智能判断:如果旧值更具体,不要用模糊值覆盖
+ if len(old_value) > len(info_value) and not any(p in old_value.lower() for p in low_quality_patterns):
+ logger.info(f"保留更具体的旧值: {info_type}='{old_value}',跳过新值: '{info_value}'")
+ return
# 更新现有记录
facts[i] = {"type": info_type, "value": info_value}
found = True
@@ -405,76 +490,72 @@ class UserProfileTool(BaseTool):
{current_score:.2f} (范围0-1,0.3=普通认识,0.5=朋友,0.7=好友,0.9=挚友)
## ⚠️ 重要:区分虚构内容和真实信息
-- 如果{target_user_name}在讲述**游戏剧情、小说情节、动漫故事、角色扮演**等虚构内容,这些是**TA分享的内容**,不是TA本人的特质
-- 印象应该记录的是**{target_user_name}这个人**的特点,比如:
- - TA喜欢玩什么游戏、看什么动漫(兴趣)
- - TA讲故事时的语气和热情(性格)
- - TA和你交流时的方式(互动风格)
-- **不要**把游戏里的角色、剧情、NPC的特点当成{target_user_name}本人的特点
-- 例如:如果TA在讲游戏里的剧情,记录的应该是"TA很喜欢这个游戏/对剧情很有感触"
+- 游戏剧情、小说情节、角色扮演等虚构内容 ≠ TA本人的特质
+- 印象记录的是**这个人本身**:TA的性格、TA喜欢什么、TA和你交流的方式
+- 如果TA在讲游戏剧情,记录的应该是"TA对这类故事很有热情"而非剧情本身
## 任务
-1. 根据聊天记录判断{target_user_name}的性别(男用"他",女用"她",无法判断用名字)
-2. {"写下你对这个人的第一印象" if is_first_impression else "在原有印象基础上,融入新的观察"}
+1. 判断{target_user_name}的性别(男用"他",女用"她",无法判断用名字)
+2. {"写下你对这个人的第一印象" if is_first_impression else "在原有印象基础上,融入新的感受和理解"}
3. 决定好感度是否需要变化(大多数情况不需要)
-## 印象写作要求(重要!)
-这是**长期印象**,不是某次聊天的记录!
+## 📝 印象写作指南
-**应该写的(泛化、抽象):**
-- TA是什么样的人(性格特点)
-- TA给你的整体感觉
-- TA的说话风格、互动方式
-- TA的兴趣爱好类型
-- 你们关系的整体状态
+**核心定位:这是你心中对这个人的画像,是你对TA的理解和感受,不是聊天日志。**
-**不要写的(太具体、太短期):**
-- ❌ "今天TA跟我聊了xxx"
-- ❌ "TA刚才说了xxx"
-- ❌ 具体的某一次对话内容
-- ❌ 某个具体事件的细节
-- ❌ 时间词如"刚才"、"今天"、"最近一次"
+### 内容维度(自然融入,不要分点罗列):
+- **性格气质**:TA给你的整体感觉,是什么类型的人
+- **交流风格**:TA说话的方式、语气特点、互动习惯
+- **情感印记**:让你印象深刻的感受(不是具体事件)
+- **关系状态**:你们现在的关系是怎样的,相处起来什么感觉
-**格式要求:**
-- 用第一人称"我"来写
-- 根据判断的性别使用"他/她"
-- {"第一印象50-150字" if is_first_impression else "150-300字,在原有基础上补充"}
-- 写出这个人的**整体特质**,而不是某次聊天的具体内容
+### 写作风格:
+- 散文式叙述,像在心里默默描绘一个人
+- 写感受和印象,不是记录"TA做了什么"
+- 带着你对TA的情感去描述,有温度
+- 可以用比喻、联想,自然流畅
-## 好感度变化规则(极其严格!99%的对话好感度不变!)
+### 绝对避免:
+- 时间词:"今天"、"刚才"、"上次"、"最近"
+- 具体事件:"TA跟我说了xxx"、"我们聊了xxx"
+- 罗列格式:"喜欢A、B、C"、"特点:1.xx 2.xx"
+- 流水账式:"首先...然后...最后..."
-**核心原则:好感度是长期关系的体现,不是单次对话能改变的。**
+### 字数要求:
+- {"初次印象:80-150字,写出第一感觉" if is_first_impression else "深化印象:200-400字,在原有基础上自然融入新的理解"}
-- 范围:-0.02 到 +0.02,**但绝大多数情况应该是 0**
-- 好感度会自然波动,即使很高也可能因为疏远、冷淡、误解而下降
+## 好感度变化规则(分阶段,越高越难涨)
-**好感度 = 0(不变)的情况(这是默认值!):**
-- 普通聊天、日常问候、闲聊 → 0
-- 聊得很开心、话题很有趣 → 0(开心≠好感增加)
-- 讨论游戏、分享故事、聊兴趣 → 0
-- 对方表达喜欢你、夸你 → 0(嘴上说的不算数)
-- 简单的关心、问候 → 0
-- 友好的互动 → 0(友好是正常的,不是加分项)
+当前好感度:{current_score:.2f}
-**好感度 = +0.01(微涨)的情况(非常罕见):**
-- 对方在真正困难时向你倾诉,展现了深层信任
-- 经过很长时间的相处,关系有了质的突破
+**关系阶段与增速:**
+| 阶段 | 分数范围 | 单次变化范围 | 说明 |
+|------|----------|--------------|------|
+| 陌生→初识 | 0.0-0.3 | ±0.03~0.05 | 容易建立初步印象 |
+| 初识→熟人 | 0.3-0.5 | ±0.02~0.04 | 逐渐熟悉的阶段 |
+| 熟人→朋友 | 0.5-0.7 | ±0.01~0.03 | 需要更多互动积累 |
+| 朋友→好友 | 0.7-0.85 | ±0.01~0.02 | 关系深化变慢 |
+| 好友→挚友 | 0.85-1.0 | ±0.005~0.01 | 极难变化,需要重大事件 |
-**好感度 = +0.02(涨)的情况(极其罕见,几乎不会发生):**
-- 对方为你做出了实质性的牺牲或帮助
-- 你们之间发生了真正改变关系的重大事件
+**加分情况(根据当前阶段选择合适幅度):**
+- 愉快的聊天、有来有往的互动 → 小幅+(低阶段更明显)
+- 分享心情、倾诉烦恼 → 中幅+
+- 主动关心、记得之前聊过的事 → 中幅+
+- 深度交流、展现信任 → 较大+
+- 在困难时寻求帮助或给予支持 → 大幅+
-**好感度 = -0.01 到 -0.02(下降)的情况:**
-- 对方明显冷淡、敷衍
-- 发生了误解或小冲突
-- 长时间不联系后的疏远感
+**减分情况:**
+- 敷衍、冷淡的回应 → 小幅-
+- 明显的不耐烦或忽视 → 中幅-
+- 冲突、误解 → 较大-
+- 长期不联系(关系会自然冷却)→ 缓慢-
-**记住:**
-1. 聊得开心 ≠ 好感增加
-2. 话题友好 ≠ 好感增加
-3. 对方说喜欢你 ≠ 好感增加
-4. 好感是需要很长时间才能培养的
-5. 如果你不确定,就填 0
+**不变的情况:**
+- 纯粹的信息询问(问时间、问天气等)
+- 机械式的对话
+- 无法判断情感倾向的中性交流
+
+**注意:高好感度(>0.8)时要非常谨慎加分,友好互动在这个阶段是常态,不是加分项。**
请严格按照以下JSON格式输出:
{{
@@ -508,8 +589,24 @@ class UserProfileTool(BaseTool):
change_reason = result.get("change_reason", "")
detected_gender = result.get("gender", "unknown")
- # 限制好感度变化范围(极严格:-0.02 到 +0.02)
- affection_change = max(-0.02, min(0.02, affection_change))
+ # 🎯 根据当前好感度阶段限制变化范围
+ if current_score < 0.3:
+ # 陌生→初识:±0.05
+ max_change = 0.05
+ elif current_score < 0.5:
+ # 初识→熟人:±0.04
+ max_change = 0.04
+ elif current_score < 0.7:
+ # 熟人→朋友:±0.03
+ max_change = 0.03
+ elif current_score < 0.85:
+ # 朋友→好友:±0.02
+ max_change = 0.02
+ else:
+ # 好友→挚友:±0.01
+ max_change = 0.01
+
+ affection_change = max(-max_change, min(max_change, affection_change))
# 如果印象为空或太短,回退到hint
if not impression or len(impression) < 10:
@@ -619,13 +716,18 @@ class UserProfileTool(BaseTool):
stage = self._calculate_relationship_stage(score)
if existing:
- # 更新现有记录
- existing.user_aliases = profile.get("user_aliases", "")
+ # 别名和偏好已经在_background_update中处理好了,直接赋值
+ existing.user_aliases = profile.get("user_aliases", "") or existing.user_aliases
+
# 同时更新新旧两个印象字段,保持兼容
impression = profile.get("relationship_text", "")
- existing.relationship_text = impression
- existing.impression_text = impression
- existing.preference_keywords = profile.get("preference_keywords", "")
+ if impression: # 只有有新印象才更新
+ existing.relationship_text = impression
+ existing.impression_text = impression
+
+ # 偏好关键词已经在_background_update中处理好了,直接赋值
+ existing.preference_keywords = profile.get("preference_keywords", "") or existing.preference_keywords
+
existing.relationship_score = score
existing.relationship_stage = stage
existing.last_impression_update = current_time
diff --git a/src/plugins/built_in/kokoro_flow_chatter/models.py b/src/plugins/built_in/kokoro_flow_chatter/models.py
index fb72423e6..774e4d34c 100644
--- a/src/plugins/built_in/kokoro_flow_chatter/models.py
+++ b/src/plugins/built_in/kokoro_flow_chatter/models.py
@@ -69,7 +69,8 @@ class WaitingConfig:
max_wait_seconds: int = 0 # 最长等待时间(秒),0 表示不等待
started_at: float = 0.0 # 开始等待的时间戳
last_thinking_at: float = 0.0 # 上次连续思考的时间戳
- thinking_count: int = 0 # 连续思考次数
+ thinking_count: int = 0 # 连续思考次数(心理活动)
+ followup_count: int = 0 # 追问次数(真正发送消息的次数)
def is_active(self) -> bool:
"""是否正在等待"""
@@ -104,6 +105,7 @@ class WaitingConfig:
"started_at": self.started_at,
"last_thinking_at": self.last_thinking_at,
"thinking_count": self.thinking_count,
+ "followup_count": self.followup_count,
}
@classmethod
@@ -114,6 +116,7 @@ class WaitingConfig:
started_at=data.get("started_at", 0.0),
last_thinking_at=data.get("last_thinking_at", 0.0),
thinking_count=data.get("thinking_count", 0),
+ followup_count=data.get("followup_count", 0),
)
def reset(self) -> None:
@@ -123,6 +126,7 @@ class WaitingConfig:
self.started_at = 0.0
self.last_thinking_at = 0.0
self.thinking_count = 0
+ self.followup_count = 0
@dataclass
diff --git a/src/plugins/built_in/kokoro_flow_chatter/proactive_thinker.py b/src/plugins/built_in/kokoro_flow_chatter/proactive_thinker.py
index 2a9f44893..bfb4c382a 100644
--- a/src/plugins/built_in/kokoro_flow_chatter/proactive_thinker.py
+++ b/src/plugins/built_in/kokoro_flow_chatter/proactive_thinker.py
@@ -424,6 +424,7 @@ class ProactiveThinker:
# 构建超时上下文信息
extra_context = {
"consecutive_timeout_count": session.consecutive_timeout_count,
+ "followup_count": session.waiting_config.followup_count, # 真正发消息的追问次数
"time_since_user_reply": time_since_user_reply,
"time_since_user_reply_str": self._format_duration(time_since_user_reply) if time_since_user_reply else "未知",
}
@@ -479,6 +480,15 @@ class ProactiveThinker:
log_prefix="[KFC ProactiveThinker]",
)
+ # 🎯 只有真正发送了消息才增加追问计数(do_nothing 不算追问)
+ has_reply_action = any(
+ a.type in ("kfc_reply", "respond", "poke_user", "send_emoji")
+ for a in plan_response.actions
+ )
+ if has_reply_action:
+ session.waiting_config.followup_count += 1
+ logger.debug(f"[ProactiveThinker] 超时追问计数+1: user={session.user_id}, followup_count={session.waiting_config.followup_count}")
+
# 记录到 mental_log
session.add_bot_planning(
thought=plan_response.thought,
diff --git a/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py b/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py
index 10632b80b..f2e6b65c5 100644
--- a/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py
+++ b/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py
@@ -684,10 +684,10 @@ class PromptBuilder:
# 构建连续超时上下文
timeout_context_parts = []
- # 添加连续超时次数信息
- consecutive_count = extra_context.get("consecutive_timeout_count", 0)
- if consecutive_count > 1:
- timeout_context_parts.append(f"⚠️ 这已经是你连续第 {consecutive_count} 次等到超时了。")
+ # 添加真正追问次数警告(只有真正发了消息才算追问)
+ followup_count = extra_context.get("followup_count", 0)
+ if followup_count > 0:
+ timeout_context_parts.append(f"⚠️ 你已经连续追问了 {followup_count} 次,对方仍未回复。再追问可能会显得太急躁,请三思。")
# 添加距离用户上次回复的时间
time_since_user_reply_str = extra_context.get("time_since_user_reply_str")
diff --git a/src/plugins/built_in/kokoro_flow_chatter/unified.py b/src/plugins/built_in/kokoro_flow_chatter/unified.py
index 8a363307f..05e9ed2e3 100644
--- a/src/plugins/built_in/kokoro_flow_chatter/unified.py
+++ b/src/plugins/built_in/kokoro_flow_chatter/unified.py
@@ -147,8 +147,8 @@ class UnifiedPromptGenerator:
# 计算等待时间
wait_duration = session.waiting_config.get_elapsed_seconds()
- # 生成连续追问警告(使用 waiting_config.thinking_count 作为追问计数)
- followup_count = session.waiting_config.thinking_count
+ # 生成连续追问警告(使用 followup_count 作为追问计数,只有真正发消息才算)
+ followup_count = session.waiting_config.followup_count
max_followups = 3 # 最多追问3次
if followup_count >= max_followups: