From 34323b65a2704fed6d2bb265826b700f826a50b0 Mon Sep 17 00:00:00 2001 From: 114514 <2514624910@qq.com> Date: Wed, 7 May 2025 03:51:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=8D=E6=AC=A1=E9=82=AA=E6=81=B6=E7=9B=B4?= =?UTF-8?q?=E6=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/chat_observer.py | 14 +++ src/plugins/PFC/conversation.py | 113 ++++++++++++++---- .../PFC/pfc_relationship_translator.py | 60 ++++++++++ 3 files changed, 162 insertions(+), 25 deletions(-) create mode 100644 src/plugins/PFC/pfc_relationship_translator.py diff --git a/src/plugins/PFC/chat_observer.py b/src/plugins/PFC/chat_observer.py index 22cbf27d..f4f43fea 100644 --- a/src/plugins/PFC/chat_observer.py +++ b/src/plugins/PFC/chat_observer.py @@ -101,6 +101,20 @@ class ChatObserver: message: 消息数据 """ try: + if isinstance(message, dict): # 确保是字典才添加 + self.message_cache.append(message) + # 可选:限制 message_cache 的大小,例如只保留最近 N 条 + # 你可以根据你的需求调整 MAX_CACHE_SIZE + # 对于情绪判断,可能不需要太长的历史,例如 5-10 条可能就足够了 + # 但 ChatObserver 的 get_cached_messages 也可能被其他地方用于获取更长的历史 + # 所以这里的 MAX_CACHE_SIZE 需要权衡,或者让调用者自己决定 limit + MAX_CACHE_SIZE = 30 # 例如,保留最近30条作为通用缓存 + if len(self.message_cache) > MAX_CACHE_SIZE: + self.message_cache = self.message_cache[-MAX_CACHE_SIZE:] + logger.debug(f"[私聊][{self.private_name}] 消息已添加到 ChatObserver 缓存,当前缓存大小: {len(self.message_cache)}") + else: + logger.warning(f"[私聊][{self.private_name}] 尝试向 message_cache 添加非字典类型消息: {type(message)}") + # 发送新消息通知 notification = create_new_message_notification( sender="chat_observer", target="observation_info", message=message diff --git a/src/plugins/PFC/conversation.py b/src/plugins/PFC/conversation.py index a95ca7a1..70e45886 100644 --- a/src/plugins/PFC/conversation.py +++ b/src/plugins/PFC/conversation.py @@ -26,7 +26,7 @@ from ...config.config import global_config # 导入用户信息 from ..person_info.person_info import person_info_manager # 导入关系 -from ..person_info.relationship_manager import relationship_manager +from .pfc_relationship_translator import translate_relationship_value_to_text # 导入情绪 from ..moods.moods import MoodManager @@ -93,7 +93,7 @@ class Conversation: # --- 新增:初始化管理器实例 --- self.person_info_mng = person_info_manager - self.relationship_mng = relationship_manager + self.relationship_mng = translate_relationship_value_to_text self.mood_mng = MoodManager.get_instance() # MoodManager 是单例 # 初始化所有核心组件为 None,将在 _initialize 中创建 @@ -281,6 +281,27 @@ class Conversation: else: logger.warning(f"[私聊][{self.private_name}] MoodManager 未能启动,相关功能可能受限。") + # --- 在初始化完成前,尝试加载一次关系和情绪信息 --- + if self.conversation_info and self.conversation_info.person_id and self.relationship_mng: + try: + self.conversation_info.relationship_text = await self.relationship_mng.build_relationship_info( + self.conversation_info.person_id, + is_id=True + ) + logger.info(f"[私聊][{self.private_name}] 初始化时加载关系文本: {self.conversation_info.relationship_text}") + except Exception as e_init_rel: + logger.error(f"[私聊][{self.private_name}] 初始化时加载关系文本出错: {e_init_rel}") + # 保留默认值 + + if self.conversation_info and self.mood_mng: + try: + self.conversation_info.current_emotion_text = self.mood_mng.get_prompt() + logger.info(f"[私聊][{self.private_name}] 初始化时加载情绪文本: {self.conversation_info.current_emotion_text}") + except Exception as e_init_emo: + logger.error(f"[私聊][{self.private_name}] 初始化时加载情绪文本出错: {e_init_emo}") + # 保留默认值 + + # 6. 标记初始化成功并设置运行状态 self._initialized = True self.should_continue = True # 初始化成功,标记可以继续运行循环 @@ -428,6 +449,22 @@ class Conversation: logger.info(f"[私聊][{self.private_name}] 正在停止对话实例: {self.stream_id}") self.should_continue = False # 设置标志,让主循环退出 + # --- 新增:在对话结束时调用最终关系更新 --- + if self._initialized and self.relationship_updater and self.conversation_info and self.observation_info and self.chat_observer: + try: + logger.info(f"[私聊][{self.private_name}] 准备执行最终关系评估...") + await self.relationship_updater.update_relationship_final( + conversation_info=self.conversation_info, + observation_info=self.observation_info, + chat_observer_for_history=self.chat_observer + ) + logger.info(f"[私聊][{self.private_name}] 最终关系评估已调用。") + except Exception as e_final_rel: + logger.error(f"[私聊][{self.private_name}] 调用最终关系评估时出错: {e_final_rel}") + logger.error(traceback.format_exc()) + else: + logger.warning(f"[私聊][{self.private_name}] 跳过最终关系评估,因为实例未完全初始化或缺少必要组件。") + # 停止空闲对话检测器 if self.idle_conversation_starter: self.idle_conversation_starter.stop() @@ -515,46 +552,72 @@ class Conversation: try: if self.conversation_info and self._initialized: # 确保 conversation_info 和实例已初始化 # 更新关系文本 - if self.conversation_info.person_id and self.observation_info and self.observation_info.sender_platform and self.observation_info.sender_user_id: + if self.conversation_info.person_id: # 确保 person_id 已获取 try: - # relationship_manager.build_relationship_info 需要一个 (platform, user_id, user_nickname) 格式的元组 - # 注意 user_id 应为 RelationshipManager 所期望的类型(通常是原始的,可能是字符串或数字,检查其内部实现) - # person_info.py 中 get_person_id 接收 int,但 build_relationship_info 的 person 参数更灵活 - # 这里我们假设 observation_info.sender_user_id 是字符串形式的 user_id - # 如果 RelationshipManager 内部的 get_person_id 需要 int,这里可能需要转换 - # 但 RelationshipManager 的 build_relationship_info 方法第一个参数 person 可以直接是 person_id (is_id=True) - # 或者是一个 (platform, user_id, nickname) 元组 (is_id=False) - # 为了安全,我们用 person_id - self.conversation_info.relationship_text = await self.relationship_mng.build_relationship_info( + # 1.直接从 person_info_manager 获取数值型的 relationship_value + numeric_relationship_value = await self.person_info_mng.get_value( self.conversation_info.person_id, - is_id=True # 明确告知是 person_id + "relationship_value" ) - logger.debug(f"[私聊][{self.private_name}] 更新关系文本: {self.conversation_info.relationship_text}") + + # 确保 relationship_value 是浮点数 (可以复用 relationship_manager 中的 ensure_float,或者在这里简单处理) + if not isinstance(numeric_relationship_value, (int, float)): + # 尝试从 Decimal128 转换 (如果你的数据库用的是这个) + from bson.decimal128 import Decimal128 + if isinstance(numeric_relationship_value, Decimal128): + numeric_relationship_value = float(numeric_relationship_value.to_decimal()) + else: # 其他类型,或转换失败,给默认值 + logger.warning(f"[私聊][{self.private_name}] 获取的 relationship_value 类型未知 ({type(numeric_relationship_value)}) 或转换失败,默认为0.0") + numeric_relationship_value = 0.0 + + logger.debug(f"[私聊][{self.private_name}] 获取到数值型关系值: {numeric_relationship_value}") + + # 2. 使用PFC内部的翻译函数将其转换为文本描述 + simplified_relationship_text = translate_relationship_value_to_text(numeric_relationship_value) + self.conversation_info.relationship_text = simplified_relationship_text + + logger.debug(f"[私聊][{self.private_name}] 更新后关系文本 (PFC内部翻译): {self.conversation_info.relationship_text}") + except Exception as e_rel: - logger.error(f"[私聊][{self.private_name}] 更新关系文本时出错: {e_rel}") - self.conversation_info.relationship_text = "我们之间的关系有点微妙。" # 出错时的默认值 - elif not self.conversation_info.person_id and self.observation_info and self.observation_info.sender_user_id and self.observation_info.sender_platform: - # 如果 person_id 之前没获取到,在这里尝试再次获取 + logger.error(f"[私聊][{self.private_name}] 更新关系文本(PFC内部翻译)时出错: {e_rel}") + self.conversation_info.relationship_text = "你们的关系是:普通。" # 出错时的默认值 + elif self.observation_info and self.observation_info.sender_user_id and self.observation_info.sender_platform: + # 如果 person_id 之前没获取到,在这里尝试再次获取 (这部分逻辑保持,因为 person_id 是必须的) try: private_user_id_int = int(self.observation_info.sender_user_id) self.conversation_info.person_id = self.person_info_mng.get_person_id( self.observation_info.sender_platform, private_user_id_int ) - await self.person_info_mng.get_or_create_person( + await self.person_info_mng.get_or_create_person( #确保用户存在 platform=self.observation_info.sender_platform, user_id=private_user_id_int, nickname=self.observation_info.sender_name if self.observation_info.sender_name else "未知用户", ) - if self.conversation_info.person_id: # 再次尝试更新关系文本 - self.conversation_info.relationship_text = await self.relationship_mng.build_relationship_info( - self.conversation_info.person_id, is_id=True - ) + if self.conversation_info.person_id: # 如果成功获取 person_id,则再次尝试更新关系文本 + numeric_relationship_value = await self.person_info_mng.get_value( + self.conversation_info.person_id, + "relationship_value" + ) + if not isinstance(numeric_relationship_value, (int, float)): + from bson.decimal128 import Decimal128 + if isinstance(numeric_relationship_value, Decimal128): + numeric_relationship_value = float(numeric_relationship_value.to_decimal()) + else: + numeric_relationship_value = 0.0 + self.conversation_info.relationship_text = translate_relationship_value_to_text(numeric_relationship_value) + logger.debug(f"[私聊][{self.private_name}] (备用逻辑)更新后关系文本: {self.conversation_info.relationship_text}") + except ValueError: logger.error(f"[私聊][{self.private_name}] 循环中无法将 sender_user_id ('{self.observation_info.sender_user_id}') 转换为整数。") + self.conversation_info.relationship_text = "你们的关系是:普通。" except Exception as e_pid_loop: - logger.error(f"[私聊][{self.private_name}] 循环中获取 person_id 时出错: {e_pid_loop}") - + logger.error(f"[私聊][{self.private_name}] 循环中获取 person_id 并更新关系时出错: {e_pid_loop}") + self.conversation_info.relationship_text = "你们的关系是:普通。" + else: + # 如果 person_id 仍无法确定 + self.conversation_info.relationship_text = "你们的关系是:普通。" # 或 "你们的关系是:未知。" + # 更新情绪文本 if self.mood_mng: self.conversation_info.current_emotion_text = self.mood_mng.get_prompt() diff --git a/src/plugins/PFC/pfc_relationship_translator.py b/src/plugins/PFC/pfc_relationship_translator.py new file mode 100644 index 00000000..09cc3ab0 --- /dev/null +++ b/src/plugins/PFC/pfc_relationship_translator.py @@ -0,0 +1,60 @@ +# 直接完整导入群聊的relationship_manager.py可能不可取,因为对于PFC的planner来说,其暗示了选择回复,所以新建代码文件来适配PFC的决策层面 +from src.common.logger_manager import get_logger + +logger = get_logger("pfc_relationship_translator") + +# 这个函数复用 relationship_manager.py 中的 calculate_level_num 的逻辑 +def _calculate_relationship_level_num(relationship_value: float) -> int: + """ + 根据关系值计算关系等级编号 (0-5)。 + 这里的阈值应与 relationship_manager.py 中的保持一致 + """ + if not isinstance(relationship_value, (int, float)): + logger.warning(f"传入的 relationship_value '{relationship_value}' 不是有效的数值类型,默认为0。") + relationship_value = 0.0 + + if -1000 <= relationship_value < -227: + level_num = 0 # 厌恶 + elif -227 <= relationship_value < -73: + level_num = 1 # 冷漠 + elif -73 <= relationship_value < 227: + level_num = 2 # 普通/认识 + elif 227 <= relationship_value < 587: + level_num = 3 # 友好 + elif 587 <= relationship_value < 900: + level_num = 4 # 喜欢 + elif 900 <= relationship_value <= 1000: + level_num = 5 # 暧昧 + else: + # 超出范围的值处理 + if relationship_value > 1000: + level_num = 5 + elif relationship_value < -1000: + level_num = 0 + else: # 理论上不会到这里,除非前面的条件逻辑有误 + logger.warning(f"关系值 {relationship_value} 未落入任何预设范围,默认为普通。") + level_num = 2 + return level_num + +def translate_relationship_value_to_text(relationship_value: float) -> str: + """ + 将数值型的关系值转换为PFC私聊场景下简洁的关系描述文本。 + """ + level_num = _calculate_relationship_level_num(relationship_value) + + relationship_descriptions = [ + "厌恶", # level_num 0 + "冷漠", # level_num 1 + "初识", # level_num 2 + "友好", # level_num 3 + "喜欢", # level_num 4 + "暧昧" # level_num 5 + ] + + if 0 <= level_num < len(relationship_descriptions): + description = relationship_descriptions[level_num] + else: + description = "普通" # 默认或错误情况 + logger.warning(f"计算出的 level_num ({level_num}) 无效,关系描述默认为 '普通'") + + return f"你们的关系是:{description}。" \ No newline at end of file