diff --git a/src/chat/replyer/prompt/replyer_prompt.py b/src/chat/replyer/prompt/replyer_prompt.py index 26b47cb4..9e5d145a 100644 --- a/src/chat/replyer/prompt/replyer_prompt.py +++ b/src/chat/replyer/prompt/replyer_prompt.py @@ -5,8 +5,6 @@ from src.chat.utils.prompt_builder import Prompt def init_replyer_prompt(): - Prompt("你正在qq群里聊天,下面是群里正在聊的内容:", "chat_target_group1") - Prompt("你正在和{sender_name}聊天,这是你们之前聊的内容:", "chat_target_private1") Prompt("正在群里聊天", "chat_target_group2") Prompt("和{sender_name}聊天", "chat_target_private2") @@ -15,7 +13,7 @@ def init_replyer_prompt(): """{knowledge_prompt}{tool_info_block}{extra_info_block} {expression_habits_block}{memory_block}{question_block} -你正在qq群里聊天,下面是群里正在聊的内容: +你正在qq群里聊天,下面是群里正在聊的内容,其中包含聊天记录和聊天中的图片: {time_block} {dialogue_prompt} @@ -25,7 +23,7 @@ def init_replyer_prompt(): 尽量简短一些。{keywords_reaction_prompt}请注意把握聊天内容,不要回复的太有条理,可以有个性。 {reply_style} 请注意不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只输出一句回复内容就好。 -{moderation_prompt}不要输出多余内容(包括前后缀,冒号和引号,括号,表情包,at或 @等 )。请不要思考太长 +不要输出多余内容(包括前后缀,冒号和引号,括号,表情包,at或 @等 )。请不要思考太长 现在,你说:""", "replyer_prompt", ) diff --git a/src/config/config.py b/src/config/config.py index e34b02b6..c379be66 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -55,7 +55,7 @@ TEMPLATE_DIR = os.path.join(PROJECT_ROOT, "template") # 考虑到,实际上配置文件中的mai_version是不会自动更新的,所以采用硬编码 # 对该字段的更新,请严格参照语义化版本规范:https://semver.org/lang/zh-CN/ -MMC_VERSION = "0.11.1-snapshot.1" +MMC_VERSION = "0.11.2-snapshot.1" def get_key_comment(toml_table, key): diff --git a/src/express/style_learner.py b/src/express/style_learner.py index 4cacba78..e26b121c 100644 --- a/src/express/style_learner.py +++ b/src/express/style_learner.py @@ -20,7 +20,7 @@ class StyleLearner: """ 单个聊天室的表达风格学习器 学习从up_content到style的映射关系 - 支持动态管理风格集合(最多2000个) + 支持动态管理风格集合(无数量上限) """ def __init__(self, chat_id: str, model_config: Optional[Dict] = None): @@ -37,7 +37,6 @@ class StyleLearner: self.expressor = ExpressorModel(**self.model_config) # 动态风格管理 - self.max_styles = 2000 # 每个chat_id最多2000个风格 self.style_to_id: Dict[str, str] = {} # style文本 -> style_id self.id_to_style: Dict[str, str] = {} # style_id -> style文本 self.id_to_situation: Dict[str, str] = {} # style_id -> situation文本 @@ -68,11 +67,6 @@ class StyleLearner: logger.debug(f"[{self.chat_id}] 风格 '{style}' 已存在") return True - # 检查是否超过最大限制 - if len(self.style_to_id) >= self.max_styles: - logger.warning(f"[{self.chat_id}] 已达到最大风格数量限制 ({self.max_styles})") - return False - # 生成新的style_id style_id = f"style_{self.next_style_id}" self.next_style_id += 1 @@ -344,7 +338,6 @@ class StyleLearner: "chat_id": self.chat_id, "total_samples": self.learning_stats["total_samples"], "style_count": len(self.style_to_id), - "max_styles": self.max_styles, "style_counts": dict(self.learning_stats["style_counts"]), "style_usage_frequency": dict(self.learning_stats["style_usage_frequency"]), "last_update": self.learning_stats["last_update"], @@ -369,7 +362,6 @@ class StyleLearner: "id_to_style": self.id_to_style, "id_to_situation": self.id_to_situation, "next_style_id": self.next_style_id, - "max_styles": self.max_styles, "learning_stats": self.learning_stats } @@ -413,7 +405,6 @@ class StyleLearner: self.id_to_style = save_data["id_to_style"] self.id_to_situation = save_data.get("id_to_situation", {}) # 兼容旧版本 self.next_style_id = save_data["next_style_id"] - self.max_styles = save_data.get("max_styles", 2000) self.learning_stats = save_data["learning_stats"] # 重新创建expressor并加载 @@ -432,7 +423,7 @@ class StyleLearnerManager: """ 多聊天室表达风格学习管理器 为每个chat_id维护独立的StyleLearner实例 - 每个chat_id可以动态管理自己的风格集合(最多2000个) + 每个chat_id可以动态管理自己的风格集合(无数量上限) """ def __init__(self, model_save_path: str = "data/style_models"): diff --git a/src/main.py b/src/main.py index f02a7098..790e97c4 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from src.common.logger import get_logger from src.common.server import get_global_server, Server from src.mood.mood_manager import mood_manager from src.chat.knowledge import lpmm_start_up -from src.memory_system.memory_management_task import MemoryManagementTask +from src.memory_system.memory_management_task import MemoryManagementTask, MemoryConflictCleanupTask from rich.traceback import install # from src.api.main import start_api_server @@ -96,6 +96,10 @@ class MainSystem: # 添加记忆管理任务 await async_task_manager.add_task(MemoryManagementTask()) logger.info("记忆管理任务已启动") + + # 添加记忆冲突清理任务 + await async_task_manager.add_task(MemoryConflictCleanupTask()) + logger.info("记忆冲突清理任务已启动") # await asyncio.sleep(0.5) #防止logger输出飞了 diff --git a/src/memory_system/memory_management_task.py b/src/memory_system/memory_management_task.py index 90b6e2ca..edfd875c 100644 --- a/src/memory_system/memory_management_task.py +++ b/src/memory_system/memory_management_task.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- import asyncio import random +import time from typing import List from src.manager.async_task_manager import AsyncTask from src.memory_system.Memory_chest import global_memory_chest from src.common.logger import get_logger -from src.common.database.database_model import MemoryChest as MemoryChestModel +from src.common.database.database_model import MemoryChest as MemoryChestModel, MemoryConflict from src.config.config import global_config logger = get_logger("memory") @@ -180,3 +181,61 @@ class MemoryManagementTask(AsyncTask): except Exception as e: logger.error(f"[记忆管理] 删除原始记忆时发生错误: {e}") return 0 + + +class MemoryConflictCleanupTask(AsyncTask): + """记忆冲突清理定时任务 + + 定期清理 memory_conflicts 表中 create_time 较早(7天前)且 answer 为空的项目 + 默认每小时执行一次 + """ + + def __init__(self, cleanup_days: int = 7, run_interval: int = 3600): + """ + 初始化清理任务 + + Args: + cleanup_days: 清理多少天前的记录,默认7天 + run_interval: 执行间隔(秒),默认3600秒(1小时) + """ + super().__init__( + task_name="Memory Conflict Cleanup Task", + wait_before_start=60, # 启动后等待60秒再开始 + run_interval=run_interval + ) + self.cleanup_days = cleanup_days + + async def run(self): + """执行清理任务""" + try: + current_time = time.time() + # 计算7天前的时间戳 + cutoff_time = current_time - (self.cleanup_days * 24 * 60 * 60) + + logger.info(f"[冲突清理] 开始清理 {self.cleanup_days} 天前且 answer 为空的冲突记录(截止时间: {cutoff_time})") + + # 查询需要清理的记录:create_time < cutoff_time 且 answer 为空 + # answer 为空的条件:answer IS NULL 或 answer == '' + query = MemoryConflict.select().where( + (MemoryConflict.create_time < cutoff_time) & + ((MemoryConflict.answer.is_null()) | (MemoryConflict.answer == '')) + ) + + # 先统计要删除的数量 + deleted_count = query.count() + + # 批量删除 + if deleted_count > 0: + deleted = MemoryConflict.delete().where( + (MemoryConflict.create_time < cutoff_time) & + ((MemoryConflict.answer.is_null()) | (MemoryConflict.answer == '')) + ).execute() + deleted_count = deleted + + if deleted_count > 0: + logger.info(f"[冲突清理] 成功清理 {deleted_count} 条过期且未回答的冲突记录") + else: + logger.debug("[冲突清理] 没有需要清理的记录") + + except Exception as e: + logger.error(f"[冲突清理] 执行清理任务时发生错误: {e}", exc_info=True)