From 7f39f6f6498e09106e63c52f2ceb645c27d44e83 Mon Sep 17 00:00:00 2001 From: tt-P607 <68868379+tt-P607@users.noreply.github.com> Date: Sat, 27 Sep 2025 00:58:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(sleep):=20=E7=BB=86=E5=8C=96=E5=94=A4?= =?UTF-8?q?=E9=86=92=E6=9C=BA=E5=88=B6=EF=BC=8C=E5=AE=9E=E7=8E=B0=E5=88=86?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E7=9A=84=E8=B5=B7=E5=BA=8A=E6=B0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 先前的唤醒与起床气机制是全局性的,一个聊天中的频繁消息会导致Bot对所有聊天都表现出“起床气”状态,这在多聊天场景下体验不佳。 本次更新将唤醒机制与具体的 `chat_id` 进行绑定,实现了更精细化的交互逻辑: - Bot被吵醒后,其“起床气”状态将只针对吵醒它的聊天生效。 - 在此期间,Bot会忽略其他所有聊天的消息,专注于处理来自触发唤醒的聊天的消息。 - Prompt现在会优先注入起床气相关的描述,确保响应符合当前状态。 此外,为了更准确地捕捉唤醒意图,在群聊中,即使没有@提及,只要消息包含Bot的昵称或别名,也会被视为一次有效“提及”,从而累加唤醒值。 --- src/chat/message_manager/message_manager.py | 14 ++++++++++- .../sleep_manager/sleep_manager.py | 4 +++ .../sleep_manager/wakeup_manager.py | 25 ++++++++++++++----- .../affinity_flow_chatter/plan_filter.py | 23 +++++++++++++++-- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/chat/message_manager/message_manager.py b/src/chat/message_manager/message_manager.py index 8df7f4bca..8aef2e0d8 100644 --- a/src/chat/message_manager/message_manager.py +++ b/src/chat/message_manager/message_manager.py @@ -180,8 +180,14 @@ class MessageManager: for message in unread_messages: is_mentioned = message.is_mentioned or False + if not is_mentioned and not is_private: + bot_names = [global_config.bot.nickname] + global_config.bot.alias_names + if any(name in message.processed_plain_text for name in bot_names): + is_mentioned = True + logger.debug(f"通过关键词 '{next((name for name in bot_names if name in message.processed_plain_text), '')}' 匹配将消息标记为 'is_mentioned'") + if is_private or is_mentioned: - if self.wakeup_manager.add_wakeup_value(is_private, is_mentioned): + if self.wakeup_manager.add_wakeup_value(is_private, is_mentioned, chat_id=stream_id): was_woken_up = True break # 一旦被吵醒,就跳出循环并处理消息 @@ -190,6 +196,12 @@ class MessageManager: return # 退出,不处理消息 logger.info(f"Bot被聊天流 {stream_id} 中的消息吵醒,继续处理。") + elif self.sleep_manager.is_woken_up(): + angry_chat_id = self.wakeup_manager.angry_chat_id + if stream_id != angry_chat_id: + logger.debug(f"Bot处于WOKEN_UP状态,但当前流 {stream_id} 不是触发唤醒的流 {angry_chat_id},跳过处理。") + return # 退出,不处理此流的消息 + logger.info(f"Bot处于WOKEN_UP状态,处理触发唤醒的流 {stream_id}。") # --- 睡眠状态检查结束 --- logger.debug(f"开始处理聊天流 {stream_id} 的 {len(unread_messages)} 条未读消息") diff --git a/src/chat/message_manager/sleep_manager/sleep_manager.py b/src/chat/message_manager/sleep_manager/sleep_manager.py index 282b7e3b6..0ed21e685 100644 --- a/src/chat/message_manager/sleep_manager/sleep_manager.py +++ b/src/chat/message_manager/sleep_manager/sleep_manager.py @@ -39,6 +39,10 @@ class SleepManager: """判断当前是否处于正在睡觉的状态。""" return self.context.current_state == SleepState.SLEEPING + def is_woken_up(self) -> bool: + """判断当前是否处于被吵醒的状态。""" + return self.context.current_state == SleepState.WOKEN_UP + async def update_sleep_state(self, wakeup_manager: Optional["WakeUpManager"] = None): """ 更新睡眠状态的核心方法,实现状态机的主要逻辑。 diff --git a/src/chat/message_manager/sleep_manager/wakeup_manager.py b/src/chat/message_manager/sleep_manager/wakeup_manager.py index 79ba9cb83..51ab80bb1 100644 --- a/src/chat/message_manager/sleep_manager/wakeup_manager.py +++ b/src/chat/message_manager/sleep_manager/wakeup_manager.py @@ -28,6 +28,7 @@ class WakeUpManager: """ self.sleep_manager = sleep_manager self.context = WakeUpContext() # 使用新的上下文管理器 + self.angry_chat_id: Optional[str] = None self.last_decay_time = time.time() self._decay_task: Optional[asyncio.Task] = None self.is_running = False @@ -87,7 +88,11 @@ class WakeUpManager: self.context.is_angry = False # 通知情绪管理系统清除愤怒状态 from src.mood.mood_manager import mood_manager - mood_manager.clear_angry_from_wakeup("global_mood") + if self.angry_chat_id: + mood_manager.clear_angry_from_wakeup(self.angry_chat_id) + self.angry_chat_id = None + else: + logger.warning("Angry state ended but no angry_chat_id was set.") logger.info("愤怒状态结束,恢复正常") self.context.save() @@ -99,7 +104,7 @@ class WakeUpManager: logger.debug(f"唤醒度衰减: {old_value:.1f} -> {self.context.wakeup_value:.1f}") self.context.save() - def add_wakeup_value(self, is_private_chat: bool, is_mentioned: bool = False) -> bool: + def add_wakeup_value(self, is_private_chat: bool, is_mentioned: bool = False, chat_id: Optional[str] = None) -> bool: """ 增加唤醒度值 @@ -148,23 +153,27 @@ class WakeUpManager: # 检查是否达到唤醒阈值 if self.context.wakeup_value >= self.wakeup_threshold: - self._trigger_wakeup() + if not chat_id: + logger.error("Wakeup threshold reached, but no chat_id was provided. Cannot trigger wakeup.") + return False + self._trigger_wakeup(chat_id) return True self.context.save() return False - def _trigger_wakeup(self): + def _trigger_wakeup(self, chat_id: str): """触发唤醒,进入愤怒状态""" self.context.is_angry = True self.context.angry_start_time = time.time() self.context.wakeup_value = 0.0 # 重置唤醒度 + self.angry_chat_id = chat_id self.context.save() # 通知情绪管理系统进入愤怒状态 from src.mood.mood_manager import mood_manager - mood_manager.set_angry_from_wakeup("global_mood") + mood_manager.set_angry_from_wakeup(chat_id) # 通知SleepManager重置睡眠状态 self.sleep_manager.reset_sleep_state_after_wakeup() @@ -185,7 +194,11 @@ class WakeUpManager: self.context.is_angry = False # 通知情绪管理系统清除愤怒状态 from src.mood.mood_manager import mood_manager - mood_manager.clear_angry_from_wakeup("global_mood") + if self.angry_chat_id: + mood_manager.clear_angry_from_wakeup(self.angry_chat_id) + self.angry_chat_id = None + else: + logger.warning("Angry state expired in check, but no angry_chat_id was set.") logger.info("愤怒状态自动过期") return False return self.context.is_angry diff --git a/src/plugins/built_in/affinity_flow_chatter/plan_filter.py b/src/plugins/built_in/affinity_flow_chatter/plan_filter.py index 4793e2835..cd8a60137 100644 --- a/src/plugins/built_in/affinity_flow_chatter/plan_filter.py +++ b/src/plugins/built_in/affinity_flow_chatter/plan_filter.py @@ -151,12 +151,31 @@ class ChatterPlanFilter: identity_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}:" schedule_block = "" - if global_config.planning_system.schedule_enable: + # 优先检查是否被吵醒 + from src.chat.message_manager.message_manager import message_manager + angry_prompt_addition = "" + wakeup_mgr = message_manager.wakeup_manager + + # 双重检查确保愤怒状态不会丢失 + # 检查1: 直接从 wakeup_manager 获取 + if wakeup_mgr.is_in_angry_state(): + angry_prompt_addition = wakeup_mgr.get_angry_prompt_addition() + + # 检查2: 如果上面没获取到,再从 mood_manager 确认 + if not angry_prompt_addition: + chat_mood_for_check = mood_manager.get_mood_by_chat_id(plan.chat_id) + if chat_mood_for_check.is_angry_from_wakeup: + angry_prompt_addition = global_config.sleep_system.angry_prompt + + if angry_prompt_addition: + schedule_block = angry_prompt_addition + elif global_config.planning_system.schedule_enable: if current_activity := schedule_manager.get_current_activity(): schedule_block = f"你当前正在:{current_activity},但注意它与群聊的聊天无关。" mood_block = "" - if global_config.mood.enable_mood: + # 如果被吵醒,则心情也是愤怒的,不需要另外的情绪模块 + if not angry_prompt_addition and global_config.mood.enable_mood: chat_mood = mood_manager.get_mood_by_chat_id(plan.chat_id) mood_block = f"你现在的心情是:{chat_mood.mood_state}"