From ef24f013de0a73b6688b1b3ef4e28383022fd10f Mon Sep 17 00:00:00 2001 From: Bakadax Date: Mon, 28 Apr 2025 16:41:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAPFC=E7=9A=84=E8=BE=93=E5=87=BA?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=B9=E6=98=93=E5=8C=BA=E5=88=86=E7=9A=84?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E6=B5=81=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/action_planner.py | 49 ++++----- src/plugins/PFC/chat_observer.py | 35 +++--- src/plugins/PFC/conversation.py | 136 ++++++++++++------------ src/plugins/PFC/message_sender.py | 5 +- src/plugins/PFC/observation_info.py | 16 +-- src/plugins/PFC/pfc.py | 32 +++--- src/plugins/PFC/pfc_KnowledgeFetcher.py | 9 +- src/plugins/PFC/pfc_manager.py | 21 ++-- src/plugins/PFC/pfc_utils.py | 15 +-- src/plugins/PFC/reply_checker.py | 19 ++-- src/plugins/PFC/reply_generator.py | 16 +-- src/plugins/PFC/waiter.py | 22 ++-- 12 files changed, 193 insertions(+), 182 deletions(-) diff --git a/src/plugins/PFC/action_planner.py b/src/plugins/PFC/action_planner.py index 238382a31..161bc0d0a 100644 --- a/src/plugins/PFC/action_planner.py +++ b/src/plugins/PFC/action_planner.py @@ -97,7 +97,7 @@ class ActionPlanner: self.identity_detail_info = Individuality.get_instance().get_prompt(type="identity", x_person=2, level=2) self.name = global_config.BOT_NICKNAME self.private_name = private_name - self.chat_observer = ChatObserver.get_instance(stream_id) + self.chat_observer = ChatObserver.get_instance(stream_id, private_name) # self.action_planner_info = ActionPlannerInfo() # 移除未使用的变量 # 修改 plan 方法签名,增加 last_successful_reply_action 参数 @@ -138,11 +138,11 @@ class ActionPlanner: ) break else: - logger.debug("Observation info chat history is empty or not available for bot time check.") + logger.debug(f"[私聊][{self.private_name}]Observation info chat history is empty or not available for bot time check.") except AttributeError: - logger.warning("ObservationInfo object might not have chat_history attribute yet for bot time check.") + logger.warning(f"[私聊][{self.private_name}]ObservationInfo object might not have chat_history attribute yet for bot time check.") except Exception as e: - logger.warning(f"获取 Bot 上次发言时间时出错: {e}") + logger.warning(f"[私聊][{self.private_name}]获取 Bot 上次发言时间时出错: {e}") # --- 获取超时提示信息 --- # (这部分逻辑不变) @@ -159,14 +159,14 @@ class ActionPlanner: except Exception: timeout_context = "重要提示:对方已经长时间没有回复你的消息了(这可能代表对方繁忙/不想回复/没注意到你的消息等情况,或在对方看来本次聊天已告一段落),请基于此情况规划下一步。\n" else: - logger.debug("Conversation info goal_list is empty or not available for timeout check.") + logger.debug(f"[私聊][{self.private_name}]Conversation info goal_list is empty or not available for timeout check.") except AttributeError: - logger.warning("ConversationInfo object might not have goal_list attribute yet for timeout check.") + logger.warning(f"[私聊][{self.private_name}]ConversationInfo object might not have goal_list attribute yet for timeout check.") except Exception as e: - logger.warning(f"检查超时目标时出错: {e}") + logger.warning(f"[私聊][{self.private_name}]检查超时目标时出错: {e}") # --- 构建通用 Prompt 参数 --- - logger.debug(f"开始规划行动:当前目标: {getattr(conversation_info, 'goal_list', '不可用')}") + logger.debug(f"[私聊][{self.private_name}]开始规划行动:当前目标: {getattr(conversation_info, 'goal_list', '不可用')}") # 构建对话目标 (goals_str) goals_str = "" @@ -189,10 +189,10 @@ class ActionPlanner: else: goals_str = "- 目前没有明确对话目标,请考虑设定一个。\n" except AttributeError: - logger.warning("ConversationInfo object might not have goal_list attribute yet.") + logger.warning(f"[私聊][{self.private_name}]ConversationInfo object might not have goal_list attribute yet.") goals_str = "- 获取对话目标时出错。\n" except Exception as e: - logger.error(f"构建对话目标字符串时出错: {e}") + logger.error(f"[私聊][{self.private_name}]构建对话目标字符串时出错: {e}") goals_str = "- 构建对话目标时出错。\n" # 获取聊天历史记录 (chat_history_text) @@ -220,13 +220,13 @@ class ActionPlanner: ) else: logger.warning( - "ObservationInfo has new_messages_count > 0 but unprocessed_messages is empty or missing." + f"[私聊][{self.private_name}]ObservationInfo has new_messages_count > 0 but unprocessed_messages is empty or missing." ) except AttributeError: - logger.warning("ObservationInfo object might be missing expected attributes for chat history.") + logger.warning(f"[私聊][{self.private_name}]ObservationInfo object might be missing expected attributes for chat history.") chat_history_text = "获取聊天记录时出错。\n" except Exception as e: - logger.error(f"处理聊天记录时发生未知错误: {e}") + logger.error(f"[私聊][{self.private_name}]处理聊天记录时发生未知错误: {e}") chat_history_text = "处理聊天记录时出错。\n" # 构建 Persona 文本 (persona_text) @@ -255,11 +255,11 @@ class ActionPlanner: if hasattr(conversation_info, "done_action") and conversation_info.done_action: action_history_list = conversation_info.done_action[-5:] else: - logger.debug("Conversation info done_action is empty or not available.") + logger.debug(f"[私聊][{self.private_name}]Conversation info done_action is empty or not available.") except AttributeError: - logger.warning("ConversationInfo object might not have done_action attribute yet.") + logger.warning(f"[私聊][{self.private_name}]ConversationInfo object might not have done_action attribute yet.") except Exception as e: - logger.error(f"访问行动历史时出错: {e}") + logger.error(f"[私聊][{self.private_name}]访问行动历史时出错: {e}") if not action_history_list: action_history_summary += "- 还没有执行过行动。\n" @@ -316,10 +316,10 @@ class ActionPlanner: # --- 选择 Prompt --- if last_successful_reply_action in ["direct_reply", "send_new_message"]: prompt_template = PROMPT_FOLLOW_UP - logger.debug("使用 PROMPT_FOLLOW_UP (追问决策)") + logger.debug(f"[私聊][{self.private_name}]使用 PROMPT_FOLLOW_UP (追问决策)") else: prompt_template = PROMPT_INITIAL_REPLY - logger.debug("使用 PROMPT_INITIAL_REPLY (首次/非连续回复决策)") + logger.debug(f"[私聊][{self.private_name}]使用 PROMPT_INITIAL_REPLY (首次/非连续回复决策)") # --- 格式化最终的 Prompt --- prompt = prompt_template.format( @@ -332,13 +332,14 @@ class ActionPlanner: chat_history_text=chat_history_text if chat_history_text.strip() else "还没有聊天记录。", ) - logger.debug(f"发送到LLM的最终提示词:\n------\n{prompt}\n------") + logger.debug(f"[私聊][{self.private_name}]发送到LLM的最终提示词:\n------\n{prompt}\n------") try: content, _ = await self.llm.generate_response_async(prompt) - logger.debug(f"LLM原始返回内容: {content}") + logger.debug(f"[私聊][{self.private_name}]LLM原始返回内容: {content}") success, result = get_items_from_json( content, + self.private_name, "action", "reason", default_values={"action": "wait", "reason": "LLM返回格式错误或未提供原因,默认等待"}, @@ -360,14 +361,14 @@ class ActionPlanner: "block_and_ignore", ] if action not in valid_actions: - logger.warning(f"LLM返回了未知的行动类型: '{action}',强制改为 wait") + logger.warning(f"[私聊][{self.private_name}]LLM返回了未知的行动类型: '{action}',强制改为 wait") reason = f"(原始行动'{action}'无效,已强制改为wait) {reason}" action = "wait" - logger.info(f"规划的行动: {action}") - logger.info(f"行动原因: {reason}") + logger.info(f"[私聊][{self.private_name}]规划的行动: {action}") + logger.info(f"[私聊][{self.private_name}]行动原因: {reason}") return action, reason except Exception as e: - logger.error(f"规划行动时调用 LLM 或处理结果出错: {str(e)}") + logger.error(f"[私聊][{self.private_name}]规划行动时调用 LLM 或处理结果出错: {str(e)}") return "wait", f"行动规划处理中发生错误,暂时等待: {str(e)}" diff --git a/src/plugins/PFC/chat_observer.py b/src/plugins/PFC/chat_observer.py index 915618474..69aede96e 100644 --- a/src/plugins/PFC/chat_observer.py +++ b/src/plugins/PFC/chat_observer.py @@ -18,7 +18,7 @@ class ChatObserver: _instances: Dict[str, "ChatObserver"] = {} @classmethod - def get_instance(cls, stream_id: str) -> "ChatObserver": + def get_instance(cls, stream_id: str, private_name: str) -> "ChatObserver": """获取或创建观察器实例 Args: @@ -28,10 +28,10 @@ class ChatObserver: ChatObserver: 观察器实例 """ if stream_id not in cls._instances: - cls._instances[stream_id] = cls(stream_id) + cls._instances[stream_id] = cls(stream_id, private_name) return cls._instances[stream_id] - def __init__(self, stream_id: str): + def __init__(self, stream_id: str, private_name: str): """初始化观察器 Args: @@ -41,6 +41,7 @@ class ChatObserver: raise RuntimeError(f"ChatObserver for {stream_id} already exists. Use get_instance() instead.") self.stream_id = stream_id + self.private_name = private_name self.message_storage = MongoDBMessageStorage() # self.last_user_speak_time: Optional[float] = None # 对方上次发言时间 @@ -76,12 +77,12 @@ class ChatObserver: Returns: bool: 是否有新消息 """ - logger.debug(f"检查距离上一次观察之后是否有了新消息: {self.last_check_time}") + logger.debug(f"[私聊][{self.private_name}]检查距离上一次观察之后是否有了新消息: {self.last_check_time}") new_message_exists = await self.message_storage.has_new_messages(self.stream_id, self.last_check_time) if new_message_exists: - logger.debug("发现新消息") + logger.debug(f"[私聊][{self.private_name}]发现新消息") self.last_check_time = time.time() return new_message_exists @@ -100,7 +101,7 @@ class ChatObserver: # print(self.notification_manager) await self.notification_manager.send_notification(notification) except Exception as e: - logger.error(f"添加消息到历史记录时出错: {e}") + logger.error(f"[私聊][{self.private_name}]添加消息到历史记录时出错: {e}") print(traceback.format_exc()) # 检查并更新冷场状态 @@ -140,11 +141,11 @@ class ChatObserver: """ if self.last_message_time is None: - logger.debug("没有最后消息时间,返回 False") + logger.debug(f"[私聊][{self.private_name}]没有最后消息时间,返回 False") return False has_new = self.last_message_time > time_point - logger.debug(f"判断是否在指定时间点后有新消息: {self.last_message_time} > {time_point} = {has_new}") + logger.debug(f"[私聊][{self.private_name}]判断是否在指定时间点后有新消息: {self.last_message_time} > {time_point} = {has_new}") return has_new def get_message_history( @@ -213,7 +214,7 @@ class ChatObserver: if new_messages: self.last_message_read = new_messages[-1]["message_id"] - logger.debug(f"获取指定时间点111之前的消息: {new_messages}") + logger.debug(f"[私聊][{self.private_name}]获取指定时间点111之前的消息: {new_messages}") return new_messages @@ -226,9 +227,9 @@ class ChatObserver: # messages = await self._fetch_new_messages_before(start_time) # for message in messages: # await self._add_message_to_history(message) - # logger.debug(f"缓冲消息: {messages}") + # logger.debug(f"[私聊][{self.private_name}]缓冲消息: {messages}") # except Exception as e: - # logger.error(f"缓冲消息出错: {e}") + # logger.error(f"[私聊][{self.private_name}]缓冲消息出错: {e}") while self._running: try: @@ -256,8 +257,8 @@ class ChatObserver: self._update_complete.set() except Exception as e: - logger.error(f"更新循环出错: {e}") - logger.error(traceback.format_exc()) + logger.error(f"[私聊][{self.private_name}]更新循环出错: {e}") + logger.error(f"[私聊][{self.private_name}]{traceback.format_exc()}") self._update_complete.set() # 即使出错也要设置完成事件 def trigger_update(self): @@ -277,7 +278,7 @@ class ChatObserver: await asyncio.wait_for(self._update_complete.wait(), timeout=timeout) return True except asyncio.TimeoutError: - logger.warning(f"等待更新完成超时({timeout}秒)") + logger.warning(f"[私聊][{self.private_name}]等待更新完成超时({timeout}秒)") return False def start(self): @@ -287,7 +288,7 @@ class ChatObserver: self._running = True self._task = asyncio.create_task(self._update_loop()) - logger.debug(f"ChatObserver for {self.stream_id} started") + logger.debug(f"[私聊][{self.private_name}]ChatObserver for {self.stream_id} started") def stop(self): """停止观察器""" @@ -296,7 +297,7 @@ class ChatObserver: self._update_complete.set() # 设置完成事件以解除等待 if self._task: self._task.cancel() - logger.debug(f"ChatObserver for {self.stream_id} stopped") + logger.debug(f"[私聊][{self.private_name}]ChatObserver for {self.stream_id} stopped") async def process_chat_history(self, messages: list): """处理聊天历史 @@ -314,7 +315,7 @@ class ChatObserver: else: self.update_user_speak_time(msg["time"]) except Exception as e: - logger.warning(f"处理消息时间时出错: {e}") + logger.warning(f"[私聊][{self.private_name}]处理消息时间时出错: {e}") continue def update_check_time(self): diff --git a/src/plugins/PFC/conversation.py b/src/plugins/PFC/conversation.py index 1cd7a6ee8..756e01e55 100644 --- a/src/plugins/PFC/conversation.py +++ b/src/plugins/PFC/conversation.py @@ -51,35 +51,35 @@ class Conversation: self.action_planner = ActionPlanner(self.stream_id, self.private_name) self.goal_analyzer = GoalAnalyzer(self.stream_id, self.private_name) self.reply_generator = ReplyGenerator(self.stream_id, self.private_name) - self.knowledge_fetcher = KnowledgeFetcher() + self.knowledge_fetcher = KnowledgeFetcher(self.private_name) self.waiter = Waiter(self.stream_id, self.private_name) - self.direct_sender = DirectMessageSender() + self.direct_sender = DirectMessageSender(self.private_name) # 获取聊天流信息 self.chat_stream = chat_manager.get_stream(self.stream_id) self.stop_action_planner = False except Exception as e: - logger.error(f"初始化对话实例:注册运行组件失败: {e}") - logger.error(traceback.format_exc()) + logger.error(f"[私聊][{self.private_name}]初始化对话实例:注册运行组件失败: {e}") + logger.error(f"[私聊][{self.private_name}]{traceback.format_exc()}") raise try: # 决策所需要的信息,包括自身自信和观察信息两部分 # 注册观察器和观测信息 - self.chat_observer = ChatObserver.get_instance(self.stream_id) + self.chat_observer = ChatObserver.get_instance(self.stream_id, self.private_name) self.chat_observer.start() - self.observation_info = ObservationInfo() - self.observation_info.bind_to_chat_observer(self.chat_observer) + self.observation_info = ObservationInfo(self.private_name) + self.observation_info.bind_to_chat_observer(self.chat_observer, self.private_name) # print(self.chat_observer.get_cached_messages(limit=) self.conversation_info = ConversationInfo() except Exception as e: - logger.error(f"初始化对话实例:注册信息组件失败: {e}") - logger.error(traceback.format_exc()) + logger.error(f"[私聊][{self.private_name}]初始化对话实例:注册信息组件失败: {e}") + logger.error(f"[私聊][{self.private_name}]{traceback.format_exc()}") raise try: - logger.info(f"为 {self.stream_id} 加载初始聊天记录...") + logger.info(f"[私聊][{self.private_name}]为 {self.stream_id} 加载初始聊天记录...") initial_messages = get_raw_msg_before_timestamp_with_chat( # chat_id=self.stream_id, timestamp=time.time(), @@ -106,17 +106,17 @@ class Conversation: self.observation_info.last_message_content = last_msg.get("processed_plain_text", "") logger.info( - f"成功加载 {len(initial_messages)} 条初始聊天记录。最后一条消息时间: {self.observation_info.last_message_time}" + f"[私聊][{self.private_name}]成功加载 {len(initial_messages)} 条初始聊天记录。最后一条消息时间: {self.observation_info.last_message_time}" ) # 让 ChatObserver 从加载的最后一条消息之后开始同步 self.chat_observer.last_message_time = self.observation_info.last_message_time self.chat_observer.last_message_read = last_msg # 更新 observer 的最后读取记录 else: - logger.info("没有找到初始聊天记录。") + logger.info(f"[私聊][{self.private_name}]没有找到初始聊天记录。") except Exception as load_err: - logger.error(f"加载初始聊天记录时出错: {load_err}") + logger.error(f"[私聊][{self.private_name}]加载初始聊天记录时出错: {load_err}") # 出错也要继续,只是没有历史记录而已 # 组件准备完成,启动该论对话 self.should_continue = True @@ -125,10 +125,10 @@ class Conversation: async def start(self): """开始对话流程""" try: - logger.info("对话系统启动中...") + logger.info(f"[私聊][{self.private_name}]对话系统启动中...") asyncio.create_task(self._plan_and_action_loop()) except Exception as e: - logger.error(f"启动对话系统失败: {e}") + logger.error(f"[私聊][{self.private_name}]启动对话系统失败: {e}") raise async def _plan_and_action_loop(self): @@ -139,7 +139,7 @@ class Conversation: await asyncio.sleep(30) continue elif self.ignore_until_timestamp and time.time() >= self.ignore_until_timestamp: - logger.info(f"忽略时间已到 {self.stream_id},准备结束对话。") + logger.info(f"[私聊][{self.private_name}]忽略时间已到 {self.stream_id},准备结束对话。") self.ignore_until_timestamp = None self.should_continue = False continue @@ -149,7 +149,7 @@ class Conversation: if hasattr(self.observation_info, "new_messages_count"): initial_new_message_count = self.observation_info.new_messages_count + 1 # 算上麦麦自己发的那一条 else: - logger.warning("ObservationInfo missing 'new_messages_count' before planning.") + logger.warning(f"[私聊][{self.private_name}]ObservationInfo missing 'new_messages_count' before planning.") # --- 调用 Action Planner --- # 传递 self.conversation_info.last_successful_reply_action @@ -162,11 +162,11 @@ class Conversation: if hasattr(self.observation_info, "new_messages_count"): current_new_message_count = self.observation_info.new_messages_count else: - logger.warning("ObservationInfo missing 'new_messages_count' after planning.") + logger.warning(f"[私聊][{self.private_name}]ObservationInfo missing 'new_messages_count' after planning.") if current_new_message_count > initial_new_message_count + 2: logger.info( - f"规划期间发现新增消息 ({initial_new_message_count} -> {current_new_message_count}),跳过本次行动,重新规划" + f"[私聊][{self.private_name}]规划期间发现新增消息 ({initial_new_message_count} -> {current_new_message_count}),跳过本次行动,重新规划" ) # 如果规划期间有新消息,也应该重置上次回复状态,因为现在要响应新消息了 self.conversation_info.last_successful_reply_action = None @@ -176,12 +176,12 @@ class Conversation: # 包含 send_new_message if initial_new_message_count > 0 and action in ["direct_reply", "send_new_message"]: if hasattr(self.observation_info, "clear_unprocessed_messages"): - logger.debug(f"准备执行 {action},清理 {initial_new_message_count} 条规划时已知的新消息。") + logger.debug(f"[私聊][{self.private_name}]准备执行 {action},清理 {initial_new_message_count} 条规划时已知的新消息。") await self.observation_info.clear_unprocessed_messages() if hasattr(self.observation_info, "new_messages_count"): self.observation_info.new_messages_count = 0 else: - logger.error("无法清理未处理消息: ObservationInfo 缺少 clear_unprocessed_messages 方法!") + logger.error(f"[私聊][{self.private_name}]无法清理未处理消息: ObservationInfo 缺少 clear_unprocessed_messages 方法!") await self._handle_action(action, reason, self.observation_info, self.conversation_info) @@ -198,34 +198,34 @@ class Conversation: if goal_ended: self.should_continue = False - logger.info("检测到'结束对话'目标,停止循环。") + logger.info(f"[私聊][{self.private_name}]检测到'结束对话'目标,停止循环。") except Exception as loop_err: - logger.error(f"PFC主循环出错: {loop_err}") - logger.error(traceback.format_exc()) + logger.error(f"[私聊][{self.private_name}]PFC主循环出错: {loop_err}") + logger.error(f"[私聊][{self.private_name}]{traceback.format_exc()}") await asyncio.sleep(1) if self.should_continue: await asyncio.sleep(0.1) - logger.info(f"PFC 循环结束 for stream_id: {self.stream_id}") + logger.info(f"[私聊][{self.private_name}]PFC 循环结束 for stream_id: {self.stream_id}") def _check_new_messages_after_planning(self): """检查在规划后是否有新消息""" # 检查 ObservationInfo 是否已初始化并且有 new_messages_count 属性 if not hasattr(self, "observation_info") or not hasattr(self.observation_info, "new_messages_count"): - logger.warning("ObservationInfo 未初始化或缺少 'new_messages_count' 属性,无法检查新消息。") + logger.warning(f"[私聊][{self.private_name}]ObservationInfo 未初始化或缺少 'new_messages_count' 属性,无法检查新消息。") return False # 或者根据需要抛出错误 if self.observation_info.new_messages_count > 2: logger.info( - f"生成/执行动作期间收到 {self.observation_info.new_messages_count} 条新消息,取消当前动作并重新规划" + f"[私聊][{self.private_name}]生成/执行动作期间收到 {self.observation_info.new_messages_count} 条新消息,取消当前动作并重新规划" ) # 如果有新消息,也应该重置上次回复状态 if hasattr(self, "conversation_info"): # 确保 conversation_info 已初始化 self.conversation_info.last_successful_reply_action = None else: - logger.warning("ConversationInfo 未初始化,无法重置 last_successful_reply_action。") + logger.warning(f"[私聊][{self.private_name}]ConversationInfo 未初始化,无法重置 last_successful_reply_action。") return True return False @@ -254,7 +254,7 @@ class Conversation: detailed_plain_text=msg_dict.get("detailed_plain_text", ""), ) except Exception as e: - logger.warning(f"转换消息时出错: {e}") + logger.warning(f"[私聊][{self.private_name}]转换消息时出错: {e}") # 可以选择返回 None 或重新抛出异常,这里选择重新抛出以指示问题 raise ValueError(f"无法将字典转换为 Message 对象: {e}") from e @@ -263,7 +263,7 @@ class Conversation: ): """处理规划的行动""" - logger.debug(f"执行行动: {action}, 原因: {reason}") + logger.debug(f"[私聊][{self.private_name}]执行行动: {action}, 原因: {reason}") # 记录action历史 (逻辑不变) current_action_record = { @@ -294,14 +294,14 @@ class Conversation: while reply_attempt_count < max_reply_attempts and not is_suitable: reply_attempt_count += 1 - logger.info(f"尝试生成追问回复 (第 {reply_attempt_count}/{max_reply_attempts} 次)...") + logger.info(f"[私聊][{self.private_name}]尝试生成追问回复 (第 {reply_attempt_count}/{max_reply_attempts} 次)...") self.state = ConversationState.GENERATING # 1. 生成回复 (调用 generate 时传入 action_type) self.generated_reply = await self.reply_generator.generate( observation_info, conversation_info, action_type="send_new_message" ) - logger.info(f"第 {reply_attempt_count} 次生成的追问回复: {self.generated_reply}") + logger.info(f"[私聊][{self.private_name}]第 {reply_attempt_count} 次生成的追问回复: {self.generated_reply}") # 2. 检查回复 (逻辑不变) self.state = ConversationState.CHECKING @@ -315,18 +315,18 @@ class Conversation: retry_count=reply_attempt_count - 1, ) logger.info( - f"第 {reply_attempt_count} 次追问检查结果: 合适={is_suitable}, 原因='{check_reason}', 需重新规划={need_replan}" + f"[私聊][{self.private_name}]第 {reply_attempt_count} 次追问检查结果: 合适={is_suitable}, 原因='{check_reason}', 需重新规划={need_replan}" ) if is_suitable: final_reply_to_send = self.generated_reply break elif need_replan: logger.warning( - f"第 {reply_attempt_count} 次追问检查建议重新规划,停止尝试。原因: {check_reason}" + f"[私聊][{self.private_name}]第 {reply_attempt_count} 次追问检查建议重新规划,停止尝试。原因: {check_reason}" ) break except Exception as check_err: - logger.error(f"第 {reply_attempt_count} 次调用 ReplyChecker (追问) 时出错: {check_err}") + logger.error(f"[私聊][{self.private_name}]第 {reply_attempt_count} 次调用 ReplyChecker (追问) 时出错: {check_err}") check_reason = f"第 {reply_attempt_count} 次检查过程出错: {check_err}" break @@ -334,7 +334,7 @@ class Conversation: if is_suitable: # 检查是否有新消息 if self._check_new_messages_after_planning(): - logger.info("生成追问回复期间收到新消息,取消发送,重新规划行动") + logger.info(f"[私聊][{self.private_name}]生成追问回复期间收到新消息,取消发送,重新规划行动") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"有新消息,取消发送追问: {final_reply_to_send}"} ) @@ -351,7 +351,7 @@ class Conversation: else: # 追问失败 - logger.warning(f"经过 {reply_attempt_count} 次尝试,未能生成合适的追问回复。最终原因: {check_reason}") + logger.warning(f"[私聊][{self.private_name}]经过 {reply_attempt_count} 次尝试,未能生成合适的追问回复。最终原因: {check_reason}") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"追问尝试{reply_attempt_count}次后失败: {check_reason}"} ) @@ -359,7 +359,7 @@ class Conversation: self.conversation_info.last_successful_reply_action = None # 执行 Wait 操作 - logger.info("由于无法生成合适追问回复,执行 'wait' 操作...") + logger.info(f"[私聊][{self.private_name}]由于无法生成合适追问回复,执行 'wait' 操作...") self.state = ConversationState.WAITING await self.waiter.wait(self.conversation_info) wait_action_record = { @@ -381,14 +381,14 @@ class Conversation: while reply_attempt_count < max_reply_attempts and not is_suitable: reply_attempt_count += 1 - logger.info(f"尝试生成首次回复 (第 {reply_attempt_count}/{max_reply_attempts} 次)...") + logger.info(f"[私聊][{self.private_name}]尝试生成首次回复 (第 {reply_attempt_count}/{max_reply_attempts} 次)...") self.state = ConversationState.GENERATING # 1. 生成回复 self.generated_reply = await self.reply_generator.generate( observation_info, conversation_info, action_type="direct_reply" ) - logger.info(f"第 {reply_attempt_count} 次生成的首次回复: {self.generated_reply}") + logger.info(f"[私聊][{self.private_name}]第 {reply_attempt_count} 次生成的首次回复: {self.generated_reply}") # 2. 检查回复 self.state = ConversationState.CHECKING @@ -402,18 +402,18 @@ class Conversation: retry_count=reply_attempt_count - 1, ) logger.info( - f"第 {reply_attempt_count} 次首次回复检查结果: 合适={is_suitable}, 原因='{check_reason}', 需重新规划={need_replan}" + f"[私聊][{self.private_name}]第 {reply_attempt_count} 次首次回复检查结果: 合适={is_suitable}, 原因='{check_reason}', 需重新规划={need_replan}" ) if is_suitable: final_reply_to_send = self.generated_reply break elif need_replan: logger.warning( - f"第 {reply_attempt_count} 次首次回复检查建议重新规划,停止尝试。原因: {check_reason}" + f"[私聊][{self.private_name}]第 {reply_attempt_count} 次首次回复检查建议重新规划,停止尝试。原因: {check_reason}" ) break except Exception as check_err: - logger.error(f"第 {reply_attempt_count} 次调用 ReplyChecker (首次回复) 时出错: {check_err}") + logger.error(f"[私聊][{self.private_name}]第 {reply_attempt_count} 次调用 ReplyChecker (首次回复) 时出错: {check_err}") check_reason = f"第 {reply_attempt_count} 次检查过程出错: {check_err}" break @@ -421,7 +421,7 @@ class Conversation: if is_suitable: # 检查是否有新消息 if self._check_new_messages_after_planning(): - logger.info("生成首次回复期间收到新消息,取消发送,重新规划行动") + logger.info(f"[私聊][{self.private_name}]生成首次回复期间收到新消息,取消发送,重新规划行动") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"有新消息,取消发送首次回复: {final_reply_to_send}"} ) @@ -438,7 +438,7 @@ class Conversation: else: # 首次回复失败 - logger.warning(f"经过 {reply_attempt_count} 次尝试,未能生成合适的首次回复。最终原因: {check_reason}") + logger.warning(f"[私聊][{self.private_name}]经过 {reply_attempt_count} 次尝试,未能生成合适的首次回复。最终原因: {check_reason}") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"首次回复尝试{reply_attempt_count}次后失败: {check_reason}"} ) @@ -446,7 +446,7 @@ class Conversation: self.conversation_info.last_successful_reply_action = None # 执行 Wait 操作 (保持原有逻辑) - logger.info("由于无法生成合适首次回复,执行 'wait' 操作...") + logger.info(f"[私聊][{self.private_name}]由于无法生成合适首次回复,执行 'wait' 操作...") self.state = ConversationState.WAITING await self.waiter.wait(self.conversation_info) wait_action_record = { @@ -464,11 +464,11 @@ class Conversation: try: # 检查 knowledge_fetcher 是否存在 if not hasattr(self, "knowledge_fetcher"): - logger.error("KnowledgeFetcher 未初始化,无法获取知识。") + logger.error(f"[私聊][{self.private_name}]KnowledgeFetcher 未初始化,无法获取知识。") raise AttributeError("KnowledgeFetcher not initialized") knowledge, source = await self.knowledge_fetcher.fetch(knowledge_query, observation_info.chat_history) - logger.info(f"获取到知识: {knowledge[:100]}..., 来源: {source}") + logger.info(f"[私聊][{self.private_name}]获取到知识: {knowledge[:100]}..., 来源: {source}") if knowledge: # 确保 knowledge_list 存在 if not hasattr(conversation_info, "knowledge_list"): @@ -478,7 +478,7 @@ class Conversation: ) action_successful = True except Exception as fetch_err: - logger.error(f"获取知识时出错: {fetch_err}") + logger.error(f"[私聊][{self.private_name}]获取知识时出错: {fetch_err}") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"获取知识失败: {fetch_err}"} ) @@ -489,12 +489,12 @@ class Conversation: try: # 检查 goal_analyzer 是否存在 if not hasattr(self, "goal_analyzer"): - logger.error("GoalAnalyzer 未初始化,无法重新思考目标。") + logger.error(f"[私聊][{self.private_name}]GoalAnalyzer 未初始化,无法重新思考目标。") raise AttributeError("GoalAnalyzer not initialized") await self.goal_analyzer.analyze_goal(conversation_info, observation_info) action_successful = True except Exception as rethink_err: - logger.error(f"重新思考目标时出错: {rethink_err}") + logger.error(f"[私聊][{self.private_name}]重新思考目标时出错: {rethink_err}") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"重新思考目标失败: {rethink_err}"} ) @@ -502,16 +502,16 @@ class Conversation: elif action == "listening": self.state = ConversationState.LISTENING - logger.info("倾听对方发言...") + logger.info(f"[私聊][{self.private_name}]倾听对方发言...") try: # 检查 waiter 是否存在 if not hasattr(self, "waiter"): - logger.error("Waiter 未初始化,无法倾听。") + logger.error(f"[私聊][{self.private_name}]Waiter 未初始化,无法倾听。") raise AttributeError("Waiter not initialized") await self.waiter.wait_listening(conversation_info) action_successful = True # Listening 完成就算成功 except Exception as listen_err: - logger.error(f"倾听时出错: {listen_err}") + logger.error(f"[私聊][{self.private_name}]倾听时出错: {listen_err}") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"倾听失败: {listen_err}"} ) @@ -519,29 +519,29 @@ class Conversation: elif action == "end_conversation": self.should_continue = False - logger.info("决定结束对话...") + logger.info(f"[私聊][{self.private_name}]决定结束对话...") action_successful = True # 标记动作成功 elif action == "block_and_ignore": - logger.info("不想再理你了...") + logger.info(f"[私聊][{self.private_name}]不想再理你了...") ignore_duration_seconds = 10 * 60 self.ignore_until_timestamp = time.time() + ignore_duration_seconds - logger.info(f"将忽略此对话直到: {datetime.datetime.fromtimestamp(self.ignore_until_timestamp)}") + logger.info(f"[私聊][{self.private_name}]将忽略此对话直到: {datetime.datetime.fromtimestamp(self.ignore_until_timestamp)}") self.state = ConversationState.IGNORED action_successful = True # 标记动作成功 else: # 对应 'wait' 动作 self.state = ConversationState.WAITING - logger.info("等待更多信息...") + logger.info(f"[私聊][{self.private_name}]等待更多信息...") try: # 检查 waiter 是否存在 if not hasattr(self, "waiter"): - logger.error("Waiter 未初始化,无法等待。") + logger.error(f"[私聊][{self.private_name}]Waiter 未初始化,无法等待。") raise AttributeError("Waiter not initialized") _timeout_occurred = await self.waiter.wait(self.conversation_info) action_successful = True # Wait 完成就算成功 except Exception as wait_err: - logger.error(f"等待时出错: {wait_err}") + logger.error(f"[私聊][{self.private_name}]等待时出错: {wait_err}") conversation_info.done_action[action_index].update( {"status": "recall", "final_reason": f"等待失败: {wait_err}"} ) @@ -559,13 +559,13 @@ class Conversation: # 重置状态: 对于非回复类动作的成功,清除上次回复状态 if action not in ["direct_reply", "send_new_message"]: self.conversation_info.last_successful_reply_action = None - logger.debug(f"动作 {action} 成功完成,重置 last_successful_reply_action") + logger.debug(f"[私聊][{self.private_name}]动作 {action} 成功完成,重置 last_successful_reply_action") # 如果动作是 recall 状态,在各自的处理逻辑中已经更新了 done_action async def _send_reply(self): """发送回复""" if not self.generated_reply: - logger.warning("没有生成回复内容,无法发送。") + logger.warning(f"[私聊][{self.private_name}]没有生成回复内容,无法发送。") return try: @@ -574,10 +574,10 @@ class Conversation: # 发送消息 (确保 direct_sender 和 chat_stream 有效) if not hasattr(self, "direct_sender") or not self.direct_sender: - logger.error("DirectMessageSender 未初始化,无法发送回复。") + logger.error(f"[私聊][{self.private_name}]DirectMessageSender 未初始化,无法发送回复。") return if not self.chat_stream: - logger.error("ChatStream 未初始化,无法发送回复。") + logger.error(f"[私聊][{self.private_name}]ChatStream 未初始化,无法发送回复。") return await self.direct_sender.send_message(chat_stream=self.chat_stream, content=reply_content) @@ -587,13 +587,13 @@ class Conversation: # 暂时注释掉,观察是否影响 ObservationInfo 的更新 # self.chat_observer.trigger_update() # if not await self.chat_observer.wait_for_update(): - # logger.warning("等待 ChatObserver 更新完成超时") + # logger.warning(f"[私聊][{self.private_name}]等待 ChatObserver 更新完成超时") self.state = ConversationState.ANALYZING # 更新状态 except Exception as e: - logger.error(f"发送消息或更新状态时失败: {str(e)}") - logger.error(traceback.format_exc()) + logger.error(f"[私聊][{self.private_name}]发送消息或更新状态时失败: {str(e)}") + logger.error(f"[私聊][{self.private_name}]{traceback.format_exc()}") self.state = ConversationState.ANALYZING async def _send_timeout_message(self): @@ -608,4 +608,4 @@ class Conversation: chat_stream=self.chat_stream, content="TODO:超时消息", reply_to_message=latest_message ) except Exception as e: - logger.error(f"发送超时消息失败: {str(e)}") + logger.error(f"[私聊][{self.private_name}]发送超时消息失败: {str(e)}") diff --git a/src/plugins/PFC/message_sender.py b/src/plugins/PFC/message_sender.py index 8a0f41762..06860af37 100644 --- a/src/plugins/PFC/message_sender.py +++ b/src/plugins/PFC/message_sender.py @@ -19,6 +19,7 @@ class DirectMessageSender: self, chat_stream: ChatStream, content: str, + private_name: str, reply_to_message: Optional[Message] = None, ) -> None: """发送消息到聊天流 @@ -43,8 +44,8 @@ class DirectMessageSender: message_set = MessageSet(chat_stream, message_sending.message_id) message_set.add_message(message_sending) message_manager.add_message(message_set) - logger.info(f"PFC消息已发送: {content}") + logger.info(f"[私聊][{private_name}]PFC消息已发送: {content}") except Exception as e: - logger.error(f"PFC消息发送失败: {str(e)}") + logger.error(f"[私聊][{private_name}]PFC消息发送失败: {str(e)}") raise diff --git a/src/plugins/PFC/observation_info.py b/src/plugins/PFC/observation_info.py index 050d839fb..92b09cc0c 100644 --- a/src/plugins/PFC/observation_info.py +++ b/src/plugins/PFC/observation_info.py @@ -15,13 +15,14 @@ logger = get_module_logger("observation_info") class ObservationInfoHandler(NotificationHandler): """ObservationInfo的通知处理器""" - def __init__(self, observation_info: "ObservationInfo"): + def __init__(self, observation_info: "ObservationInfo", private_name: str): """初始化处理器 Args: observation_info: 要更新的ObservationInfo实例 """ self.observation_info = observation_info + self.private_name = private_name async def handle_notification(self, notification): # 获取通知类型和数据 @@ -30,7 +31,7 @@ class ObservationInfoHandler(NotificationHandler): if notification_type == NotificationType.NEW_MESSAGE: # 处理新消息通知 - logger.debug(f"收到新消息通知data: {data}") + logger.debug(f"[私聊][{self.private_name}]收到新消息通知data: {data}") message_id = data.get("message_id") processed_plain_text = data.get("processed_plain_text") detailed_plain_text = data.get("detailed_plain_text") @@ -89,7 +90,7 @@ class ObservationInfoHandler(NotificationHandler): elif notification_type == NotificationType.ERROR: # 处理错误通知 error_msg = data.get("error", "") - logger.error(f"收到错误通知: {error_msg}") + logger.error(f"[私聊][{self.private_name}]收到错误通知: {error_msg}") @dataclass @@ -122,12 +123,13 @@ class ObservationInfo: # #spec # meta_plan_trigger: bool = False - def __post_init__(self): + def __post_init__(self, private_name: str = None): """初始化后创建handler""" self.chat_observer = None - self.handler = ObservationInfoHandler(self) + self.handler = ObservationInfoHandler(self, private_name) + self.private_name = private_name - def bind_to_chat_observer(self, chat_observer: ChatObserver): + def bind_to_chat_observer(self, chat_observer: ChatObserver, private_name: str): """绑定到指定的chat_observer Args: @@ -158,7 +160,7 @@ class ObservationInfo: Args: message: 消息数据 """ - # logger.debug(f"更新信息from_message: {message}") + # logger.debug(f"[私聊][{self.private_name}]更新信息from_message: {message}") self.last_message_time = message["time"] self.last_message_id = message["message_id"] diff --git a/src/plugins/PFC/pfc.py b/src/plugins/PFC/pfc.py index 7cb609e78..db10e79b8 100644 --- a/src/plugins/PFC/pfc.py +++ b/src/plugins/PFC/pfc.py @@ -40,7 +40,7 @@ class GoalAnalyzer: self.name = global_config.BOT_NICKNAME self.nick_name = global_config.BOT_ALIAS_NAMES self.private_name = private_name - self.chat_observer = ChatObserver.get_instance(stream_id) + self.chat_observer = ChatObserver.get_instance(stream_id, private_name) # 多目标存储结构 self.goals = [] # 存储多个目标 @@ -135,27 +135,27 @@ class GoalAnalyzer: 输出格式示例: [ - {{ +{{ "goal": "回答用户关于Python编程的具体问题", "reasoning": "用户提出了关于Python的技术问题,需要专业且准确的解答" - }}, - {{ +}}, +{{ "goal": "回答用户关于python安装的具体问题", "reasoning": "用户提出了关于Python的技术问题,需要专业且准确的解答" - }} +}} ]""" - logger.debug(f"发送到LLM的提示词: {prompt}") + logger.debug(f"[私聊][{self.private_name}]发送到LLM的提示词: {prompt}") try: content, _ = await self.llm.generate_response_async(prompt) - logger.debug(f"LLM原始返回内容: {content}") + logger.debug(f"[私聊][{self.private_name}]LLM原始返回内容: {content}") except Exception as e: - logger.error(f"分析对话目标时出错: {str(e)}") + logger.error(f"[私聊][{self.private_name}]分析对话目标时出错: {str(e)}") content = "" # 使用改进后的get_items_from_json函数处理JSON数组 success, result = get_items_from_json( - content, "goal", "reasoning", required_types={"goal": str, "reasoning": str}, allow_array=True + content, self.private_name, "goal", "reasoning", required_types={"goal": str, "reasoning": str}, allow_array=True ) if success: @@ -287,11 +287,12 @@ class GoalAnalyzer: try: content, _ = await self.llm.generate_response_async(prompt) - logger.debug(f"LLM原始返回内容: {content}") + logger.debug(f"[私聊][{self.private_name}]LLM原始返回内容: {content}") # 尝试解析JSON success, result = get_items_from_json( content, + self.private_name, "goal_achieved", "stop_conversation", "reason", @@ -299,7 +300,7 @@ class GoalAnalyzer: ) if not success: - logger.error("无法解析对话分析结果JSON") + logger.error(f"[私聊][{self.private_name}]无法解析对话分析结果JSON") return False, False, "解析结果失败" goal_achieved = result["goal_achieved"] @@ -309,16 +310,17 @@ class GoalAnalyzer: return goal_achieved, stop_conversation, reason except Exception as e: - logger.error(f"分析对话状态时出错: {str(e)}") + logger.error(f"[私聊][{self.private_name}]分析对话状态时出错: {str(e)}") return False, False, f"分析出错: {str(e)}" class DirectMessageSender: """直接发送消息到平台的发送器""" - def __init__(self): + def __init__(self, private_name: str): self.logger = get_module_logger("direct_sender") self.storage = MessageStorage() + self.private_name = private_name async def send_via_ws(self, message: MessageSending) -> None: try: @@ -368,6 +370,6 @@ class DirectMessageSender: try: await self.send_via_ws(message) await self.storage.store_message(message, chat_stream) - logger.success(f"PFC消息已发送: {content}") + logger.success(f"[私聊][{self.private_name}]PFC消息已发送: {content}") except Exception as e: - logger.error(f"PFC消息发送失败: {str(e)}") + logger.error(f"[私聊][{self.private_name}]PFC消息发送失败: {str(e)}") diff --git a/src/plugins/PFC/pfc_KnowledgeFetcher.py b/src/plugins/PFC/pfc_KnowledgeFetcher.py index 958b05bf8..099b4979e 100644 --- a/src/plugins/PFC/pfc_KnowledgeFetcher.py +++ b/src/plugins/PFC/pfc_KnowledgeFetcher.py @@ -13,13 +13,14 @@ logger = get_module_logger("knowledge_fetcher") class KnowledgeFetcher: """知识调取器""" - def __init__(self): + def __init__(self, private_name: str): self.llm = LLMRequest( model=global_config.llm_normal, temperature=global_config.llm_normal["temp"], max_tokens=1000, request_type="knowledge_fetch", ) + self.private_name = private_name def _lpmm_get_knowledge(self, query: str) -> str: """获取相关知识 @@ -31,13 +32,13 @@ class KnowledgeFetcher: str: 构造好的,带相关度的知识 """ - logger.debug("正在从LPMM知识库中获取知识") + logger.debug(f"[私聊][{self.private_name}]正在从LPMM知识库中获取知识") try: knowledge_info = qa_manager.get_knowledge(query) - logger.debug(f"LPMM知识库查询结果: {knowledge_info:150}") + logger.debug(f"[私聊][{self.private_name}]LPMM知识库查询结果: {knowledge_info:150}") return knowledge_info except Exception as e: - logger.error(f"LPMM知识库搜索工具执行失败: {str(e)}") + logger.error(f"[私聊][{self.private_name}]LPMM知识库搜索工具执行失败: {str(e)}") return "未找到匹配的知识" async def fetch(self, query: str, chat_history: List[Message]) -> Tuple[str, str]: diff --git a/src/plugins/PFC/pfc_manager.py b/src/plugins/PFC/pfc_manager.py index 6a0c00708..621686a90 100644 --- a/src/plugins/PFC/pfc_manager.py +++ b/src/plugins/PFC/pfc_manager.py @@ -39,11 +39,11 @@ class PFCManager: """ # 检查是否已经有实例 if stream_id in self._initializing and self._initializing[stream_id]: - logger.debug(f"会话实例正在初始化中: {stream_id}") + logger.debug(f"[私聊][{private_name}]会话实例正在初始化中: {stream_id}") return None if stream_id in self._instances and self._instances[stream_id].should_continue: - logger.debug(f"使用现有会话实例: {stream_id}") + logger.debug(f"[私聊][{private_name}]使用现有会话实例: {stream_id}") return self._instances[stream_id] if stream_id in self._instances: instance = self._instances[stream_id] @@ -52,19 +52,19 @@ class PFCManager: and instance.ignore_until_timestamp and time.time() < instance.ignore_until_timestamp ): - logger.debug(f"会话实例当前处于忽略状态: {stream_id}") + logger.debug(f"[私聊][{private_name}]会话实例当前处于忽略状态: {stream_id}") # 返回 None 阻止交互。或者可以返回实例但标记它被忽略了喵? # 还是返回 None 吧喵。 return None # 检查 should_continue 状态 if instance.should_continue: - logger.debug(f"使用现有会话实例: {stream_id}") + logger.debug(f"[私聊][{private_name}]使用现有会话实例: {stream_id}") return instance # else: 实例存在但不应继续 try: # 创建新实例 - logger.info(f"创建新的对话实例: {stream_id}") + logger.info(f"[私聊][{private_name}]创建新的对话实例: {stream_id}") self._initializing[stream_id] = True # 创建实例 conversation_instance = Conversation(stream_id, private_name) @@ -73,7 +73,7 @@ class PFCManager: # 启动实例初始化 await self._initialize_conversation(conversation_instance) except Exception as e: - logger.error(f"创建会话实例失败: {stream_id}, 错误: {e}") + logger.error(f"[私聊][{private_name}]创建会话实例失败: {stream_id}, 错误: {e}") return None return conversation_instance @@ -85,20 +85,21 @@ class PFCManager: conversation: 要初始化的会话实例 """ stream_id = conversation.stream_id + private_name = conversation.private_name try: - logger.info(f"开始初始化会话实例: {stream_id}") + logger.info(f"[私聊][{private_name}]开始初始化会话实例: {stream_id}") # 启动初始化流程 await conversation._initialize() # 标记初始化完成 self._initializing[stream_id] = False - logger.info(f"会话实例 {stream_id} 初始化完成") + logger.info(f"[私聊][{private_name}]会话实例 {stream_id} 初始化完成") except Exception as e: - logger.error(f"管理器初始化会话实例失败: {stream_id}, 错误: {e}") - logger.error(traceback.format_exc()) + logger.error(f"[私聊][{private_name}]管理器初始化会话实例失败: {stream_id}, 错误: {e}") + logger.error(f"[私聊][{private_name}]{traceback.format_exc()}") # 清理失败的初始化 async def get_conversation(self, stream_id: str) -> Optional[Conversation]: diff --git a/src/plugins/PFC/pfc_utils.py b/src/plugins/PFC/pfc_utils.py index eae36e125..5e35d47be 100644 --- a/src/plugins/PFC/pfc_utils.py +++ b/src/plugins/PFC/pfc_utils.py @@ -8,6 +8,7 @@ logger = get_module_logger("pfc_utils") def get_items_from_json( content: str, + private_name: str, *items: str, default_values: Optional[Dict[str, Any]] = None, required_types: Optional[Dict[str, type]] = None, @@ -78,9 +79,9 @@ def get_items_from_json( if valid_items: return True, valid_items except json.JSONDecodeError: - logger.debug("JSON数组解析失败,尝试解析单个JSON对象") + logger.debug(f"[私聊][{private_name}]JSON数组解析失败,尝试解析单个JSON对象") except Exception as e: - logger.debug(f"尝试解析JSON数组时出错: {str(e)}") + logger.debug(f"[私聊][{private_name}]尝试解析JSON数组时出错: {str(e)}") # 尝试解析JSON对象 try: @@ -93,10 +94,10 @@ def get_items_from_json( try: json_data = json.loads(json_match.group()) except json.JSONDecodeError: - logger.error("提取的JSON内容解析失败") + logger.error(f"[私聊][{private_name}]提取的JSON内容解析失败") return False, result else: - logger.error("无法在返回内容中找到有效的JSON") + logger.error(f"[私聊][{private_name}]无法在返回内容中找到有效的JSON") return False, result # 提取字段 @@ -106,20 +107,20 @@ def get_items_from_json( # 验证必需字段 if not all(item in result for item in items): - logger.error(f"JSON缺少必要字段,实际内容: {json_data}") + logger.error(f"[私聊][{private_name}]JSON缺少必要字段,实际内容: {json_data}") return False, result # 验证字段类型 if required_types: for field, expected_type in required_types.items(): if field in result and not isinstance(result[field], expected_type): - logger.error(f"{field} 必须是 {expected_type.__name__} 类型") + logger.error(f"[私聊][{private_name}]{field} 必须是 {expected_type.__name__} 类型") return False, result # 验证字符串字段不为空 for field in items: if isinstance(result[field], str) and not result[field].strip(): - logger.error(f"{field} 不能为空") + logger.error(f"[私聊][{private_name}]{field} 不能为空") return False, result return True, result diff --git a/src/plugins/PFC/reply_checker.py b/src/plugins/PFC/reply_checker.py index 26b20875c..590421aa6 100644 --- a/src/plugins/PFC/reply_checker.py +++ b/src/plugins/PFC/reply_checker.py @@ -12,12 +12,13 @@ logger = get_module_logger("reply_checker") class ReplyChecker: """回复检查器""" - def __init__(self, stream_id: str): + def __init__(self, stream_id: str, private_name: str): self.llm = LLMRequest( model=global_config.llm_PFC_reply_checker, temperature=0.50, max_tokens=1000, request_type="reply_check" ) self.name = global_config.BOT_NICKNAME - self.chat_observer = ChatObserver.get_instance(stream_id) + self.private_name = private_name + self.chat_observer = ChatObserver.get_instance(stream_id, private_name) self.max_retries = 3 # 最大重试次数 async def check( @@ -49,7 +50,7 @@ class ReplyChecker: # 可以用简单比较,或者更复杂的相似度库 (如 difflib) # 简单比较:是否完全相同 if reply == bot_messages[0]: # 和最近一条完全一样 - logger.warning(f"ReplyChecker 检测到回复与上一条 Bot 消息完全相同: '{reply}'") + logger.warning(f"[私聊][{self.private_name}]ReplyChecker 检测到回复与上一条 Bot 消息完全相同: '{reply}'") return ( False, "回复内容与你上一条发言完全相同,请修改,可以选择深入话题或寻找其它话题或等待", @@ -60,13 +61,13 @@ class ReplyChecker: # 计算编辑距离相似度,ratio() 返回 0 到 1 之间的浮点数 similarity_ratio = difflib.SequenceMatcher(None, reply, bot_messages[0]).ratio() - logger.debug(f"ReplyChecker - 相似度: {similarity_ratio:.2f}") + logger.debug(f"[私聊][{self.private_name}]ReplyChecker - 相似度: {similarity_ratio:.2f}") # 设置一个相似度阈值 similarity_threshold = 0.9 if similarity_ratio > similarity_threshold: logger.warning( - f"ReplyChecker 检测到回复与上一条 Bot 消息高度相似 (相似度 {similarity_ratio:.2f}): '{reply}'" + f"[私聊][{self.private_name}]ReplyChecker 检测到回复与上一条 Bot 消息高度相似 (相似度 {similarity_ratio:.2f}): '{reply}'" ) return ( False, @@ -77,8 +78,8 @@ class ReplyChecker: except Exception as e: import traceback - logger.error(f"检查回复时出错: 类型={type(e)}, 值={e}") - logger.error(traceback.format_exc()) # 打印详细的回溯信息 + logger.error(f"[私聊][{self.private_name}]检查回复时出错: 类型={type(e)}, 值={e}") + logger.error(f"[私聊][{self.private_name}]{traceback.format_exc()}") # 打印详细的回溯信息 prompt = f"""请检查以下回复或消息是否合适: @@ -118,7 +119,7 @@ class ReplyChecker: try: content, _ = await self.llm.generate_response_async(prompt) - logger.debug(f"检查回复的原始返回: {content}") + logger.debug(f"[私聊][{self.private_name}]检查回复的原始返回: {content}") # 清理内容,尝试提取JSON部分 content = content.strip() @@ -171,7 +172,7 @@ class ReplyChecker: return suitable, reason, need_replan except Exception as e: - logger.error(f"检查回复时出错: {e}") + logger.error(f"[私聊][{self.private_name}]检查回复时出错: {e}") # 如果出错且已达到最大重试次数,建议重新规划 if retry_count >= self.max_retries: return False, "多次检查失败,建议重新规划", True diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index a86051cf2..fa4fdc424 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -72,8 +72,8 @@ class ReplyGenerator: self.identity_detail_info = Individuality.get_instance().get_prompt(type="identity", x_person=2, level=2) self.name = global_config.BOT_NICKNAME self.private_name = private_name - self.chat_observer = ChatObserver.get_instance(stream_id) - self.reply_checker = ReplyChecker(stream_id) + self.chat_observer = ChatObserver.get_instance(stream_id, private_name) + self.reply_checker = ReplyChecker(stream_id, private_name) # 修改 generate 方法签名,增加 action_type 参数 async def generate( @@ -90,7 +90,7 @@ class ReplyGenerator: str: 生成的回复 """ # 构建提示词 - logger.debug(f"开始生成回复 (动作类型: {action_type}):当前目标: {conversation_info.goal_list}") + logger.debug(f"[私聊][{self.private_name}]开始生成回复 (动作类型: {action_type}):当前目标: {conversation_info.goal_list}") # --- 构建通用 Prompt 参数 --- # (这部分逻辑基本不变) @@ -146,10 +146,10 @@ class ReplyGenerator: # --- 选择 Prompt --- if action_type == "send_new_message": prompt_template = PROMPT_SEND_NEW_MESSAGE - logger.info("使用 PROMPT_SEND_NEW_MESSAGE (追问生成)") + logger.info(f"[私聊][{self.private_name}]使用 PROMPT_SEND_NEW_MESSAGE (追问生成)") else: # 默认使用 direct_reply 的 prompt prompt_template = PROMPT_DIRECT_REPLY - logger.info("使用 PROMPT_DIRECT_REPLY (首次/非连续回复生成)") + logger.info(f"[私聊][{self.private_name}]使用 PROMPT_DIRECT_REPLY (首次/非连续回复生成)") # --- 格式化最终的 Prompt --- prompt = prompt_template.format( @@ -157,15 +157,15 @@ class ReplyGenerator: ) # --- 调用 LLM 生成 --- - logger.debug(f"发送到LLM的生成提示词:\n------\n{prompt}\n------") + logger.debug(f"[私聊][{self.private_name}]发送到LLM的生成提示词:\n------\n{prompt}\n------") try: content, _ = await self.llm.generate_response_async(prompt) - logger.debug(f"生成的回复: {content}") + logger.debug(f"[私聊][{self.private_name}]生成的回复: {content}") # 移除旧的检查新消息逻辑,这应该由 conversation 控制流处理 return content except Exception as e: - logger.error(f"生成回复时出错: {e}") + logger.error(f"[私聊][{self.private_name}]生成回复时出错: {e}") return "抱歉,我现在有点混乱,让我重新思考一下..." # check_reply 方法保持不变 diff --git a/src/plugins/PFC/waiter.py b/src/plugins/PFC/waiter.py index 5d8fdecfd..742c70a97 100644 --- a/src/plugins/PFC/waiter.py +++ b/src/plugins/PFC/waiter.py @@ -18,7 +18,7 @@ class Waiter: """等待处理类""" def __init__(self, stream_id: str, private_name: str): - self.chat_observer = ChatObserver.get_instance(stream_id) + self.chat_observer = ChatObserver.get_instance(stream_id, private_name) self.name = global_config.BOT_NICKNAME self.private_name = private_name # self.wait_accumulated_time = 0 # 不再需要累加计时 @@ -26,52 +26,52 @@ class Waiter: async def wait(self, conversation_info: ConversationInfo) -> bool: """等待用户新消息或超时""" wait_start_time = time.time() - logger.info(f"进入常规等待状态 (超时: {DESIRED_TIMEOUT_SECONDS} 秒)...") + logger.info(f"[私聊][{self.private_name}]进入常规等待状态 (超时: {DESIRED_TIMEOUT_SECONDS} 秒)...") while True: # 检查是否有新消息 if self.chat_observer.new_message_after(wait_start_time): - logger.info("等待结束,收到新消息") + logger.info(f"[私聊][{self.private_name}]等待结束,收到新消息") return False # 返回 False 表示不是超时 # 检查是否超时 elapsed_time = time.time() - wait_start_time if elapsed_time > DESIRED_TIMEOUT_SECONDS: - logger.info(f"等待超过 {DESIRED_TIMEOUT_SECONDS} 秒...添加思考目标。") + logger.info(f"[私聊][{self.private_name}]等待超过 {DESIRED_TIMEOUT_SECONDS} 秒...添加思考目标。") wait_goal = { "goal": f"你等待了{elapsed_time / 60:.1f}分钟,注意可能在对方看来聊天已经结束,思考接下来要做什么", "reasoning": "对方很久没有回复你的消息了", } conversation_info.goal_list.append(wait_goal) - logger.info(f"添加目标: {wait_goal}") + logger.info(f"[私聊][{self.private_name}]添加目标: {wait_goal}") return True # 返回 True 表示超时 await asyncio.sleep(5) # 每 5 秒检查一次 - logger.debug("等待中...") # 可以考虑把这个频繁日志注释掉,只在超时或收到消息时输出 + logger.debug(f"[私聊][{self.private_name}]等待中...") # 可以考虑把这个频繁日志注释掉,只在超时或收到消息时输出 async def wait_listening(self, conversation_info: ConversationInfo) -> bool: """倾听用户发言或超时""" wait_start_time = time.time() - logger.info(f"进入倾听等待状态 (超时: {DESIRED_TIMEOUT_SECONDS} 秒)...") + logger.info(f"[私聊][{self.private_name}]进入倾听等待状态 (超时: {DESIRED_TIMEOUT_SECONDS} 秒)...") while True: # 检查是否有新消息 if self.chat_observer.new_message_after(wait_start_time): - logger.info("倾听等待结束,收到新消息") + logger.info(f"[私聊][{self.private_name}]倾听等待结束,收到新消息") return False # 返回 False 表示不是超时 # 检查是否超时 elapsed_time = time.time() - wait_start_time if elapsed_time > DESIRED_TIMEOUT_SECONDS: - logger.info(f"倾听等待超过 {DESIRED_TIMEOUT_SECONDS} 秒...添加思考目标。") + logger.info(f"[私聊][{self.private_name}]倾听等待超过 {DESIRED_TIMEOUT_SECONDS} 秒...添加思考目标。") wait_goal = { # 保持 goal 文本一致 "goal": f"你等待了{elapsed_time / 60:.1f}分钟,对方似乎话说一半突然消失了,可能忙去了?也可能忘记了回复?要问问吗?还是结束对话?或继续等待?思考接下来要做什么", "reasoning": "对方话说一半消失了,很久没有回复", } conversation_info.goal_list.append(wait_goal) - logger.info(f"添加目标: {wait_goal}") + logger.info(f"[私聊][{self.private_name}]添加目标: {wait_goal}") return True # 返回 True 表示超时 await asyncio.sleep(5) # 每 5 秒检查一次 - logger.debug("倾听等待中...") # 同上,可以考虑注释掉 + logger.debug(f"[私聊][{self.private_name}]倾听等待中...") # 同上,可以考虑注释掉