From 37ef10f499d3fca25574acb2d373558f122a7b7a Mon Sep 17 00:00:00 2001 From: Furina-1013-create <189647097+Furina-1013-create@users.noreply.github.com> Date: Sun, 14 Sep 2025 23:45:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dreply=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E7=BC=BA=E5=B0=91action=5Fmessage=E7=9A=84=E9=87=8D=E5=A4=A7?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/chat_loop/cycle_processor.py | 12 +++++++++++- src/chat/planner_actions/plan_filter.py | 8 ++++++++ src/chat/planner_actions/planner.py | 11 ++++++++++- src/chat/replyer/default_generator.py | 26 +++++++++++++++++++++++++ src/chat/utils/prompt.py | 2 +- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/chat/chat_loop/cycle_processor.py b/src/chat/chat_loop/cycle_processor.py index 3748c5780..7dcf34bd3 100644 --- a/src/chat/chat_loop/cycle_processor.py +++ b/src/chat/chat_loop/cycle_processor.py @@ -302,8 +302,18 @@ class CycleProcessor: if not action_message: logger.warning(f"{self.log_prefix} reply 动作缺少 action_message,跳过") continue + + # 检查是否是空的DatabaseMessages对象 + if hasattr(action_message, 'chat_info') and hasattr(action_message.chat_info, 'user_info'): + target_user_id = action_message.chat_info.user_info.user_id + else: + # 如果是字典格式,使用原来的方式 + target_user_id = action_message.get("chat_info_user_id", "") + + if not target_user_id: + logger.warning(f"{self.log_prefix} reply 动作的 action_message 缺少用户ID,跳过") + continue - target_user_id = action_message.get("chat_info_user_id","") if target_user_id == global_config.bot.qq_account and not global_config.chat.allow_reply_self: logger.warning("选取的reply的目标为bot自己,跳过reply action") continue diff --git a/src/chat/planner_actions/plan_filter.py b/src/chat/planner_actions/plan_filter.py index 838320700..53e1e4a80 100644 --- a/src/chat/planner_actions/plan_filter.py +++ b/src/chat/planner_actions/plan_filter.py @@ -263,7 +263,15 @@ class PlanFilter: target_message_dict = self._get_latest_message(message_id_list) if target_message_dict: + # 直接使用字典作为action_message,避免DatabaseMessages对象创建失败 target_message_obj = target_message_dict + else: + # 如果找不到目标消息,对于reply动作来说这是必需的,应该记录警告 + if action == "reply": + logger.warning(f"reply动作找不到目标消息,target_message_id: {action_json.get('target_message_id')}") + # 将reply动作改为no_action,避免后续执行时出错 + action = "no_action" + reasoning = f"找不到目标消息进行回复。原始理由: {reasoning}" available_action_names = list(plan.available_actions.keys()) if action not in ["no_action", "no_reply", "reply", "do_nothing", "proactive_reply"] and action not in available_action_names: diff --git a/src/chat/planner_actions/planner.py b/src/chat/planner_actions/planner.py index b69f3a2ba..8e4f18fae 100644 --- a/src/chat/planner_actions/planner.py +++ b/src/chat/planner_actions/planner.py @@ -82,6 +82,15 @@ class ActionPlanner: ) final_actions_dict = [asdict(act) for act in final_actions] - final_target_message_dict = asdict(final_target_message) if final_target_message else None + # action_message现在可能是字典而不是dataclass实例,需要特殊处理 + if final_target_message: + if hasattr(final_target_message, '__dataclass_fields__'): + # 如果是dataclass实例,使用asdict转换 + final_target_message_dict = asdict(final_target_message) + else: + # 如果已经是字典,直接使用 + final_target_message_dict = final_target_message + else: + final_target_message_dict = None return final_actions_dict, final_target_message_dict diff --git a/src/chat/replyer/default_generator.py b/src/chat/replyer/default_generator.py index a5da7bdeb..818bceb00 100644 --- a/src/chat/replyer/default_generator.py +++ b/src/chat/replyer/default_generator.py @@ -594,6 +594,9 @@ class DefaultReplyer: def _parse_reply_target(self, target_message: str) -> Tuple[str, str]: """解析回复目标消息 - 使用共享工具""" from src.chat.utils.prompt import Prompt + if target_message is None: + logger.warning("target_message为None,返回默认值") + return "未知用户", "(无消息内容)" return Prompt.parse_reply_target(target_message) async def build_keywords_reaction_prompt(self, target: Optional[str]) -> str: @@ -872,6 +875,13 @@ class DefaultReplyer: ) person_name = await person_info_manager.get_value(person_id, "person_name") + # 如果person_name为None,使用fallback值 + if person_name is None: + # 尝试从reply_message获取用户名 + fallback_name = reply_message.get("user_nickname") or reply_message.get("user_id", "未知用户") + logger.warning(f"无法获取person_name,使用fallback: {fallback_name}") + person_name = str(fallback_name) + # 检查是否是bot自己的名字,如果是则替换为"(你)" bot_user_id = str(global_config.bot.qq_account) current_user_id = person_info_manager.get_value_sync(person_id, "user_id") @@ -884,6 +894,14 @@ class DefaultReplyer: sender = person_name target = reply_message.get("processed_plain_text") + # 最终的空值检查,确保sender和target不为None + if sender is None: + logger.warning("sender为None,使用默认值'未知用户'") + sender = "未知用户" + if target is None: + logger.warning("target为None,使用默认值'(无消息内容)'") + target = "(无消息内容)" + person_info_manager = get_person_info_manager() person_id = person_info_manager.get_person_id_by_person_name(sender) platform = chat_stream.platform @@ -1112,6 +1130,14 @@ class DefaultReplyer: else: sender, target = self._parse_reply_target(reply_to) + # 添加空值检查,确保sender和target不为None + if sender is None: + logger.warning("build_rewrite_context: sender为None,使用默认值'未知用户'") + sender = "未知用户" + if target is None: + logger.warning("build_rewrite_context: target为None,使用默认值'(无消息内容)'") + target = "(无消息内容)" + # 添加情绪状态获取 if global_config.mood.enable_mood: chat_mood = mood_manager.get_mood_by_chat_id(chat_id) diff --git a/src/chat/utils/prompt.py b/src/chat/utils/prompt.py index dd4fee364..217a2071b 100644 --- a/src/chat/utils/prompt.py +++ b/src/chat/utils/prompt.py @@ -757,7 +757,7 @@ class Prompt: "cross_context_block": context_data.get("cross_context_block", ""), "identity": self.parameters.identity_block or context_data.get("identity", ""), "action_descriptions": self.parameters.action_descriptions or context_data.get("action_descriptions", ""), - "sender_name": self.parameters.sender, + "sender_name": self.parameters.sender or "未知用户", "mood_state": self.parameters.mood_prompt or context_data.get("mood_state", ""), "background_dialogue_prompt": context_data.get("background_dialogue_prompt", ""), "time_block": context_data.get("time_block", ""),