diff --git a/plugins/hello_world_plugin/plugin.py b/plugins/hello_world_plugin/plugin.py index 11ff22bd8..8ede9616a 100644 --- a/plugins/hello_world_plugin/plugin.py +++ b/plugins/hello_world_plugin/plugin.py @@ -20,6 +20,7 @@ class HelloAction(BaseAction): # === 基本信息(必须填写)=== action_name = "hello_greeting" action_description = "向用户发送问候消息" + activation_type = ActionActivationType.ALWAYS # 始终激活 # === 功能描述(必须填写)=== action_parameters = {"greeting_message": "要发送的问候消息"} @@ -44,8 +45,7 @@ class ByeAction(BaseAction): action_description = "向用户发送告别消息" # 使用关键词激活 - focus_activation_type = ActionActivationType.KEYWORD - normal_activation_type = ActionActivationType.KEYWORD + activation_type = ActionActivationType.KEYWORD # 关键词设置 activation_keywords = ["再见", "bye", "88", "拜拜"] @@ -75,8 +75,6 @@ class TimeCommand(BaseCommand): # === 命令设置(必须填写)=== command_pattern = r"^/time$" # 精确匹配 "/time" 命令 - command_help = "查询当前时间" - command_examples = ["/time"] async def execute(self) -> Tuple[bool, str, bool]: """执行时间查询""" diff --git a/scripts/interest_value_analysis.py b/scripts/interest_value_analysis.py index 19007f68a..fba1f160d 100644 --- a/scripts/interest_value_analysis.py +++ b/scripts/interest_value_analysis.py @@ -3,10 +3,10 @@ import sys import os from typing import Dict, List, Tuple, Optional from datetime import datetime -from src.common.database.database_model import Messages, ChatStreams # Add project root to Python path project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, project_root) +from src.common.database.database_model import Messages, ChatStreams #noqa diff --git a/src/chat/planner_actions/action_modifier.py b/src/chat/planner_actions/action_modifier.py index c7964edc9..dce706783 100644 --- a/src/chat/planner_actions/action_modifier.py +++ b/src/chat/planner_actions/action_modifier.py @@ -438,94 +438,4 @@ class ActionModifier: return True else: logger.debug(f"{self.log_prefix}动作 {action_name} 未匹配到任何关键词: {activation_keywords}") - return False - - # async def analyze_loop_actions(self, history_loop: List[CycleDetail]) -> List[tuple[str, str]]: - # """分析最近的循环内容并决定动作的移除 - - # Returns: - # List[Tuple[str, str]]: 包含要删除的动作及原因的元组列表 - # [("action3", "some reason")] - # """ - # removals = [] - - # # 获取最近10次循环 - # recent_cycles = history_loop[-10:] if len(history_loop) > 10 else history_loop - # if not recent_cycles: - # return removals - - # reply_sequence = [] # 记录最近的动作序列 - - # for cycle in recent_cycles: - # action_result = cycle.loop_plan_info.get("action_result", {}) - # action_type = action_result.get("action_type", "unknown") - # reply_sequence.append(action_type == "reply") - - # # 计算连续回复的相关阈值 - - # max_reply_num = int(global_config.focus_chat.consecutive_replies * 3.2) - # sec_thres_reply_num = int(global_config.focus_chat.consecutive_replies * 2) - # one_thres_reply_num = int(global_config.focus_chat.consecutive_replies * 1.5) - - # # 获取最近max_reply_num次的reply状态 - # if len(reply_sequence) >= max_reply_num: - # last_max_reply_num = reply_sequence[-max_reply_num:] - # else: - # last_max_reply_num = reply_sequence[:] - - # # 详细打印阈值和序列信息,便于调试 - # logger.info( - # f"连续回复阈值: max={max_reply_num}, sec={sec_thres_reply_num}, one={one_thres_reply_num}," - # f"最近reply序列: {last_max_reply_num}" - # ) - # # print(f"consecutive_replies: {consecutive_replies}") - - # # 根据最近的reply情况决定是否移除reply动作 - # if len(last_max_reply_num) >= max_reply_num and all(last_max_reply_num): - # # 如果最近max_reply_num次都是reply,直接移除 - # reason = f"连续回复过多(最近{len(last_max_reply_num)}次全是reply,超过阈值{max_reply_num})" - # removals.append(("reply", reason)) - # # reply_count = len(last_max_reply_num) - no_reply_count - # elif len(last_max_reply_num) >= sec_thres_reply_num and all(last_max_reply_num[-sec_thres_reply_num:]): - # # 如果最近sec_thres_reply_num次都是reply,40%概率移除 - # removal_probability = 0.4 / global_config.focus_chat.consecutive_replies - # if random.random() < removal_probability: - # reason = ( - # f"连续回复较多(最近{sec_thres_reply_num}次全是reply,{removal_probability:.2f}概率移除,触发移除)" - # ) - # removals.append(("reply", reason)) - # elif len(last_max_reply_num) >= one_thres_reply_num and all(last_max_reply_num[-one_thres_reply_num:]): - # # 如果最近one_thres_reply_num次都是reply,20%概率移除 - # removal_probability = 0.2 / global_config.focus_chat.consecutive_replies - # if random.random() < removal_probability: - # reason = ( - # f"连续回复检测(最近{one_thres_reply_num}次全是reply,{removal_probability:.2f}概率移除,触发移除)" - # ) - # removals.append(("reply", reason)) - # else: - # logger.debug(f"{self.log_prefix}连续回复检测:无需移除reply动作,最近回复模式正常") - - # return removals - - # def get_available_actions_count(self, mode: str = "focus") -> int: - # """获取当前可用动作数量(排除默认的no_action)""" - # current_actions = self.action_manager.get_using_actions_for_mode(mode) - # # 排除no_action(如果存在) - # filtered_actions = {k: v for k, v in current_actions.items() if k != "no_action"} - # return len(filtered_actions) - - # def should_skip_planning_for_no_reply(self) -> bool: - # """判断是否应该跳过规划过程""" - # current_actions = self.action_manager.get_using_actions_for_mode("focus") - # # 排除no_action(如果存在) - # if len(current_actions) == 1 and "no_reply" in current_actions: - # return True - # return False - - # def should_skip_planning_for_no_action(self) -> bool: - # """判断是否应该跳过规划过程""" - # available_count = self.action_manager.get_using_actions_for_mode("normal") - # if available_count == 0: - # logger.debug(f"{self.log_prefix} 没有可用动作,跳过规划") - # return True - # return False + return False \ No newline at end of file diff --git a/src/chat/planner_actions/planner.py b/src/chat/planner_actions/planner.py index e3d1edef9..a679c4953 100644 --- a/src/chat/planner_actions/planner.py +++ b/src/chat/planner_actions/planner.py @@ -40,7 +40,6 @@ def init_prompt(): {moderation_prompt} 现在请你根据{by_what}选择合适的action和触发action的消息: -你刚刚选择并执行过的action是: {actions_before_now_block} {no_action_block} @@ -130,17 +129,18 @@ class ActionPlanner: logger.warning(f"{self.log_prefix}使用中的动作 {action_name} 未在已注册动作中找到") # 如果没有可用动作或只有no_reply动作,直接返回no_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 + # 因为现在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( @@ -268,6 +268,7 @@ class ActionPlanner: actions_before_now = get_actions_by_timestamp_with_chat( chat_id=self.chat_id, + timestamp_start=time.time()-3600, timestamp_end=time.time(), limit=5, ) @@ -275,6 +276,8 @@ class ActionPlanner: actions_before_now_block = build_readable_actions( actions=actions_before_now, ) + + actions_before_now_block = f"你刚刚选择并执行过的action是:\n{actions_before_now_block}" self.last_obs_time_mark = time.time() @@ -288,7 +291,7 @@ class ActionPlanner: by_what = "聊天内容" target_prompt = '\n "target_message_id":"触发action的消息id"' - no_action_block = f"""重要说明1: + no_action_block = f"""重要说明: - 'no_reply' 表示只进行不进行回复,等待合适的回复时机 - 当你刚刚发送了消息,没有人回复时,选择no_reply - 当你一次发送了太多消息,为了避免打扰聊天节奏,选择no_reply diff --git a/src/person_info/relationship_builder.py b/src/person_info/relationship_builder.py index 69b9e84d2..5bf689910 100644 --- a/src/person_info/relationship_builder.py +++ b/src/person_info/relationship_builder.py @@ -419,7 +419,7 @@ class RelationshipBuilder: async def update_impression_on_segments(self, person_id: str, chat_id: str, segments: List[Dict[str, Any]]): """基于消息段更新用户印象""" original_segment_count = len(segments) - logger.info(f"开始为 {person_id} 基于 {original_segment_count} 个消息段更新印象") + logger.debug(f"开始为 {person_id} 基于 {original_segment_count} 个消息段更新印象") try: # 筛选要处理的消息段,每个消息段有10%的概率被丢弃 segments_to_process = [s for s in segments if random.random() >= 0.1] @@ -432,7 +432,7 @@ class RelationshipBuilder: dropped_count = original_segment_count - len(segments_to_process) if dropped_count > 0: - logger.info(f"为 {person_id} 随机丢弃了 {dropped_count} / {original_segment_count} 个消息段") + logger.debug(f"为 {person_id} 随机丢弃了 {dropped_count} / {original_segment_count} 个消息段") processed_messages = [] diff --git a/src/plugin_system/base/base_command.py b/src/plugin_system/base/base_command.py index b79f68845..60ee99add 100644 --- a/src/plugin_system/base/base_command.py +++ b/src/plugin_system/base/base_command.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Dict, Tuple, Optional, List +from typing import Dict, Tuple, Optional from src.common.logger import get_logger from src.plugin_system.base.component_types import CommandInfo, ComponentType from src.chat.message_receive.message import MessageRecv @@ -26,9 +26,6 @@ class BaseCommand(ABC): # 默认命令设置 command_pattern: str = r"" """命令匹配的正则表达式""" - command_help: str = "" - """命令帮助信息""" - command_examples: List[str] = [] def __init__(self, message: MessageRecv, plugin_config: Optional[dict] = None): """初始化Command组件 @@ -228,6 +225,4 @@ class BaseCommand(ABC): component_type=ComponentType.COMMAND, description=cls.command_description, command_pattern=cls.command_pattern, - command_help=cls.command_help, - command_examples=cls.command_examples.copy() if cls.command_examples else [], ) diff --git a/src/plugin_system/base/component_types.py b/src/plugin_system/base/component_types.py index 74b01ddd7..eeb2a5a08 100644 --- a/src/plugin_system/base/component_types.py +++ b/src/plugin_system/base/component_types.py @@ -140,13 +140,9 @@ class CommandInfo(ComponentInfo): """命令组件信息""" command_pattern: str = "" # 命令匹配模式(正则表达式) - command_help: str = "" # 命令帮助信息 - command_examples: List[str] = field(default_factory=list) # 命令使用示例 def __post_init__(self): super().__post_init__() - if self.command_examples is None: - self.command_examples = [] self.component_type = ComponentType.COMMAND diff --git a/src/plugin_system/core/events_manager.py b/src/plugin_system/core/events_manager.py index 1f01b4ab4..3c215a7ff 100644 --- a/src/plugin_system/core/events_manager.py +++ b/src/plugin_system/core/events_manager.py @@ -182,17 +182,17 @@ class EventsManager: async def cancel_handler_tasks(self, handler_name: str) -> None: tasks_to_be_cancelled = self._handler_tasks.get(handler_name, []) - remaining_tasks = [task for task in tasks_to_be_cancelled if not task.done()] - for task in remaining_tasks: - task.cancel() - try: - await asyncio.wait_for(asyncio.gather(*remaining_tasks, return_exceptions=True), timeout=5) - logger.info(f"已取消事件处理器 {handler_name} 的所有任务") - except asyncio.TimeoutError: - logger.warning(f"取消事件处理器 {handler_name} 的任务超时,开始强制取消") - except Exception as e: - logger.error(f"取消事件处理器 {handler_name} 的任务时发生异常: {e}") - finally: + if remaining_tasks := [task for task in tasks_to_be_cancelled if not task.done()]: + for task in remaining_tasks: + task.cancel() + try: + await asyncio.wait_for(asyncio.gather(*remaining_tasks, return_exceptions=True), timeout=5) + logger.info(f"已取消事件处理器 {handler_name} 的所有任务") + except asyncio.TimeoutError: + logger.warning(f"取消事件处理器 {handler_name} 的任务超时,开始强制取消") + except Exception as e: + logger.error(f"取消事件处理器 {handler_name} 的任务时发生异常: {e}") + if handler_name in self._handler_tasks: del self._handler_tasks[handler_name] async def unregister_event_subscriber(self, handler_name: str) -> bool: diff --git a/src/plugins/built_in/core_actions/emoji.py b/src/plugins/built_in/core_actions/emoji.py index d44183c83..4563b47f8 100644 --- a/src/plugins/built_in/core_actions/emoji.py +++ b/src/plugins/built_in/core_actions/emoji.py @@ -20,8 +20,7 @@ class EmojiAction(BaseAction): """表情动作 - 发送表情包""" # 激活设置 - focus_activation_type = ActionActivationType.RANDOM - normal_activation_type = ActionActivationType.RANDOM + activation_type = ActionActivationType.RANDOM mode_enable = ChatMode.ALL parallel_action = True random_activation_probability = 0.2 # 默认值,可通过配置覆盖