From e9be27d87473954199ce6617715ababafe41312e Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Sat, 26 Jul 2025 19:18:49 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix=EF=BC=9A=E6=97=A0=E5=8F=AF=E7=94=A8?= =?UTF-8?q?=E5=8A=A8=E4=BD=9C=E4=B8=8Bnormal=E4=BB=8D=E6=97=A7plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat_loop/heartFC_chat.py | 64 +++++++++++++++------ src/chat/planner_actions/planner.py | 14 ----- src/plugins/built_in/core_actions/emoji.py | 8 ++- src/plugins/built_in/core_actions/plugin.py | 9 --- 4 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/chat/chat_loop/heartFC_chat.py b/src/chat/chat_loop/heartFC_chat.py index 31e5b94d1..4b6141a50 100644 --- a/src/chat/chat_loop/heartFC_chat.py +++ b/src/chat/chat_loop/heartFC_chat.py @@ -283,25 +283,55 @@ class HeartFChatting: except Exception as e: logger.error(f"{self.log_prefix} 动作修改失败: {e}") - # 如果normal,开始一个回复生成进程,先准备好回复(其实是和planer同时进行的) - gen_task = None - reply_to_str = "" + # 检查是否在normal模式下没有可用动作(除了reply相关动作) + skip_planner = False if self.loop_mode == ChatMode.NORMAL: - reply_to_str = await self.build_reply_to_str(message_data) - gen_task = asyncio.create_task(self._generate_response(message_data, available_actions, reply_to_str, "chat.replyer.normal")) + # 过滤掉reply相关的动作,检查是否还有其他动作 + non_reply_actions = {k: v for k, v in available_actions.items() + if k not in ['reply', 'no_reply', 'no_action']} + + if not non_reply_actions: + skip_planner = True + logger.info(f"{self.log_prefix} Normal模式下没有可用动作,直接回复") + + # 直接设置为reply动作 + action_type = "reply" + reasoning = "" + action_data = {"loop_start_time": loop_start_time} + is_parallel = False + + # 构建plan_result用于后续处理 + plan_result = { + "action_result": { + "action_type": action_type, + "action_data": action_data, + "reasoning": reasoning, + "timestamp": time.time(), + "is_parallel": is_parallel, + }, + "action_prompt": "", + } + target_message = message_data + # 如果normal,开始一个回复生成进程,先准备好回复(其实是和planer同时进行的) + gen_task = None + reply_to_str = "" + if self.loop_mode == ChatMode.NORMAL: + reply_to_str = await self.build_reply_to_str(message_data) + gen_task = asyncio.create_task(self._generate_response(message_data, available_actions, reply_to_str, "chat.replyer.normal")) + + if not skip_planner: + with Timer("规划器", cycle_timers): + plan_result, target_message = await self.action_planner.plan(mode=self.loop_mode) - with Timer("规划器", cycle_timers): - plan_result, target_message = await self.action_planner.plan(mode=self.loop_mode) + action_result: dict = plan_result.get("action_result", {}) # type: ignore + action_type, action_data, reasoning, is_parallel = ( + action_result.get("action_type", "error"), + action_result.get("action_data", {}), + action_result.get("reasoning", "未提供理由"), + action_result.get("is_parallel", True), + ) - action_result: dict = plan_result.get("action_result", {}) # type: ignore - action_type, action_data, reasoning, is_parallel = ( - action_result.get("action_type", "error"), - action_result.get("action_data", {}), - action_result.get("reasoning", "未提供理由"), - action_result.get("is_parallel", True), - ) - - action_data["loop_start_time"] = loop_start_time + action_data["loop_start_time"] = loop_start_time if action_type == "reply": @@ -358,7 +388,7 @@ class HeartFChatting: with Timer("回复发送", cycle_timers): reply_text = await self._send_response(response_set, reply_to_str, loop_start_time, action_message) - # 存储reply action信息 (focus模式) + # 存储reply action信息 person_info_manager = get_person_info_manager() person_id = person_info_manager.get_person_id( action_message.get("chat_info_platform", ""), diff --git a/src/chat/planner_actions/planner.py b/src/chat/planner_actions/planner.py index 4e33bafc8..d4c3feb36 100644 --- a/src/chat/planner_actions/planner.py +++ b/src/chat/planner_actions/planner.py @@ -129,20 +129,6 @@ class ActionPlanner: else: logger.warning(f"{self.log_prefix}使用中的动作 {action_name} 未在已注册动作中找到") - # 如果没有可用动作或只有no_reply动作,直接返回no_reply - # 因为现在reply是永远激活,所以不需要空跳判定 - # if not current_available_actions: - # action = "no_reply" if mode == ChatMode.FOCUS else "no_action" - # reasoning = "没有可用的动作" - # logger.info(f"{self.log_prefix}{reasoning}") - # return { - # "action_result": { - # "action_type": action, - # "action_data": action_data, - # "reasoning": reasoning, - # }, - # }, None - # --- 构建提示词 (调用修改后的 PromptBuilder 方法) --- prompt, message_id_list = await self.build_planner_prompt( is_group_chat=is_group_chat, # <-- Pass HFC state diff --git a/src/plugins/built_in/core_actions/emoji.py b/src/plugins/built_in/core_actions/emoji.py index 1c6b9c267..fa922dc1f 100644 --- a/src/plugins/built_in/core_actions/emoji.py +++ b/src/plugins/built_in/core_actions/emoji.py @@ -21,10 +21,14 @@ class EmojiAction(BaseAction): """表情动作 - 发送表情包""" # 激活设置 - activation_type = ActionActivationType.RANDOM + if global_config.emoji.emoji_activate_type == "llm": + activation_type = ActionActivationType.LLM_JUDGE + random_activation_probability = 0 + else: + activation_type = ActionActivationType.RANDOM + random_activation_probability = global_config.emoji.emoji_chance mode_enable = ChatMode.ALL parallel_action = True - random_activation_probability = 0.2 # 默认值,可通过配置覆盖 # 动作基本信息 action_name = "emoji" diff --git a/src/plugins/built_in/core_actions/plugin.py b/src/plugins/built_in/core_actions/plugin.py index 5bf80af33..952be0a13 100644 --- a/src/plugins/built_in/core_actions/plugin.py +++ b/src/plugins/built_in/core_actions/plugin.py @@ -62,14 +62,6 @@ class CoreActionsPlugin(BasePlugin): def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]: """返回插件包含的组件列表""" - if global_config.emoji.emoji_activate_type == "llm": - EmojiAction.random_activation_probability = 0.0 - EmojiAction.activation_type = ActionActivationType.LLM_JUDGE - - elif global_config.emoji.emoji_activate_type == "random": - EmojiAction.random_activation_probability = global_config.emoji.emoji_chance - EmojiAction.activation_type = ActionActivationType.RANDOM - # --- 根据配置注册组件 --- components = [] if self.get_config("components.enable_no_reply", True): @@ -77,6 +69,5 @@ class CoreActionsPlugin(BasePlugin): if self.get_config("components.enable_emoji", True): components.append((EmojiAction.get_action_info(), EmojiAction)) - # components.append((DeepReplyAction.get_action_info(), DeepReplyAction)) return components From b3e8fa7058035a391e43d1d814eda095048f7ba7 Mon Sep 17 00:00:00 2001 From: UnCLAS-Prommer Date: Sat, 26 Jul 2025 19:23:21 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=AE=A9activation=E6=A6=82=E7=8E=87?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E4=B8=BA0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/planner_actions/action_manager.py | 7 +------ src/chat/planner_actions/action_modifier.py | 2 +- src/plugin_system/apis/chat_api.py | 7 +++++-- src/plugin_system/apis/generator_api.py | 2 +- src/plugin_system/base/base_action.py | 2 +- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/chat/planner_actions/action_manager.py b/src/chat/planner_actions/action_manager.py index 37f939b92..21d47c75d 100644 --- a/src/chat/planner_actions/action_manager.py +++ b/src/chat/planner_actions/action_manager.py @@ -3,7 +3,7 @@ from src.plugin_system.base.base_action import BaseAction from src.chat.message_receive.chat_stream import ChatStream from src.common.logger import get_logger from src.plugin_system.core.component_registry import component_registry -from src.plugin_system.base.component_types import ComponentType, ActionActivationType, ChatMode, ActionInfo +from src.plugin_system.base.component_types import ComponentType, ActionInfo logger = get_logger("action_manager") @@ -15,11 +15,6 @@ class ActionManager: 现在统一使用新插件系统,简化了原有的新旧兼容逻辑。 """ - # 类常量 - DEFAULT_RANDOM_PROBABILITY = 0.3 - DEFAULT_MODE = ChatMode.ALL - DEFAULT_ACTIVATION_TYPE = ActionActivationType.ALWAYS - def __init__(self): """初始化动作管理器""" diff --git a/src/chat/planner_actions/action_modifier.py b/src/chat/planner_actions/action_modifier.py index dce706783..da11c54f6 100644 --- a/src/chat/planner_actions/action_modifier.py +++ b/src/chat/planner_actions/action_modifier.py @@ -174,7 +174,7 @@ class ActionModifier: continue # 总是激活,无需处理 elif activation_type == ActionActivationType.RANDOM: - probability = action_info.random_activation_probability or ActionManager.DEFAULT_RANDOM_PROBABILITY + probability = action_info.random_activation_probability if random.random() >= probability: reason = f"RANDOM类型未触发(概率{probability})" deactivated_actions.append((action_name, reason)) diff --git a/src/plugin_system/apis/chat_api.py b/src/plugin_system/apis/chat_api.py index 35a210faa..7a3f0941c 100644 --- a/src/plugin_system/apis/chat_api.py +++ b/src/plugin_system/apis/chat_api.py @@ -32,6 +32,7 @@ class ChatManager: @staticmethod def get_all_streams(platform: Optional[str] | SpecialTypes = "qq") -> List[ChatStream]: + # sourcery skip: for-append-to-extend """获取所有聊天流 Args: @@ -57,6 +58,7 @@ class ChatManager: @staticmethod def get_group_streams(platform: Optional[str] | SpecialTypes = "qq") -> List[ChatStream]: + # sourcery skip: for-append-to-extend """获取所有群聊聊天流 Args: @@ -79,6 +81,7 @@ class ChatManager: @staticmethod def get_private_streams(platform: Optional[str] | SpecialTypes = "qq") -> List[ChatStream]: + # sourcery skip: for-append-to-extend """获取所有私聊聊天流 Args: @@ -105,7 +108,7 @@ class ChatManager: @staticmethod def get_group_stream_by_group_id( group_id: str, platform: Optional[str] | SpecialTypes = "qq" - ) -> Optional[ChatStream]: + ) -> Optional[ChatStream]: # sourcery skip: remove-unnecessary-cast """根据群ID获取聊天流 Args: @@ -142,7 +145,7 @@ class ChatManager: @staticmethod def get_private_stream_by_user_id( user_id: str, platform: Optional[str] | SpecialTypes = "qq" - ) -> Optional[ChatStream]: + ) -> Optional[ChatStream]: # sourcery skip: remove-unnecessary-cast """根据用户ID获取私聊流 Args: diff --git a/src/plugin_system/apis/generator_api.py b/src/plugin_system/apis/generator_api.py index 60ab7d5bb..5ee9e4036 100644 --- a/src/plugin_system/apis/generator_api.py +++ b/src/plugin_system/apis/generator_api.py @@ -108,7 +108,7 @@ async def generate_reply( logger.debug("[GeneratorAPI] 开始生成回复") - if not reply_to: + if not reply_to and action_data: reply_to = action_data.get("reply_to", "") if not extra_info and action_data: extra_info = action_data.get("extra_info", "") diff --git a/src/plugin_system/base/base_action.py b/src/plugin_system/base/base_action.py index c108c5d86..7acd14a48 100644 --- a/src/plugin_system/base/base_action.py +++ b/src/plugin_system/base/base_action.py @@ -384,7 +384,7 @@ class BaseAction(ABC): keyword_case_sensitive=getattr(cls, "keyword_case_sensitive", False), mode_enable=getattr(cls, "mode_enable", ChatMode.ALL), parallel_action=getattr(cls, "parallel_action", True), - random_activation_probability=getattr(cls, "random_activation_probability", 0.3), + random_activation_probability=getattr(cls, "random_activation_probability", 0.0), llm_judge_prompt=getattr(cls, "llm_judge_prompt", ""), # 使用正确的字段名 action_parameters=getattr(cls, "action_parameters", {}).copy(),