From 6cf59deef37cd39de1930ea98afcfc7b8f87e97f Mon Sep 17 00:00:00 2001 From: Windpicker-owo <3431391539@qq.com> Date: Mon, 1 Sep 2025 15:24:43 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=EF=BC=9A69a855d=EF=BC=88feat?= =?UTF-8?q?=EF=BC=9A=E4=BF=9D=E5=AD=98=E5=85=B3=E9=94=AE=E8=AF=8D=E5=88=B0?= =?UTF-8?q?message=E6=95=B0=E6=8D=AE=E5=BA=93=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat_loop/cycle_processor.py | 17 ++----- src/chat/chat_loop/heartFC_chat.py | 48 ++++++++++++------- .../heart_flow/heartflow_message_processor.py | 2 +- src/chat/message_receive/message.py | 3 ++ src/chat/message_receive/storage.py | 11 ++--- src/common/database/sqlalchemy_models.py | 2 + src/config/official_configs.py | 6 +-- src/plugins/built_in/core_actions/no_reply.py | 21 ++------ 8 files changed, 51 insertions(+), 59 deletions(-) diff --git a/src/chat/chat_loop/cycle_processor.py b/src/chat/chat_loop/cycle_processor.py index 8aaf34291..85297bdea 100644 --- a/src/chat/chat_loop/cycle_processor.py +++ b/src/chat/chat_loop/cycle_processor.py @@ -159,19 +159,12 @@ class CycleProcessor: self.context.last_action = action_type # 处理no_reply相关的逻辑 - if action_type != "no_reply" and action_type != "no_action": - # 导入NoReplyAction并重置计数器 - from src.plugins.built_in.core_actions.no_reply import NoReplyAction - NoReplyAction.reset_consecutive_count() + if action_type != "no_reply": self.context.no_reply_consecutive = 0 - logger.info(f"{self.context.log_prefix} 执行了{action_type}动作,重置no_reply计数器") - elif action_type == "no_action": - # 当执行回复动作时,也重置no_reply计数 - from src.plugins.built_in.core_actions.no_reply import NoReplyAction - NoReplyAction.reset_consecutive_count() - self.context.no_reply_consecutive = 0 - logger.info(f"{self.context.log_prefix} 执行了回复动作,重置no_reply计数器") - + if hasattr(self.context, 'chat_instance') and self.context.chat_instance: + self.context.chat_instance.recent_interest_records.clear() + logger.info(f"{self.context.log_prefix} 执行了{action_type}动作,重置no_reply计数器和兴趣度记录") + if action_type == "no_reply": self.context.no_reply_consecutive += 1 # 调用HeartFChatting中的_determine_form_type方法 diff --git a/src/chat/chat_loop/heartFC_chat.py b/src/chat/chat_loop/heartFC_chat.py index 33dcfc910..29d4b945f 100644 --- a/src/chat/chat_loop/heartFC_chat.py +++ b/src/chat/chat_loop/heartFC_chat.py @@ -3,6 +3,7 @@ import time import traceback import random from typing import Optional, List, Dict, Any, Tuple +from collections import deque from src.common.logger import get_logger from src.config.config import global_config @@ -55,6 +56,9 @@ class HeartFChatting: self.context.chat_instance = self self._loop_task: Optional[asyncio.Task] = None + + # 记录最近3次的兴趣度 + self.recent_interest_records: deque = deque(maxlen=3) self._initialize_chat_mode() logger.info(f"{self.context.log_prefix} HeartFChatting 初始化完成") @@ -242,23 +246,20 @@ class HeartFChatting: logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。") # 根据聊天模式处理新消息 - if self.context.loop_mode == ChatMode.FOCUS: - # 如果上一个动作是no_reply,则执行no_reply逻辑 - if self.context.last_action == "no_reply": - if not await self._execute_no_reply(recent_messages): - self.context.energy_value -= 0.3 / global_config.chat.focus_value - logger.info(f"{self.context.log_prefix} 能量值减少,当前能量值:{self.context.energy_value:.1f}") - return has_new_messages + # 统一使用 _should_process_messages 判断是否应该处理 + if not self._should_process_messages(recent_messages if has_new_messages else None): + return has_new_messages + if self.context.loop_mode == ChatMode.FOCUS: # 处理新消息 for message in recent_messages: await self.cycle_processor.observe(message) - + # 如果成功观察,增加能量值 if has_new_messages: self.context.energy_value += 1 / global_config.chat.focus_value logger.info(f"{self.context.log_prefix} 能量值增加,当前能量值:{self.context.energy_value:.1f}") - + self._check_focus_exit() elif self.context.loop_mode == ChatMode.NORMAL: self._check_focus_entry(len(recent_messages)) @@ -399,9 +400,8 @@ class HeartFChatting: self.context.focus_energy = 1 else: # 计算最近三次记录的兴趣度总和 - from src.plugins.built_in.core_actions.no_reply import NoReplyAction - total_recent_interest = sum(NoReplyAction._recent_interest_records) - + total_recent_interest = sum(self.recent_interest_records) + # 获取当前聊天频率和意愿系数 talk_frequency = global_config.chat.get_current_talk_frequency(self.context.stream_id) @@ -417,6 +417,22 @@ class HeartFChatting: else: logger.info(f"{self.context.log_prefix} 兴趣度充足") self.context.focus_energy = 1 + + def _should_process_messages(self, messages: List[Dict[str, Any]] = None) -> bool: + """ + 统一判断是否应该处理消息的函数 + 根据当前循环模式和消息内容决定是否继续处理 + """ + from src.chat.utils.utils_image import is_image_message + + if self.context.loop_mode == ChatMode.FOCUS: + if self.context.last_action == "no_reply": + if messages: + return self._execute_no_reply(messages) + return False + return True + + return True async def _execute_no_reply(self, new_message: List[Dict[str, Any]]) -> bool: """执行breaking形式的no_reply(原有逻辑)""" @@ -427,14 +443,13 @@ class HeartFChatting: if new_message_count >= modified_exit_count_threshold: # 记录兴趣度到列表 - from src.plugins.built_in.core_actions.no_reply import NoReplyAction total_interest = 0.0 for msg_dict in new_message: interest_value = msg_dict.get("interest_value", 0.0) if msg_dict.get("processed_plain_text", ""): total_interest += interest_value - NoReplyAction._recent_interest_records.append(total_interest) + self.recent_interest_records.append(total_interest) logger.info( f"{self.context.log_prefix} 累计消息数量达到{new_message_count}条(>{modified_exit_count_threshold}),结束等待" @@ -458,11 +473,10 @@ class HeartFChatting: if accumulated_interest >= 3 / talk_frequency: # 记录兴趣度到列表 - from src.plugins.built_in.core_actions.no_reply import NoReplyAction - NoReplyAction._recent_interest_records.append(accumulated_interest) + self.recent_interest_records.append(accumulated_interest) logger.info( - f"{self.context.log_prefix} 累计兴趣值达到{accumulated_interest:.2f}(>{5 / talk_frequency}),结束等待" + f"{self.context.log_prefix} 累计兴趣值达到{accumulated_interest:.2f}(>{3 / talk_frequency}),结束等待" ) return True diff --git a/src/chat/heart_flow/heartflow_message_processor.py b/src/chat/heart_flow/heartflow_message_processor.py index 87c25c478..76d83ebac 100644 --- a/src/chat/heart_flow/heartflow_message_processor.py +++ b/src/chat/heart_flow/heartflow_message_processor.py @@ -37,7 +37,7 @@ async def _calculate_interest(message: MessageRecv) -> Tuple[float, bool, list[s with Timer("记忆激活"): interested_rate, keywords = await hippocampus_manager.get_activate_from_text( message.processed_plain_text, - max_depth=5, + max_depth=4, fast_retrieval=False, ) message.key_words = keywords diff --git a/src/chat/message_receive/message.py b/src/chat/message_receive/message.py index bc432760e..48181606a 100644 --- a/src/chat/message_receive/message.py +++ b/src/chat/message_receive/message.py @@ -120,6 +120,9 @@ class MessageRecv(Message): self.priority_mode = "interest" self.priority_info = None self.interest_value: float = 0.0 + + self.key_words = [] + self.key_words_lite = [] def update_chat_stream(self, chat_stream: "ChatStream"): self.chat_stream = chat_stream diff --git a/src/chat/message_receive/storage.py b/src/chat/message_receive/storage.py index 75117cb4e..69fd488e8 100644 --- a/src/chat/message_receive/storage.py +++ b/src/chat/message_receive/storage.py @@ -19,7 +19,7 @@ class MessageStorage: def _serialize_keywords(keywords) -> str: """将关键词列表序列化为JSON字符串""" if isinstance(keywords, list): - return json.dumps(keywords, ensure_ascii=False) + return orjson.dumps(keywords).decode("utf-8") return "[]" @staticmethod @@ -28,8 +28,8 @@ class MessageStorage: if not keywords_str: return [] try: - return json.loads(keywords_str) - except (json.JSONDecodeError, TypeError): + return orjson.loads(keywords_str) + except (orjson.JSONDecodeError, TypeError): return [] @staticmethod @@ -64,7 +64,6 @@ class MessageStorage: is_command = False key_words = "" key_words_lite = "" - selected_expressions = message.selected_expressions else: filtered_display_message = "" interest_value = message.interest_value @@ -79,8 +78,7 @@ class MessageStorage: # 序列化关键词列表为JSON字符串 key_words = MessageStorage._serialize_keywords(message.key_words) key_words_lite = MessageStorage._serialize_keywords(message.key_words_lite) - selected_expressions = "" - + chat_info_dict = chat_stream.to_dict() user_info_dict = message.message_info.user_info.to_dict() # type: ignore @@ -130,7 +128,6 @@ class MessageStorage: is_command=is_command, key_words=key_words, key_words_lite=key_words_lite, - selected_expressions=selected_expressions, ) with get_db_session() as session: session.add(new_message) diff --git a/src/common/database/sqlalchemy_models.py b/src/common/database/sqlalchemy_models.py index b134e23be..d9948408a 100644 --- a/src/common/database/sqlalchemy_models.py +++ b/src/common/database/sqlalchemy_models.py @@ -128,6 +128,8 @@ class Messages(Base): chat_id = Column(get_string_field(64), nullable=False, index=True) reply_to = Column(Text, nullable=True) interest_value = Column(Float, nullable=True) + key_words = Column(Text, nullable=True) + key_words_lite = Column(Text, nullable=True) is_mentioned = Column(Boolean, nullable=True) # 从 chat_info 扁平化而来的字段 diff --git a/src/config/official_configs.py b/src/config/official_configs.py index c89c8af6b..204fc60ac 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -114,11 +114,7 @@ class ChatConfig(ValidatedConfigBase): # 检查全局时段配置(第一个元素为空字符串的配置) global_frequency = self._get_global_frequency() - if global_frequency is not None: - return global_frequency - - # 如果都没有匹配,返回默认值 - return self.talk_frequency + return self.talk_frequency if global_frequency is None else global_frequency def _get_time_based_frequency(self, time_freq_list: list[str]) -> Optional[float]: """ diff --git a/src/plugins/built_in/core_actions/no_reply.py b/src/plugins/built_in/core_actions/no_reply.py index fd7f590da..7e80f9409 100644 --- a/src/plugins/built_in/core_actions/no_reply.py +++ b/src/plugins/built_in/core_actions/no_reply.py @@ -1,5 +1,4 @@ -from typing import Tuple, List -from collections import deque +from typing import Tuple # 导入新插件系统 from src.plugin_system import BaseAction, ActionActivationType, ChatMode @@ -23,11 +22,10 @@ class NoReplyAction(BaseAction): action_name = "no_reply" action_description = "暂时不回复消息" - # 最近三次no_reply的新消息兴趣度记录 - _recent_interest_records: deque = deque(maxlen=3) - # 动作参数定义 - action_parameters = {} + action_parameters = { + "reason": "不回复的原因", + } # 动作使用场景 action_require = [""] @@ -60,14 +58,3 @@ class NoReplyAction(BaseAction): action_done=True, ) return False, f"不回复动作执行失败: {e}" - - @classmethod - def reset_consecutive_count(cls): - """重置连续计数器和兴趣度记录""" - cls._recent_interest_records.clear() - logger.debug("NoReplyAction连续计数器和兴趣度记录已重置") - - @classmethod - def get_recent_interest_records(cls) -> List[float]: - """获取最近的兴趣度记录""" - return list(cls._recent_interest_records)