mirror of https://github.com/Mai-with-u/MaiBot.git
加入关系判断和情绪,邪恶直推!
parent
5794774290
commit
0ed2e22360
|
|
@ -493,6 +493,7 @@ class BotConfig:
|
|||
"llm_PFC_action_planner",
|
||||
"llm_PFC_chat",
|
||||
"llm_PFC_reply_checker",
|
||||
"llm_PFC_relationship_eval",
|
||||
]
|
||||
|
||||
for item in config_list:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ logger = get_logger("pfc_action_planner")
|
|||
# Prompt(1): 首次回复或非连续回复时的决策 Prompt
|
||||
PROMPT_INITIAL_REPLY = """
|
||||
当前时间:{current_time_str}
|
||||
{persona_text}。现在你在参与一场QQ私聊,请根据以下【所有信息】审慎且灵活的决策下一步行动,可以回复,可以倾听,可以调取知识,甚至可以屏蔽对方:
|
||||
{persona_text}
|
||||
现在你正在和{sender_name}在QQ上私聊
|
||||
你和对方的关系是:{relationship_text}
|
||||
你现在的心情是:{current_emotion_text}
|
||||
请根据以下【所有信息】审慎且灵活的决策下一步行动,可以回复,可以倾听,可以调取知识,甚至可以屏蔽对方:
|
||||
|
||||
【当前对话目标】
|
||||
{goals_str}
|
||||
|
|
@ -58,7 +62,11 @@ block_and_ignore: 更加极端的结束对话方式,直接结束对话并在
|
|||
# Prompt(2): 上一次成功回复后,决定继续发言时的决策 Prompt
|
||||
PROMPT_FOLLOW_UP = """
|
||||
当前时间:{current_time_str}
|
||||
{persona_text}。现在你在参与一场QQ私聊,刚刚你已经回复了对方,请根据以下【所有信息】审慎且灵活的决策下一步行动,可以继续发送新消息,可以等待,可以倾听,可以调取知识,甚至可以屏蔽对方:
|
||||
{persona_text}
|
||||
现在你正在和{sender_name}在QQ上私聊,**并且刚刚你已经回复了对方**
|
||||
你与对方的关系是:{relationship_text}
|
||||
你现在的心情是:{current_emotion_text}
|
||||
请根据以下【所有信息】审慎且灵活的决策下一步行动,可以继续发送新消息,可以等待,可以倾听,可以调取知识,甚至可以屏蔽对方:
|
||||
|
||||
【当前对话目标】
|
||||
{goals_str}
|
||||
|
|
@ -170,6 +178,14 @@ class ActionPlanner:
|
|||
timeout_context = self._get_timeout_context(conversation_info)
|
||||
goals_str = self._build_goals_string(conversation_info)
|
||||
chat_history_text = await self._build_chat_history_text(observation_info)
|
||||
# 获取 sender_name, relationship_text, current_emotion_text
|
||||
sender_name_str = getattr(observation_info, 'sender_name', '对方') # 从 observation_info 获取
|
||||
if not sender_name_str: sender_name_str = '对方' # 再次确保有默认值
|
||||
|
||||
relationship_text_str = getattr(conversation_info, 'relationship_text', '我们还不熟悉。')
|
||||
current_emotion_text_str = getattr(conversation_info, 'current_emotion_text', '心情平静。')
|
||||
|
||||
|
||||
persona_text = f"你的名字是{self.name},{self.personality_info}。"
|
||||
action_history_summary, last_action_context = self._build_action_history_context(conversation_info)
|
||||
retrieved_memory_str, retrieved_knowledge_str = await retrieve_contextual_info(
|
||||
|
|
@ -212,7 +228,11 @@ class ActionPlanner:
|
|||
chat_history_text=chat_history_text if chat_history_text.strip() else "还没有聊天记录。",
|
||||
retrieved_memory_str=retrieved_memory_str if retrieved_memory_str else "无相关记忆。",
|
||||
retrieved_knowledge_str=retrieved_knowledge_str if retrieved_knowledge_str else "无相关知识。",
|
||||
current_time_str=current_time_value # 新增:传入当前时间字符串
|
||||
current_time_str=current_time_value, # 新增:传入当前时间字符串
|
||||
### 标记新增/修改区域 开始 ###
|
||||
sender_name=sender_name_str,
|
||||
relationship_text=relationship_text_str,
|
||||
current_emotion_text=current_emotion_text_str
|
||||
)
|
||||
logger.debug(f"[私聊][{self.private_name}] 发送到LLM的最终提示词:\n------\n{prompt}\n------")
|
||||
except KeyError as fmt_key_err:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,16 @@ from ..chat.message import Message # 假设 Message 类在这里
|
|||
# 导入全局配置
|
||||
from ...config.config import global_config
|
||||
|
||||
# 导入用户信息
|
||||
from ..person_info.person_info import person_info_manager
|
||||
# 导入关系
|
||||
from ..person_info.relationship_manager import relationship_manager
|
||||
# 导入情绪
|
||||
from ..moods.moods import MoodManager
|
||||
|
||||
from .pfc_relationship_updater import PfcRelationshipUpdater # 新增
|
||||
from .pfc_emotion_updater import PfcEmotionUpdater # 新增
|
||||
|
||||
# 导入 PFC 内部组件和类型
|
||||
from .pfc_types import ConversationState # 导入更新后的 pfc_types
|
||||
from .pfc import GoalAnalyzer # 假设 GoalAnalyzer 在 pfc.py
|
||||
|
|
@ -81,7 +91,14 @@ class Conversation:
|
|||
self.generated_reply: str = "" # 存储最近生成的回复内容
|
||||
self.chat_stream: Optional[ChatStream] = None # 关联的聊天流对象
|
||||
|
||||
# --- 新增:初始化管理器实例 ---
|
||||
self.person_info_mng = person_info_manager
|
||||
self.relationship_mng = relationship_manager
|
||||
self.mood_mng = MoodManager.get_instance() # MoodManager 是单例
|
||||
|
||||
# 初始化所有核心组件为 None,将在 _initialize 中创建
|
||||
self.relationship_updater: Optional[PfcRelationshipUpdater] = None # 新增
|
||||
self.emotion_updater: Optional[PfcEmotionUpdater] = None # 新增
|
||||
self.action_planner: Optional[ActionPlanner] = None
|
||||
self.goal_analyzer: Optional[GoalAnalyzer] = None
|
||||
self.reply_generator: Optional[ReplyGenerator] = None
|
||||
|
|
@ -122,6 +139,18 @@ class Conversation:
|
|||
logger.debug(f"[私聊][{self.private_name}] 初始化 ActionPlanner...")
|
||||
self.action_planner = ActionPlanner(self.stream_id, self.private_name)
|
||||
|
||||
self.relationship_updater = PfcRelationshipUpdater(
|
||||
private_name=self.private_name,
|
||||
bot_name=global_config.BOT_NICKNAME # 或者 self.name (如果 Conversation 类有 self.name)
|
||||
)
|
||||
logger.info(f"[私聊][{self.private_name}] PfcRelationshipUpdater 初始化完成。")
|
||||
|
||||
self.emotion_updater = PfcEmotionUpdater(
|
||||
private_name=self.private_name,
|
||||
bot_name=global_config.BOT_NICKNAME # 或者 self.name
|
||||
)
|
||||
logger.info(f"[私聊][{self.private_name}] PfcEmotionUpdater 初始化完成。")
|
||||
|
||||
logger.debug(f"[私聊][{self.private_name}] 初始化 GoalAnalyzer...")
|
||||
self.goal_analyzer = GoalAnalyzer(self.stream_id, self.private_name)
|
||||
|
||||
|
|
@ -175,6 +204,66 @@ class Conversation:
|
|||
# 4. 加载初始聊天记录
|
||||
await self._load_initial_history()
|
||||
|
||||
# 4.1 加载用户数据
|
||||
# 尝试从 observation_info 获取,这依赖于 _load_initial_history 的实现
|
||||
private_user_id_str: Optional[str] = None
|
||||
private_platform_str: Optional[str] = None
|
||||
private_nickname_str: Optional[str] = None
|
||||
|
||||
if self.observation_info and self.observation_info.last_message_sender and self.observation_info.last_message_sender != self.bot_qq_str:
|
||||
# 如果历史记录最后一条不是机器人发的,那么发送者就是对方
|
||||
# 假设 observation_info 中已经有了 sender_user_id, sender_platform, sender_name
|
||||
# 这些字段应该在 observation_info.py 的 update_from_message 中从非机器人消息填充
|
||||
# 并且 _load_initial_history 处理历史消息时也应该填充它们
|
||||
# 这里的逻辑是:取 observation_info 中最新记录的非机器人发送者的信息
|
||||
if self.observation_info.sender_user_id and self.observation_info.sender_platform:
|
||||
private_user_id_str = self.observation_info.sender_user_id
|
||||
private_platform_str = self.observation_info.sender_platform
|
||||
private_nickname_str = self.observation_info.sender_name
|
||||
logger.info(f"[私聊][{self.private_name}] 从 ObservationInfo 获取到私聊对象信息: ID={private_user_id_str}, Platform={private_platform_str}, Name={private_nickname_str}")
|
||||
|
||||
if not private_user_id_str and self.chat_stream: # 如果 observation_info 中没有,尝试从 chat_stream (通常代表对方)
|
||||
if self.chat_stream.user_info and str(self.chat_stream.user_info.user_id) != self.bot_qq_str : # 确保不是机器人自己
|
||||
private_user_id_str = str(self.chat_stream.user_info.user_id)
|
||||
private_platform_str = self.chat_stream.user_info.platform
|
||||
private_nickname_str = self.chat_stream.user_info.user_nickname
|
||||
logger.info(f"[私聊][{self.private_name}] 从 ChatStream 获取到私聊对象信息: ID={private_user_id_str}, Platform={private_platform_str}, Name={private_nickname_str}")
|
||||
elif self.chat_stream.group_info is None and self.private_name: # 私聊场景,且 private_name 可能有用
|
||||
# 这是一个备选方案,如果 private_name 直接是 user_id
|
||||
# 你需要确认 private_name 的确切含义和格式
|
||||
# logger.warning(f"[私聊][{self.private_name}] 尝试使用 private_name ('{self.private_name}') 作为 user_id,平台默认为 'qq'")
|
||||
# private_user_id_str = self.private_name
|
||||
# private_platform_str = "qq" # 假设平台是qq
|
||||
# private_nickname_str = self.private_name # 昵称也暂时用 private_name
|
||||
pass # 暂时不启用此逻辑,依赖 observation_info 或 chat_stream.user_info
|
||||
|
||||
if private_user_id_str and private_platform_str:
|
||||
try:
|
||||
# 将 user_id 转换为整数类型,因为 person_info_manager.get_person_id 需要 int
|
||||
private_user_id_int = int(private_user_id_str)
|
||||
self.conversation_info.person_id = self.person_info_mng.get_person_id(
|
||||
private_platform_str,
|
||||
private_user_id_int # 使用转换后的整数ID
|
||||
)
|
||||
logger.info(f"[私聊][{self.private_name}] 获取到 person_id: {self.conversation_info.person_id} for {private_platform_str}:{private_user_id_str}")
|
||||
|
||||
# 确保用户在数据库中存在,如果不存在则创建
|
||||
# get_or_create_person 内部处理 person_id 的生成,所以我们直接传 platform 和 user_id
|
||||
await self.person_info_mng.get_or_create_person(
|
||||
platform=private_platform_str,
|
||||
user_id=private_user_id_int, # 使用转换后的整数ID
|
||||
nickname=private_nickname_str if private_nickname_str else "未知用户",
|
||||
# user_cardname 和 user_avatar 如果能从 chat_stream.user_info 或 observation_info 获取也应传入
|
||||
# user_cardname = self.chat_stream.user_info.card if self.chat_stream and self.chat_stream.user_info else None,
|
||||
# user_avatar = self.chat_stream.user_info.avatar if self.chat_stream and self.chat_stream.user_info else None
|
||||
)
|
||||
except ValueError:
|
||||
logger.error(f"[私聊][{self.private_name}] 无法将 private_user_id_str ('{private_user_id_str}') 转换为整数。")
|
||||
except Exception as e_pid:
|
||||
logger.error(f"[私聊][{self.private_name}] 获取或创建 person_id 时出错: {e_pid}")
|
||||
else:
|
||||
logger.warning(f"[私聊][{self.private_name}] 未能确定私聊对象的 user_id 或 platform,无法获取 person_id。将在收到消息后尝试。")
|
||||
|
||||
# 5. 启动需要后台运行的组件
|
||||
logger.debug(f"[私聊][{self.private_name}] 启动 ChatObserver...")
|
||||
self.chat_observer.start()
|
||||
|
|
@ -183,6 +272,15 @@ class Conversation:
|
|||
self.idle_conversation_starter.start()
|
||||
logger.info(f"[私聊][{self.private_name}] 空闲对话检测器已启动")
|
||||
|
||||
# 5.1 启动 MoodManager 的后台更新
|
||||
if self.mood_mng and hasattr(self.mood_mng, 'start_mood_update') and not self.mood_mng._running:
|
||||
self.mood_mng.start_mood_update(update_interval=global_config.mood_update_interval) # 使用配置的更新间隔
|
||||
logger.info(f"[私聊][{self.private_name}] MoodManager 已启动后台更新,间隔: {global_config.mood_update_interval} 秒。")
|
||||
elif self.mood_mng and self.mood_mng._running:
|
||||
logger.info(f"[私聊][{self.private_name}] MoodManager 已在运行中。")
|
||||
else:
|
||||
logger.warning(f"[私聊][{self.private_name}] MoodManager 未能启动,相关功能可能受限。")
|
||||
|
||||
# 6. 标记初始化成功并设置运行状态
|
||||
self._initialized = True
|
||||
self.should_continue = True # 初始化成功,标记可以继续运行循环
|
||||
|
|
@ -338,6 +436,10 @@ class Conversation:
|
|||
if self.observation_info and self.chat_observer:
|
||||
self.observation_info.unbind_from_chat_observer()
|
||||
|
||||
if self.mood_mng and hasattr(self.mood_mng, 'stop_mood_update') and self.mood_mng._running:
|
||||
self.mood_mng.stop_mood_update()
|
||||
logger.info(f"[私聊][{self.private_name}] MoodManager 后台更新已停止。")
|
||||
|
||||
# ChatObserver 是单例,通常不由单个 Conversation 停止
|
||||
# 如果需要,可以在管理器层面处理 ChatObserver 的生命周期
|
||||
|
||||
|
|
@ -411,6 +513,57 @@ 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:
|
||||
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(
|
||||
self.conversation_info.person_id,
|
||||
is_id=True # 明确告知是 person_id
|
||||
)
|
||||
logger.debug(f"[私聊][{self.private_name}] 更新关系文本: {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 之前没获取到,在这里尝试再次获取
|
||||
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(
|
||||
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
|
||||
)
|
||||
except ValueError:
|
||||
logger.error(f"[私聊][{self.private_name}] 循环中无法将 sender_user_id ('{self.observation_info.sender_user_id}') 转换为整数。")
|
||||
except Exception as e_pid_loop:
|
||||
logger.error(f"[私聊][{self.private_name}] 循环中获取 person_id 时出错: {e_pid_loop}")
|
||||
|
||||
# 更新情绪文本
|
||||
if self.mood_mng:
|
||||
self.conversation_info.current_emotion_text = self.mood_mng.get_prompt()
|
||||
logger.debug(f"[私聊][{self.private_name}] 更新情绪文本: {self.conversation_info.current_emotion_text}")
|
||||
else:
|
||||
# 如果 mood_mng 未初始化,使用 ConversationInfo 中的默认值
|
||||
pass # self.conversation_info.current_emotion_text 会保持其在 ConversationInfo 中的默认值
|
||||
### 标记新增/修改区域 结束 ###
|
||||
|
||||
# 1. 检查核心组件是否都已初始化
|
||||
if not all([self.action_planner, self.observation_info, self.conversation_info]):
|
||||
logger.error(f"[私聊][{self.private_name}] 核心组件未初始化,无法继续规划循环。将等待5秒后重试...")
|
||||
|
|
@ -458,6 +611,37 @@ class Conversation:
|
|||
f"[私聊][{self.private_name}] 规划期间收到新消息总数: {new_msg_count}, 来自他人: {other_new_msg_count}"
|
||||
)
|
||||
|
||||
if self.conversation_info and other_new_msg_count > 0: # 如果有来自他人的新消息
|
||||
self.conversation_info.current_instance_message_count += other_new_msg_count
|
||||
logger.debug(f"[私聊][{self.private_name}] 用户发送新消息,实例消息计数增加到: {self.conversation_info.current_instance_message_count}")
|
||||
|
||||
# 调用增量关系更新
|
||||
if self.relationship_updater:
|
||||
await self.relationship_updater.update_relationship_incremental(
|
||||
conversation_info=self.conversation_info,
|
||||
observation_info=self.observation_info,
|
||||
chat_observer_for_history=self.chat_observer
|
||||
)
|
||||
|
||||
# 调用情绪更新
|
||||
if self.emotion_updater and other_new_messages_during_planning:
|
||||
# 取最后一条用户消息作为情绪更新的上下文事件
|
||||
last_user_msg = other_new_messages_during_planning[-1]
|
||||
last_user_msg_text = last_user_msg.get("processed_plain_text", "用户发了新消息")
|
||||
|
||||
sender_name_for_event = getattr(self.observation_info, 'sender_name', '对方')
|
||||
if not sender_name_for_event: # 如果 observation_info 中还没有,尝试从消息中取
|
||||
user_info_dict = last_user_msg.get("user_info", {})
|
||||
sender_name_for_event = user_info_dict.get("user_nickname", "对方")
|
||||
|
||||
event_desc = f"用户【{sender_name_for_event}】发送了新消息: '{last_user_msg_text[:30]}...'"
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=self.conversation_info,
|
||||
observation_info=self.observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_desc
|
||||
)
|
||||
|
||||
# 5. 根据动作类型和新消息数量,判断是否需要中断当前规划
|
||||
should_interrupt: bool = False
|
||||
interrupt_reason: str = ""
|
||||
|
|
@ -806,7 +990,27 @@ class Conversation:
|
|||
f"[私聊][{self.private_name}] 规划期间无他人新消息,下一轮【允许】使用追问逻辑 (基于 '{action}')。"
|
||||
)
|
||||
conversation_info.last_successful_reply_action = action # 允许追问
|
||||
|
||||
|
||||
if conversation_info: # 确保 conversation_info 存在
|
||||
conversation_info.current_instance_message_count += 1
|
||||
logger.debug(f"[私聊][{self.private_name}] 实例消息计数(机器人发送后)增加到: {conversation_info.current_instance_message_count}")
|
||||
|
||||
if self.relationship_updater:
|
||||
await self.relationship_updater.update_relationship_incremental(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer
|
||||
)
|
||||
|
||||
sent_reply_summary = self.generated_reply[:50] if self.generated_reply else "空回复"
|
||||
event_for_emotion_update = f"你刚刚发送了消息: '{sent_reply_summary}...'"
|
||||
if self.emotion_updater:
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_for_emotion_update
|
||||
)
|
||||
else:
|
||||
# 如果发送失败
|
||||
logger.error(f"[私聊][{self.private_name}] 动作 '{action}': 发送回复失败。")
|
||||
|
|
@ -888,6 +1092,25 @@ class Conversation:
|
|||
message_ids_to_clear.add(msg_id)
|
||||
if message_ids_to_clear:
|
||||
await observation_info.clear_processed_messages(message_ids_to_clear)
|
||||
|
||||
### [[[ 新增:调用关系和情绪更新 ]]] ###
|
||||
if conversation_info: # 确保 conversation_info 存在
|
||||
conversation_info.current_instance_message_count += 1
|
||||
logger.debug(f"[私聊][{self.private_name}] 实例消息计数(告别语后)增加到: {conversation_info.current_instance_message_count}")
|
||||
|
||||
# 告别通常是结束,可以不进行增量关系更新,但情绪可以更新
|
||||
# if self.relationship_updater:
|
||||
# await self.relationship_updater.update_relationship_incremental(...)
|
||||
|
||||
sent_reply_summary = self.generated_reply[:50] if self.generated_reply else "空回复"
|
||||
event_for_emotion_update = f"你发送了告别消息: '{sent_reply_summary}...'"
|
||||
if self.emotion_updater:
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_for_emotion_update
|
||||
)
|
||||
# 发送成功后结束对话
|
||||
self.should_continue = False
|
||||
else:
|
||||
|
|
@ -906,6 +1129,14 @@ class Conversation:
|
|||
# 调用 GoalAnalyzer 分析并更新目标
|
||||
await self.goal_analyzer.analyze_goal(conversation_info, observation_info)
|
||||
action_successful = True # 标记成功
|
||||
event_for_emotion_update = "你重新思考了对话目标和方向"
|
||||
if self.emotion_updater and conversation_info and observation_info: # 确保updater和info都存在
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_for_emotion_update
|
||||
)
|
||||
|
||||
# 4. 处理倾听动作
|
||||
elif action == "listening":
|
||||
|
|
@ -916,6 +1147,14 @@ class Conversation:
|
|||
# 调用 Waiter 的倾听等待方法,内部会处理超时
|
||||
await self.waiter.wait_listening(conversation_info)
|
||||
action_successful = True # listening 动作本身执行即视为成功,后续由新消息或超时驱动
|
||||
event_for_emotion_update = "你决定耐心倾听对方的发言"
|
||||
if self.emotion_updater and conversation_info and observation_info:
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_for_emotion_update
|
||||
)
|
||||
|
||||
# 5. 处理结束对话动作
|
||||
elif action == "end_conversation":
|
||||
|
|
@ -933,6 +1172,16 @@ class Conversation:
|
|||
)
|
||||
self.state = ConversationState.IGNORED # 设置忽略状态
|
||||
action_successful = True # 标记成功
|
||||
event_for_emotion_update = "当前对话让你感到不适,你决定暂时不再理会对方"
|
||||
if self.emotion_updater and conversation_info and observation_info:
|
||||
# 可以让LLM判断此时的情绪,或者直接设定一个倾向(比如厌恶、不耐烦)
|
||||
# 这里还是让LLM判断
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_for_emotion_update
|
||||
)
|
||||
|
||||
# 7. 处理等待动作
|
||||
elif action == "wait":
|
||||
|
|
@ -944,6 +1193,19 @@ class Conversation:
|
|||
# wait 方法返回是否超时 (True=超时, False=未超时/被新消息中断)
|
||||
timeout_occurred = await self.waiter.wait(self.conversation_info)
|
||||
action_successful = True # wait 动作本身执行即视为成功
|
||||
event_for_emotion_update = ""
|
||||
if timeout_occurred: # 假设 timeout_occurred 能正确反映是否超时
|
||||
event_for_emotion_update = "你等待对方回复,但对方长时间没有回应"
|
||||
else:
|
||||
event_for_emotion_update = "你选择等待对方的回复(对方可能很快回复了)"
|
||||
|
||||
if self.emotion_updater and conversation_info and observation_info:
|
||||
await self.emotion_updater.update_emotion_based_on_context(
|
||||
conversation_info=conversation_info,
|
||||
observation_info=observation_info,
|
||||
chat_observer_for_history=self.chat_observer,
|
||||
event_description=event_for_emotion_update
|
||||
)
|
||||
# wait 动作完成后不需要清理消息,等待新消息或超时触发重新规划
|
||||
logger.debug(f"[私聊][{self.private_name}] Wait 动作完成,无需在此清理消息。")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
from typing import Optional
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
|
||||
class ConversationInfo:
|
||||
def __init__(self):
|
||||
self.done_action = []
|
||||
self.goal_list = []
|
||||
self.knowledge_list = []
|
||||
self.memory_list = []
|
||||
self.done_action: List[Dict[str, Any]] = [] # 建议明确类型
|
||||
self.goal_list: List[Dict[str, Any]] = [] # 建议明确类型
|
||||
self.knowledge_list: List[Any] = [] # 建议明确类型
|
||||
self.memory_list: List[Any] = [] # 建议明确类型
|
||||
self.last_successful_reply_action: Optional[str] = None
|
||||
self.last_reply_rejection_reason: Optional[str] = None # 用于存储上次回复被拒原因
|
||||
self.last_rejected_reply_content: Optional[str] = None # 用于存储上次被拒的回复内容
|
||||
self.my_message_count: int = 0 # 用于存储连续发送了多少条消息
|
||||
self.my_message_count: int = 0 # 用于存储连续发送了多少条消息
|
||||
|
||||
# --- 新增字段 ---
|
||||
self.person_id: Optional[str] = None # 私聊对象的唯一ID
|
||||
self.relationship_text: Optional[str] = "你们还不熟悉。" # 与当前对话者的关系描述文本
|
||||
self.current_emotion_text: Optional[str] = "心情平静。" # 机器人当前的情绪描述文本
|
||||
self.current_instance_message_count: int = 0 # 当前私聊实例中的消息计数
|
||||
# --- 新增字段结束 ---
|
||||
|
|
@ -123,6 +123,12 @@ class ObservationInfo:
|
|||
"""初始化 ObservationInfo"""
|
||||
self.private_name: str = private_name
|
||||
|
||||
# 新增:发信人信息
|
||||
self.sender_name: Optional[str] = None
|
||||
self.sender_user_id: Optional[str] = None # 存储为字符串
|
||||
self.sender_platform: Optional[str] = None
|
||||
|
||||
|
||||
# 聊天记录相关
|
||||
self.chat_history: List[Dict[str, Any]] = [] # 存储已处理的消息历史
|
||||
self.chat_history_str: str = "还没有聊天记录。" # 用于生成 Prompt 的历史记录字符串
|
||||
|
|
@ -230,13 +236,37 @@ class ObservationInfo:
|
|||
if not message_time or not message_id:
|
||||
logger.warning(f"[私聊][{self.private_name}] 收到的消息缺少 time 或 message_id: {message}")
|
||||
return
|
||||
|
||||
# --- 新增/修改:提取并存储发信人详细信息 ---
|
||||
current_message_sender_id: Optional[str] = None
|
||||
if user_info:
|
||||
try:
|
||||
self.sender_user_id = str(user_info.user_id) # 确保是字符串
|
||||
self.sender_name = user_info.user_nickname # 或者 user_info.card 如果私聊时card更准
|
||||
self.sender_platform = user_info.platform
|
||||
current_message_sender_id = self.sender_user_id # 用于后续逻辑
|
||||
logger.debug(f"[私聊][{self.private_name}] 更新发信人信息: ID={self.sender_user_id}, Name={self.sender_name}, Platform={self.sender_platform}")
|
||||
except AttributeError as e:
|
||||
logger.error(f"[私聊][{self.private_name}] 从 UserInfo 对象提取信息时出错: {e}, UserInfo: {user_info}")
|
||||
# 如果提取失败,将这些新字段设为 None,避免使用旧数据
|
||||
self.sender_user_id = None
|
||||
self.sender_name = None
|
||||
self.sender_platform = None
|
||||
else:
|
||||
logger.warning(f"[私聊][{self.private_name}] 处理消息更新时缺少有效的 UserInfo, message_id: {message_id}")
|
||||
# 如果没有 UserInfo,也将这些新字段设为 None
|
||||
self.sender_user_id = None
|
||||
self.sender_name = None
|
||||
self.sender_platform = None
|
||||
# --- 新增/修改结束 ---
|
||||
|
||||
|
||||
# 更新最后消息时间(所有消息)
|
||||
if message_time > (self.last_message_time or 0):
|
||||
self.last_message_time = message_time
|
||||
self.last_message_id = message_id
|
||||
self.last_message_content = processed_text
|
||||
self.last_message_sender = sender_id_str
|
||||
self.last_message_sender = current_message_sender_id # 使用新获取的 current_message_sender_id
|
||||
|
||||
# 更新说话者特定时间
|
||||
if sender_id_str:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
# PFC/pfc_emotion_updater.py
|
||||
|
||||
from typing import List, Dict, Any, Optional
|
||||
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.plugins.models.utils_model import LLMRequest
|
||||
from src.plugins.moods.moods import MoodManager # MoodManager 本身是单例
|
||||
from src.plugins.utils.chat_message_builder import build_readable_messages
|
||||
|
||||
try:
|
||||
from .observation_info import ObservationInfo
|
||||
from .conversation_info import ConversationInfo
|
||||
except ImportError:
|
||||
from observation_info import ObservationInfo
|
||||
from conversation_info import ConversationInfo
|
||||
|
||||
from ...config.config import global_config # 导入全局配置
|
||||
|
||||
logger = get_logger("pfc_emotion_updater")
|
||||
|
||||
class PfcEmotionUpdater:
|
||||
def __init__(self, private_name: str, bot_name: str):
|
||||
"""
|
||||
初始化情绪更新器。
|
||||
"""
|
||||
self.private_name = private_name
|
||||
self.bot_name = bot_name
|
||||
self.mood_mng = MoodManager.get_instance() # 获取 MoodManager 单例
|
||||
|
||||
# LLM 实例 (根据 global_config.llm_summary 配置)
|
||||
llm_config_summary = getattr(global_config, 'llm_summary', None)
|
||||
if llm_config_summary and isinstance(llm_config_summary, dict):
|
||||
logger.info(f"[私聊][{self.private_name}] 使用 llm_summary 配置初始化情绪判断LLM。")
|
||||
self.llm = LLMRequest(
|
||||
model=llm_config_summary,
|
||||
temperature=llm_config_summary.get("temperature", 0.5), # temperature 来自其自身配置或默认0.7,这里用0.5
|
||||
max_tokens=llm_config_summary.get("max_tokens", 256), # 情绪词输出不需要很多token
|
||||
request_type="pfc_emotion_evaluation"
|
||||
)
|
||||
else:
|
||||
logger.error(f"[私聊][{self.private_name}] 未找到 llm_summary 配置或配置无效!情绪判断功能将受限。")
|
||||
self.llm = None # LLM 未初始化
|
||||
|
||||
self.EMOTION_UPDATE_INTENSITY = getattr(global_config, 'pfc_emotion_update_intensity', 0.6)
|
||||
self.EMOTION_HISTORY_COUNT = getattr(global_config, 'pfc_emotion_history_count', 5)
|
||||
|
||||
async def update_emotion_based_on_context(
|
||||
self,
|
||||
conversation_info: ConversationInfo,
|
||||
observation_info: ObservationInfo,
|
||||
chat_observer_for_history, # ChatObserver 实例
|
||||
event_description: str
|
||||
) -> None:
|
||||
if not self.llm:
|
||||
logger.error(f"[私聊][{self.private_name}] LLM未初始化,无法进行情绪更新。")
|
||||
# 即使LLM失败,也应该更新conversation_info中的情绪文本为MoodManager的当前状态
|
||||
if conversation_info and self.mood_mng:
|
||||
conversation_info.current_emotion_text = self.mood_mng.get_prompt()
|
||||
return
|
||||
|
||||
if not self.mood_mng or not conversation_info or not observation_info:
|
||||
logger.debug(f"[私聊][{self.private_name}] 情绪更新:缺少必要管理器或信息。")
|
||||
return
|
||||
|
||||
recent_messages_for_emotion: List[Dict[str, Any]] = []
|
||||
if chat_observer_for_history:
|
||||
recent_messages_for_emotion = chat_observer_for_history.get_cached_messages(limit=self.EMOTION_HISTORY_COUNT)
|
||||
elif observation_info.chat_history:
|
||||
recent_messages_for_emotion = observation_info.chat_history[-self.EMOTION_HISTORY_COUNT:]
|
||||
|
||||
readable_recent_history = await build_readable_messages(
|
||||
recent_messages_for_emotion, replace_bot_name=True, merge_messages=True, timestamp_mode="none"
|
||||
)
|
||||
|
||||
current_mood_text_from_manager = self.mood_mng.current_mood.text # 从 MoodManager 获取当前情绪文本
|
||||
sender_name_for_prompt = getattr(observation_info, 'sender_name', '对方')
|
||||
if not sender_name_for_prompt: sender_name_for_prompt = '对方'
|
||||
relationship_text_for_prompt = getattr(conversation_info, 'relationship_text', '关系一般。') # 从 ConversationInfo 获取关系文本
|
||||
|
||||
emotion_prompt = f"""你是机器人 {self.bot_name}。你现在的心情是【{current_mood_text_from_manager}】。
|
||||
你正在和用户【{sender_name_for_prompt}】私聊,你们的关系是:【{relationship_text_for_prompt}】。
|
||||
最近发生的事件是:【{event_description}】
|
||||
最近的对话摘要:
|
||||
---
|
||||
{readable_recent_history}
|
||||
---
|
||||
基于以上所有信息,你认为你现在最主要的情绪是什么?请从以下情绪词中选择一个(必须是列表中的一个):
|
||||
[开心, 害羞, 愤怒, 恐惧, 悲伤, 厌恶, 惊讶, 困惑, 平静]
|
||||
请只输出一个最符合的情绪词。例如: 开心
|
||||
如果难以判断或当前情绪依然合适,请输出: 无变化
|
||||
"""
|
||||
try:
|
||||
logger.debug(f"[私聊][{self.private_name}] 情绪判断Prompt:\n{emotion_prompt}")
|
||||
content, _ = await self.llm.generate_response_async(emotion_prompt)
|
||||
detected_emotion_word = content.strip().replace("\"", "").replace("'", "")
|
||||
logger.debug(f"[私聊][{self.private_name}] 情绪判断LLM原始返回: '{detected_emotion_word}'")
|
||||
|
||||
if detected_emotion_word and detected_emotion_word != "无变化" and detected_emotion_word in self.mood_mng.emotion_map:
|
||||
self.mood_mng.update_mood_from_emotion(detected_emotion_word, intensity=self.EMOTION_UPDATE_INTENSITY)
|
||||
logger.info(f"[私聊][{self.private_name}] 基于事件 '{event_description}',情绪已更新为倾向于 '{detected_emotion_word}'。当前心情: {self.mood_mng.current_mood.text}")
|
||||
elif detected_emotion_word == "无变化":
|
||||
logger.info(f"[私聊][{self.private_name}] 基于事件 '{event_description}',LLM判断情绪无显著变化。")
|
||||
else:
|
||||
logger.warning(f"[私聊][{self.private_name}] LLM返回了未知的情绪词 '{detected_emotion_word}' 或未返回有效词,情绪未主动更新。")
|
||||
except Exception as e:
|
||||
logger.error(f"[私聊][{self.private_name}] 情绪判断LLM调用或处理失败: {e}")
|
||||
|
||||
# 无论LLM判断如何,都更新conversation_info中的情绪文本以供Prompt使用
|
||||
if conversation_info and self.mood_mng: # 确保conversation_info有效
|
||||
conversation_info.current_emotion_text = self.mood_mng.get_prompt()
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
from typing import List, Dict, Any, Optional
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.plugins.models.utils_model import LLMRequest
|
||||
from src.plugins.person_info.person_info import person_info_manager
|
||||
from src.plugins.person_info.relationship_manager import relationship_manager # 主要用其 ensure_float 和 build_relationship_info
|
||||
from src.plugins.utils.chat_message_builder import build_readable_messages
|
||||
|
||||
# 从PFC内部导入必要的类 (根据你的项目结构调整,当前假设与PFC核心文件同级或有正确路径)
|
||||
try:
|
||||
from .observation_info import ObservationInfo
|
||||
from .conversation_info import ConversationInfo
|
||||
from .pfc_utils import get_items_from_json
|
||||
except ImportError: # 如果直接从 plugins/PFC 目录运行,上面的相对导入会失败,尝试绝对导入
|
||||
from observation_info import ObservationInfo
|
||||
from conversation_info import ConversationInfo
|
||||
from pfc_utils import get_items_from_json
|
||||
|
||||
|
||||
from ...config.config import global_config # 导入全局配置 (向上两级到 src/, 再到 config)
|
||||
|
||||
|
||||
logger = get_logger("pfc_relationship_updater")
|
||||
|
||||
class PfcRelationshipUpdater:
|
||||
def __init__(self, private_name: str, bot_name: str):
|
||||
"""
|
||||
初始化关系更新器。
|
||||
|
||||
Args:
|
||||
private_name (str): 当前私聊对象的名称 (用于日志)。
|
||||
bot_name (str): 机器人自己的名称。
|
||||
"""
|
||||
self.private_name = private_name
|
||||
self.bot_name = bot_name
|
||||
self.person_info_mng = person_info_manager
|
||||
self.relationship_mng = relationship_manager # 复用其实例方法
|
||||
|
||||
# LLM 实例 (为关系评估创建一个新的)
|
||||
# 尝试读取 llm_PFC_relationship_eval 配置,如果不存在则回退
|
||||
llm_config_rel_eval = getattr(global_config, 'llm_PFC_relationship_eval', None)
|
||||
if llm_config_rel_eval and isinstance(llm_config_rel_eval, dict):
|
||||
logger.info(f"[私聊][{self.private_name}] 使用 llm_PFC_relationship_eval 配置初始化关系评估LLM。")
|
||||
self.llm = LLMRequest(
|
||||
model=llm_config_rel_eval,
|
||||
temperature=llm_config_rel_eval.get("temp", 0.5), # 判断任务通常用较低温度
|
||||
max_tokens=llm_config_rel_eval.get("max_tokens", 512),
|
||||
request_type="pfc_relationship_evaluation"
|
||||
)
|
||||
else:
|
||||
logger.warning(f"[私聊][{self.private_name}] 未找到 llm_PFC_relationship_eval 配置或配置无效,将回退使用 llm_PFC_action_planner 的配置。")
|
||||
llm_config_action_planner = getattr(global_config, 'llm_PFC_action_planner', None)
|
||||
if llm_config_action_planner and isinstance(llm_config_action_planner, dict):
|
||||
self.llm = LLMRequest(
|
||||
model=llm_config_action_planner, # 使用 action_planner 的模型配置
|
||||
temperature=llm_config_action_planner.get("temp", 0.5), # 但温度可以尝试低一些
|
||||
max_tokens=llm_config_action_planner.get("max_tokens", 512),
|
||||
request_type="pfc_relationship_evaluation_fallback"
|
||||
)
|
||||
else: # 极端情况,连 action_planner 的配置都没有
|
||||
logger.error(f"[私聊][{self.private_name}] 无法找到任何有效的LLM配置用于关系评估!关系更新功能将受限。")
|
||||
self.llm = None # LLM 未初始化
|
||||
|
||||
# 从 global_config 读取参数,若无则使用默认值
|
||||
self.REL_INCREMENTAL_INTERVAL = getattr(global_config, 'pfc_relationship_incremental_interval', 10)
|
||||
self.REL_INCREMENTAL_MSG_COUNT = getattr(global_config, 'pfc_relationship_incremental_msg_count', 10)
|
||||
self.REL_INCREMENTAL_DEFAULT_CHANGE = getattr(global_config, 'pfc_relationship_incremental_default_change', 1.0)
|
||||
self.REL_INCREMENTAL_MAX_CHANGE = getattr(global_config, 'pfc_relationship_incremental_max_change', 5.0)
|
||||
|
||||
self.REL_FINAL_MSG_COUNT = getattr(global_config, 'pfc_relationship_final_msg_count', 30)
|
||||
self.REL_FINAL_DEFAULT_CHANGE = getattr(global_config, 'pfc_relationship_final_default_change', 5.0)
|
||||
self.REL_FINAL_MAX_CHANGE = getattr(global_config, 'pfc_relationship_final_max_change', 50.0)
|
||||
|
||||
async def update_relationship_incremental(
|
||||
self,
|
||||
conversation_info: ConversationInfo,
|
||||
observation_info: ObservationInfo,
|
||||
chat_observer_for_history # ChatObserver 实例
|
||||
) -> None:
|
||||
if not self.llm:
|
||||
logger.error(f"[私聊][{self.private_name}] LLM未初始化,无法进行增量关系更新。")
|
||||
return
|
||||
if not conversation_info or not conversation_info.person_id or not observation_info:
|
||||
logger.debug(f"[私聊][{self.private_name}] 增量关系更新:缺少必要信息。")
|
||||
return
|
||||
|
||||
if not (conversation_info.current_instance_message_count % self.REL_INCREMENTAL_INTERVAL == 0 \
|
||||
and conversation_info.current_instance_message_count > 0):
|
||||
return
|
||||
|
||||
logger.info(f"[私聊][{self.private_name}] 达到增量关系更新阈值 ({conversation_info.current_instance_message_count}条消息),开始评估...")
|
||||
|
||||
messages_for_eval: List[Dict[str, Any]] = []
|
||||
if chat_observer_for_history:
|
||||
messages_for_eval = chat_observer_for_history.get_cached_messages(limit=self.REL_INCREMENTAL_MSG_COUNT)
|
||||
elif observation_info.chat_history:
|
||||
messages_for_eval = observation_info.chat_history[-self.REL_INCREMENTAL_MSG_COUNT:]
|
||||
|
||||
if not messages_for_eval:
|
||||
logger.warning(f"[私聊][{self.private_name}] 增量关系更新:没有足够的消息进行评估。")
|
||||
return
|
||||
|
||||
readable_history_for_llm = await build_readable_messages(
|
||||
messages_for_eval, replace_bot_name=True, merge_messages=False, timestamp_mode="relative"
|
||||
)
|
||||
|
||||
current_relationship_value = await self.person_info_mng.get_value(conversation_info.person_id, "relationship_value")
|
||||
current_relationship_value = self.relationship_mng.ensure_float(current_relationship_value, conversation_info.person_id)
|
||||
|
||||
sender_name_for_prompt = getattr(observation_info, 'sender_name', '对方')
|
||||
if not sender_name_for_prompt: sender_name_for_prompt = '对方'
|
||||
|
||||
relationship_prompt = f"""你是{self.bot_name}。你正在与{sender_name_for_prompt}私聊。
|
||||
你们当前的关系值大约是 {current_relationship_value:.0f} (范围通常在-1000到1000,越高越代表关系越好)。
|
||||
以下是你们最近的对话内容:
|
||||
---
|
||||
{readable_history_for_llm}
|
||||
---
|
||||
请基于以上对话,判断你与{sender_name_for_prompt}的关系值应该如何“谨慎地”调整。
|
||||
请输出一个JSON对象,包含一个 "adjustment" 字段,其值为一个介于 -{self.REL_INCREMENTAL_MAX_CHANGE} 和 +{self.REL_INCREMENTAL_MAX_CHANGE} 之间的整数,代表关系值的变化。
|
||||
例如:{{ "adjustment": 3 }}。如果对话内容不明确或难以判断,请倾向于输出较小的调整值(如0, 1, -1)。"""
|
||||
|
||||
adjustment_val = self.REL_INCREMENTAL_DEFAULT_CHANGE
|
||||
try:
|
||||
logger.debug(f"[私聊][{self.private_name}] 增量关系评估Prompt:\n{relationship_prompt}")
|
||||
content, _ = await self.llm.generate_response_async(relationship_prompt)
|
||||
logger.debug(f"[私聊][{self.private_name}] 增量关系评估LLM原始返回: {content}")
|
||||
|
||||
success, result = get_items_from_json(
|
||||
content, self.private_name, "adjustment",
|
||||
default_values={"adjustment": self.REL_INCREMENTAL_DEFAULT_CHANGE},
|
||||
required_types={"adjustment": (int, float)}
|
||||
)
|
||||
raw_adjustment = result.get("adjustment", self.REL_INCREMENTAL_DEFAULT_CHANGE)
|
||||
if not isinstance(raw_adjustment, (int, float)):
|
||||
adjustment_val = self.REL_INCREMENTAL_DEFAULT_CHANGE
|
||||
else:
|
||||
adjustment_val = float(raw_adjustment)
|
||||
adjustment_val = max(-self.REL_INCREMENTAL_MAX_CHANGE, min(self.REL_INCREMENTAL_MAX_CHANGE, adjustment_val))
|
||||
except Exception as e:
|
||||
logger.error(f"[私聊][{self.private_name}] 增量关系评估LLM调用或解析失败: {e}")
|
||||
|
||||
new_relationship_value = max(-1000.0, min(1000.0, current_relationship_value + adjustment_val))
|
||||
await self.person_info_mng.update_one_field(conversation_info.person_id, "relationship_value", new_relationship_value)
|
||||
logger.info(f"[私聊][{self.private_name}] 增量关系值更新:与【{sender_name_for_prompt}】的关系值从 {current_relationship_value:.2f} 调整了 {adjustment_val:.2f},变为 {new_relationship_value:.2f}")
|
||||
|
||||
if conversation_info.person_id:
|
||||
conversation_info.relationship_text = await self.relationship_mng.build_relationship_info(conversation_info.person_id, is_id=True)
|
||||
|
||||
async def update_relationship_final(
|
||||
self,
|
||||
conversation_info: ConversationInfo,
|
||||
observation_info: ObservationInfo,
|
||||
chat_observer_for_history
|
||||
) -> None:
|
||||
if not self.llm:
|
||||
logger.error(f"[私聊][{self.private_name}] LLM未初始化,无法进行最终关系更新。")
|
||||
return
|
||||
if not conversation_info or not conversation_info.person_id or not observation_info:
|
||||
logger.debug(f"[私聊][{self.private_name}] 最终关系更新:缺少必要信息。")
|
||||
return
|
||||
|
||||
logger.info(f"[私聊][{self.private_name}] 私聊结束,开始最终关系评估...")
|
||||
|
||||
messages_for_eval: List[Dict[str, Any]] = []
|
||||
if chat_observer_for_history:
|
||||
messages_for_eval = chat_observer_for_history.get_cached_messages(limit=self.REL_FINAL_MSG_COUNT)
|
||||
elif observation_info.chat_history:
|
||||
messages_for_eval = observation_info.chat_history[-self.REL_FINAL_MSG_COUNT:]
|
||||
|
||||
if not messages_for_eval:
|
||||
logger.warning(f"[私聊][{self.private_name}] 最终关系更新:没有足够的消息进行评估。")
|
||||
return
|
||||
|
||||
readable_history_for_llm = await build_readable_messages(
|
||||
messages_for_eval, replace_bot_name=True, merge_messages=False, timestamp_mode="relative"
|
||||
)
|
||||
|
||||
current_relationship_value = await self.person_info_mng.get_value(conversation_info.person_id, "relationship_value")
|
||||
current_relationship_value = self.relationship_mng.ensure_float(current_relationship_value, conversation_info.person_id)
|
||||
|
||||
sender_name_for_prompt = getattr(observation_info, 'sender_name', '对方')
|
||||
if not sender_name_for_prompt: sender_name_for_prompt = '对方'
|
||||
|
||||
relationship_prompt = f"""你是{self.bot_name}。你与{sender_name_for_prompt}的私聊刚刚结束。
|
||||
你们当前的关系值大约是 {current_relationship_value:.0f} (范围通常在-1000到1000,越高越好)。
|
||||
以下是你们本次私聊最后部分的对话内容:
|
||||
---
|
||||
{readable_history_for_llm}
|
||||
---
|
||||
请基于以上对话的整体情况,判断你与【{sender_name_for_prompt}】的关系值应该如何进行一次总结性的调整。
|
||||
请输出一个JSON对象,包含一个 "final_adjustment" 字段,其值为一个整数,代表关系值的变化量(例如,可以是 -{self.REL_FINAL_MAX_CHANGE} 到 +{self.REL_FINAL_MAX_CHANGE} 之间的一个值)。
|
||||
请大胆评估,但也要合理。"""
|
||||
|
||||
adjustment_val = self.REL_FINAL_DEFAULT_CHANGE
|
||||
try:
|
||||
logger.debug(f"[私聊][{self.private_name}] 最终关系评估Prompt:\n{relationship_prompt}")
|
||||
content, _ = await self.llm.generate_response_async(relationship_prompt)
|
||||
logger.debug(f"[私聊][{self.private_name}] 最终关系评估LLM原始返回: {content}")
|
||||
|
||||
success, result = get_items_from_json(
|
||||
content, self.private_name, "final_adjustment",
|
||||
default_values={"final_adjustment": self.REL_FINAL_DEFAULT_CHANGE},
|
||||
required_types={"final_adjustment": (int, float)}
|
||||
)
|
||||
raw_adjustment = result.get("final_adjustment", self.REL_FINAL_DEFAULT_CHANGE)
|
||||
if not isinstance(raw_adjustment, (int, float)):
|
||||
adjustment_val = self.REL_FINAL_DEFAULT_CHANGE
|
||||
else:
|
||||
adjustment_val = float(raw_adjustment)
|
||||
adjustment_val = max(-self.REL_FINAL_MAX_CHANGE, min(self.REL_FINAL_MAX_CHANGE, adjustment_val))
|
||||
except Exception as e:
|
||||
logger.error(f"[私聊][{self.private_name}] 最终关系评估LLM调用或解析失败: {e}")
|
||||
|
||||
new_relationship_value = max(-1000.0, min(1000.0, current_relationship_value + adjustment_val))
|
||||
await self.person_info_mng.update_one_field(conversation_info.person_id, "relationship_value", new_relationship_value)
|
||||
logger.info(f"[私聊][{self.private_name}] 最终关系值更新:与【{sender_name_for_prompt}】的关系值从 {current_relationship_value:.2f} 调整了 {adjustment_val:.2f},最终为 {new_relationship_value:.2f}")
|
||||
|
||||
if conversation_info.person_id: # 虽然通常结束了,但更新一下无妨
|
||||
conversation_info.relationship_text = await self.relationship_mng.build_relationship_info(conversation_info.person_id, is_id=True)
|
||||
|
|
@ -23,7 +23,11 @@ logger = get_logger("reply_generator")
|
|||
# Prompt for direct_reply (首次回复)
|
||||
PROMPT_DIRECT_REPLY = """
|
||||
当前时间:{current_time_str}
|
||||
{persona_text}。现在你在参与一场QQ私聊,请根据以下信息生成一条回复:
|
||||
{persona_text}。
|
||||
你正在和{sender_name}在QQ上私聊。
|
||||
你与对方的关系是:{relationship_text}
|
||||
你现在的心情是:{current_emotion_text}
|
||||
请根据以下信息生成一条回复:
|
||||
|
||||
当前对话目标:{goals_str}
|
||||
|
||||
|
|
@ -56,7 +60,11 @@ PROMPT_DIRECT_REPLY = """
|
|||
# Prompt for send_new_message (追问/补充)
|
||||
PROMPT_SEND_NEW_MESSAGE = """
|
||||
当前时间:{current_time_str}
|
||||
{persona_text}。现在你在参与一场QQ私聊,**刚刚你已经发送了一条或多条消息**,现在请根据以下信息再发一条新消息:
|
||||
{persona_text}。
|
||||
你正在和{sender_name}在QQ上私聊,**并且刚刚你已经发送了一条或多条消息**
|
||||
你与对方的关系是:{relationship_text}
|
||||
你现在的心情是:{current_emotion_text}
|
||||
现在请根据以下信息再发一条新消息:
|
||||
|
||||
当前对话目标:{goals_str}
|
||||
|
||||
|
|
@ -88,7 +96,11 @@ PROMPT_SEND_NEW_MESSAGE = """
|
|||
# Prompt for say_goodbye (告别语生成)
|
||||
PROMPT_FAREWELL = """
|
||||
当前时间:{current_time_str}
|
||||
{persona_text}。你在参与一场 QQ 私聊,现在对话似乎已经结束,你决定再发一条最后的消息来圆满结束。
|
||||
{persona_text}。
|
||||
你正在和{sender_name}私聊,在QQ上私聊,现在你们的对话似乎已经结束。
|
||||
你与对方的关系是:{relationship_text}
|
||||
你现在的心情是:{current_emotion_text}
|
||||
现在你决定再发一条最后的消息来圆满结束。
|
||||
|
||||
最近的聊天记录:
|
||||
{chat_history_text}
|
||||
|
|
@ -179,6 +191,14 @@ class ReplyGenerator:
|
|||
chat_history_text += (
|
||||
f"\n--- 以上均为已读消息,未读消息均已处理完毕 ---\n"
|
||||
)
|
||||
|
||||
# 获取 sender_name, relationship_text, current_emotion_text
|
||||
sender_name_str = getattr(observation_info, 'sender_name', '对方')
|
||||
if not sender_name_str: sender_name_str = '对方'
|
||||
|
||||
relationship_text_str = getattr(conversation_info, 'relationship_text', '你们还不熟悉。')
|
||||
current_emotion_text_str = getattr(conversation_info, 'current_emotion_text', '心情平静。')
|
||||
|
||||
# 构建 Persona 文本 (persona_text)
|
||||
persona_text = f"你的名字是{self.name},{self.personality_info}。"
|
||||
retrieval_context = chat_history_text # 使用前面构建好的 chat_history_text
|
||||
|
|
@ -231,7 +251,10 @@ class ReplyGenerator:
|
|||
prompt = prompt_template.format(
|
||||
persona_text=persona_text,
|
||||
chat_history_text=chat_history_text,
|
||||
current_time_str=current_time_value # 添加时间
|
||||
current_time_str=current_time_value, # 添加时间
|
||||
sender_name=sender_name_str,
|
||||
relationship_text=relationship_text_str,
|
||||
current_emotion_text=current_emotion_text_str
|
||||
)
|
||||
|
||||
else:
|
||||
|
|
@ -242,7 +265,10 @@ class ReplyGenerator:
|
|||
retrieved_memory_str=retrieved_memory_str if retrieved_memory_str else "无相关记忆。",
|
||||
retrieved_knowledge_str=retrieved_knowledge_str if retrieved_knowledge_str else "无相关知识。",
|
||||
last_rejection_info=last_rejection_info_str, # <--- 新增传递上次拒绝原因
|
||||
current_time_str=current_time_value # 新增:传入当前时间字符串
|
||||
current_time_str=current_time_value, # 新增:传入当前时间字符串
|
||||
sender_name=sender_name_str,
|
||||
relationship_text=relationship_text_str,
|
||||
current_emotion_text=current_emotion_text_str
|
||||
)
|
||||
except KeyError as e:
|
||||
logger.error(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[inner]
|
||||
version = "1.6.3"
|
||||
version = "1.6.4"
|
||||
|
||||
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
||||
#如果你想要修改配置文件,请在修改后将version的值进行变更
|
||||
|
|
@ -297,6 +297,15 @@ provider = "SILICONFLOW"
|
|||
pri_in = 2
|
||||
pri_out = 8
|
||||
|
||||
# PFC 关系评估LLM
|
||||
[model.llm_PFC_relationship_eval]
|
||||
name = "Pro/deepseek-ai/DeepSeek-V3" # 或者其他你认为适合判断任务的模型
|
||||
provider = "SILICONFLOW"
|
||||
temp = 0.4 # 判断任务建议温度稍低
|
||||
max_tokens = 512 # 根据Prompt长度和期望输出来调整
|
||||
pri_in = 2 # 价格信息(可选)
|
||||
pri_out = 8 # 价格信息(可选)
|
||||
|
||||
#以下模型暂时没有使用!!
|
||||
#以下模型暂时没有使用!!
|
||||
#以下模型暂时没有使用!!
|
||||
|
|
|
|||
Loading…
Reference in New Issue