From bbbf54307831af6ad4fbbac8fbeed2f884128c2d Mon Sep 17 00:00:00 2001 From: Windpicker-owo <3431391539@qq.com> Date: Fri, 26 Sep 2025 13:56:43 +0800 Subject: [PATCH] =?UTF-8?q?refactor(chat):=20=E9=87=8D=E6=9E=84=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=85=B4=E8=B6=A3=E5=BA=A6=E8=AE=A1=E7=AE=97=E4=B8=8E?= =?UTF-8?q?=E5=8A=A8=E4=BD=9C=E8=AE=B0=E5=BD=95=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构聊天系统以使用集中式消息管理API,移除ChatMessageContext类,将兴趣度计算和动作记录功能整合到StreamContext中。 主要变更: - 移除ChatMessageContext类,使用StreamContext统一管理消息上下文 - 在DatabaseMessages模型中添加interest_degree、actions、should_reply字段 - 实现消息管理器API用于更新消息信息和刷新focus_energy - 重构ChatStream的focus_energy计算逻辑,基于StreamContext历史消息 - 在动作管理器中添加动作记录功能,确保动作执行后更新消息状态 BREAKING CHANGE: ChatMessageContext类已被移除,相关功能需使用StreamContext API替代 --- src/chat/message_manager/message_manager.py | 78 ++----- src/chat/message_receive/chat_stream.py | 203 +++++++++--------- src/chat/planner_actions/action_manager.py | 47 +++- src/chat/planner_actions/action_modifier.py | 7 +- src/common/data_models/database_data_model.py | 67 ++++++ .../data_models/message_manager_data_model.py | 102 +++++++++ .../built_in/affinity_flow_chatter/planner.py | 41 +++- 7 files changed, 364 insertions(+), 181 deletions(-) diff --git a/src/chat/message_manager/message_manager.py b/src/chat/message_manager/message_manager.py index 26ff69aba..25053d39a 100644 --- a/src/chat/message_manager/message_manager.py +++ b/src/chat/message_manager/message_manager.py @@ -89,6 +89,18 @@ class MessageManager: logger.debug(f"添加消息到聊天流 {stream_id}: {message.message_id}") + def update_message_and_refresh_energy(self, stream_id: str, message_id: str, interest_degree: float = None, actions: list = None, should_reply: bool = None): + """更新消息信息""" + if stream_id in self.stream_contexts: + context = self.stream_contexts[stream_id] + context.update_message_info(message_id, interest_degree, actions, should_reply) + + def add_action_and_refresh_energy(self, stream_id: str, message_id: str, action: str): + """添加动作到消息""" + if stream_id in self.stream_contexts: + context = self.stream_contexts[stream_id] + context.add_action_to_message(message_id, action) + async def _manager_loop(self): """管理器主循环 - 独立聊天流分发周期版本""" while self.is_running: @@ -296,72 +308,6 @@ class MessageManager: else: logger.debug(f"聊天流 {stream_id} 未触发打断,打断概率: {interruption_probability:.2f}") - def _calculate_dynamic_distribution_interval(self) -> float: - """根据所有活跃聊天流的focus_energy动态计算分发周期""" - if not global_config.chat.dynamic_distribution_enabled: - return self.check_interval # 使用固定间隔 - - if not self.stream_contexts: - return self.check_interval # 默认间隔 - - # 计算活跃流的平均focus_energy - active_streams = [ctx for ctx in self.stream_contexts.values() if ctx.is_active] - if not active_streams: - return self.check_interval - - total_focus_energy = 0.0 - max_focus_energy = 0.0 - stream_count = 0 - - for context in active_streams: - from src.plugin_system.apis.chat_api import get_chat_manager - chat_stream = get_chat_manager().get_stream(context.stream_id) - if chat_stream: - focus_energy = chat_stream.focus_energy - total_focus_energy += focus_energy - max_focus_energy = max(max_focus_energy, focus_energy) - stream_count += 1 - - if stream_count == 0: - return self.check_interval - - avg_focus_energy = total_focus_energy / stream_count - - # 使用配置参数 - base_interval = global_config.chat.dynamic_distribution_base_interval - min_interval = global_config.chat.dynamic_distribution_min_interval - max_interval = global_config.chat.dynamic_distribution_max_interval - jitter_factor = global_config.chat.dynamic_distribution_jitter_factor - - # 根据平均兴趣度调整间隔 - # 高兴趣度 -> 更频繁检查 (间隔更短) - # 低兴趣度 -> 较少检查 (间隔更长) - if avg_focus_energy >= 0.7: - # 高兴趣度:1-5秒 - interval = base_interval * (1.0 - (avg_focus_energy - 0.7) * 2.0) - elif avg_focus_energy >= 0.4: - # 中等兴趣度:5-15秒 - interval = base_interval * (1.0 + (avg_focus_energy - 0.4) * 3.33) - else: - # 低兴趣度:15-30秒 - interval = base_interval * (3.0 + (0.4 - avg_focus_energy) * 5.0) - - # 添加随机扰动避免同步 - import random - jitter = random.uniform(1.0 - jitter_factor, 1.0 + jitter_factor) - final_interval = interval * jitter - - # 限制在合理范围内 - final_interval = max(min_interval, min(max_interval, final_interval)) - - logger.debug( - f"动态分发周期: {final_interval:.2f}s | " - f"平均兴趣度: {avg_focus_energy:.3f} | " - f"活跃流数: {stream_count}" - ) - - return final_interval - def _calculate_stream_distribution_interval(self, context: StreamContext) -> float: """计算单个聊天流的分发周期 - 基于阈值感知的focus_energy""" if not global_config.chat.dynamic_distribution_enabled: diff --git a/src/chat/message_receive/chat_stream.py b/src/chat/message_receive/chat_stream.py index c59a6bbd7..3f05e7d69 100644 --- a/src/chat/message_receive/chat_stream.py +++ b/src/chat/message_receive/chat_stream.py @@ -25,43 +25,6 @@ install(extra_lines=3) logger = get_logger("chat_stream") -class ChatMessageContext: - """聊天消息上下文,存储消息的上下文信息""" - - def __init__(self, message: "MessageRecv"): - self.message = message - - def get_template_name(self) -> Optional[str]: - """获取模板名称""" - if self.message.message_info.template_info and not self.message.message_info.template_info.template_default: - return self.message.message_info.template_info.template_name # type: ignore - return None - - def get_last_message(self) -> "MessageRecv": - """获取最后一条消息""" - return self.message - - def check_types(self, types: list) -> bool: - # sourcery skip: invert-any-all, use-any, use-next - """检查消息类型""" - if not self.message.message_info.format_info.accept_format: # type: ignore - return False - for t in types: - if t not in self.message.message_info.format_info.accept_format: # type: ignore - return False - return True - - def get_priority_mode(self) -> str: - """获取优先级模式""" - return self.message.priority_mode - - def get_priority_info(self) -> Optional[dict]: - """获取优先级信息""" - if hasattr(self.message, "priority_info") and self.message.priority_info: - return self.message.priority_info - return None - - class ChatStream: """聊天流对象,存储一个完整的聊天上下文""" @@ -79,24 +42,23 @@ class ChatStream: self.group_info = group_info self.create_time = data.get("create_time", time.time()) if data else time.time() self.last_active_time = data.get("last_active_time", self.create_time) if data else self.create_time - self.energy_value = data.get("energy_value", 5.0) if data else 5.0 self.sleep_pressure = data.get("sleep_pressure", 0.0) if data else 0.0 self.saved = False - self.context: ChatMessageContext = None # type: ignore # 用于存储该聊天的上下文信息 - # 动态兴趣度系统 - 重构后的focus_energy - self.base_interest_energy = data.get("base_interest_energy", 0.5) if data else 0.5 - self.message_interest_total = data.get("message_interest_total", 0.0) if data else 0.0 - self.message_count = data.get("message_count", 0) if data else 0 - self.action_count = data.get("action_count", 0) if data else 0 - self.reply_count = data.get("reply_count", 0) if data else 0 - self.last_interaction_time = data.get("last_interaction_time", time.time()) if data else time.time() - self.consecutive_no_reply = data.get("consecutive_no_reply", 0) if data else 0 + # 使用StreamContext替代ChatMessageContext + from src.common.data_models.message_manager_data_model import StreamContext + from src.plugin_system.base.component_types import ChatType, ChatMode + self.stream_context: StreamContext = StreamContext( + stream_id=stream_id, + chat_type=ChatType.GROUP if group_info else ChatType.PRIVATE, + chat_mode=ChatMode.NORMAL + ) - # 计算动态focus_energy - self.focus_energy = self._calculate_dynamic_focus_energy() + # 基础参数 + self.base_interest_energy = 0.5 # 默认基础兴趣度 + self._focus_energy = 0.5 # 内部存储的focus_energy值 self.no_reply_consecutive = 0 - self.breaking_accumulated_interest = 0.0 + def to_dict(self) -> dict: """转换为字典格式""" @@ -107,18 +69,13 @@ class ChatStream: "group_info": self.group_info.to_dict() if self.group_info else None, "create_time": self.create_time, "last_active_time": self.last_active_time, - "energy_value": self.energy_value, "sleep_pressure": self.sleep_pressure, "focus_energy": self.focus_energy, - "breaking_accumulated_interest": self.breaking_accumulated_interest, - # 新增动态兴趣度系统字段 + # 基础兴趣度 "base_interest_energy": self.base_interest_energy, - "message_interest_total": self.message_interest_total, - "message_count": self.message_count, - "action_count": self.action_count, - "reply_count": self.reply_count, - "last_interaction_time": self.last_interaction_time, - "consecutive_no_reply": self.consecutive_no_reply, + # 新增stream_context信息 + "stream_context_chat_type": self.stream_context.chat_type.value, + "stream_context_chat_mode": self.stream_context.chat_mode.value, } @classmethod @@ -127,7 +84,7 @@ class ChatStream: user_info = UserInfo.from_dict(data.get("user_info", {})) if data.get("user_info") else None group_info = GroupInfo.from_dict(data.get("group_info", {})) if data.get("group_info") else None - return cls( + instance = cls( stream_id=data["stream_id"], platform=data["platform"], user_info=user_info, # type: ignore @@ -135,6 +92,16 @@ class ChatStream: data=data, ) + # 恢复stream_context信息 + if "stream_context_chat_type" in data: + from src.plugin_system.base.component_types import ChatType, ChatMode + instance.stream_context.chat_type = ChatType(data["stream_context_chat_type"]) + if "stream_context_chat_mode" in data: + from src.plugin_system.base.component_types import ChatType, ChatMode + instance.stream_context.chat_mode = ChatMode(data["stream_context_chat_mode"]) + + return instance + def update_active_time(self): """更新最后活跃时间""" self.last_active_time = time.time() @@ -142,32 +109,91 @@ class ChatStream: def set_context(self, message: "MessageRecv"): """设置聊天消息上下文""" - self.context = ChatMessageContext(message) + # 将MessageRecv转换为DatabaseMessages并设置到stream_context + from src.common.data_models.database_data_model import DatabaseMessages + + # 简化转换,实际可能需要更完整的转换逻辑 + db_message = DatabaseMessages( + message_id=getattr(message, 'message_id', ''), + time=getattr(message, 'time', time.time()), + chat_id=getattr(message, 'chat_id', ''), + user_id=str(getattr(message.message_info, 'user_info', {}).user_id) if hasattr(message, 'message_info') and hasattr(message.message_info, 'user_info') else '', + user_nickname=getattr(message.message_info, 'user_info', {}).user_nickname if hasattr(message, 'message_info') and hasattr(message.message_info, 'user_info') else '', + user_platform=getattr(message.message_info, 'user_info', {}).platform if hasattr(message, 'message_info') and hasattr(message.message_info, 'user_info') else '', + priority_mode=getattr(message, 'priority_mode', None), + priority_info=str(getattr(message, 'priority_info', None)) if hasattr(message, 'priority_info') and message.priority_info else None, + ) + + self.stream_context.set_current_message(db_message) + self.stream_context.priority_mode = getattr(message, 'priority_mode', None) + self.stream_context.priority_info = getattr(message, 'priority_info', None) + + @property + def focus_energy(self) -> float: + """动态计算的聊天流总体兴趣度,访问时自动更新""" + self._focus_energy = self._calculate_dynamic_focus_energy() + return self._focus_energy + + @focus_energy.setter + def focus_energy(self, value: float): + """设置focus_energy值(主要用于初始化或特殊场景)""" + self._focus_energy = max(0.0, min(1.0, value)) def _calculate_dynamic_focus_energy(self) -> float: - """动态计算聊天流的总体兴趣度""" + """动态计算聊天流的总体兴趣度,使用StreamContext历史消息""" try: - # 基础分:平均消息兴趣度 - avg_message_interest = self.message_interest_total / max(self.message_count, 1) + # 从StreamContext获取历史消息计算统计数据 + history_messages = self.stream_context.get_history_messages(limit=global_config.chat.max_context_size) + unread_messages = self.stream_context.get_unread_messages() + all_messages = history_messages + unread_messages - # 动作参与度:动作执行率 - action_rate = self.action_count / max(self.message_count, 1) + # 计算基于历史消息的统计数据 + if all_messages: + # 基础分:平均消息兴趣度 + message_interests = [msg.interest_degree for msg in all_messages if hasattr(msg, 'interest_degree')] + avg_message_interest = sum(message_interests) / len(message_interests) if message_interests else 0.3 - # 回复活跃度:回复率 - reply_rate = self.reply_count / max(self.message_count, 1) + # 动作参与度:有动作的消息比例 + messages_with_actions = [msg for msg in all_messages if hasattr(msg, 'actions') and msg.actions] + action_rate = len(messages_with_actions) / len(all_messages) + + # 回复活跃度:应该回复且已回复的消息比例 + should_reply_messages = [msg for msg in all_messages if hasattr(msg, 'should_reply') and msg.should_reply] + replied_messages = [msg for msg in should_reply_messages if hasattr(msg, 'actions') and 'reply' in (msg.actions or [])] + reply_rate = len(replied_messages) / len(should_reply_messages) if should_reply_messages else 0.0 + + # 获取最后交互时间 + if all_messages: + self.last_interaction_time = max(msg.time for msg in all_messages) + + # 连续无回复计算:从最近的未回复消息计数 + consecutive_no_reply = 0 + for msg in reversed(all_messages): + if hasattr(msg, 'should_reply') and msg.should_reply: + if not (hasattr(msg, 'actions') and 'reply' in (msg.actions or [])): + consecutive_no_reply += 1 + else: + break + else: + # 没有历史消息时的默认值 + avg_message_interest = 0.3 + action_rate = 0.0 + reply_rate = 0.0 + consecutive_no_reply = 0 + self.last_interaction_time = time.time() # 获取用户关系分(对于私聊,群聊无效) relationship_factor = self._get_user_relationship_score() # 时间衰减因子:最近活跃度 current_time = time.time() - if not self.last_interaction_time: + if not hasattr(self, 'last_interaction_time') or not self.last_interaction_time: self.last_interaction_time = current_time time_since_interaction = current_time - self.last_interaction_time time_decay = max(0.3, 1.0 - min(time_since_interaction / (7 * 24 * 3600), 0.7)) # 7天衰减 # 连续无回复惩罚 - no_reply_penalty = max(0.1, 1.0 - self.consecutive_no_reply * 0.1) + no_reply_penalty = max(0.1, 1.0 - consecutive_no_reply * 0.1) # 获取AFC系统阈值,添加None值检查 reply_threshold = getattr(global_config.affinity_flow, 'reply_action_interest_threshold', 0.4) @@ -250,45 +276,8 @@ class ChatStream: # 默认基础分 return 0.3 - def add_message_interest(self, interest_score: float): - """添加消息兴趣值并更新focus_energy""" - self.message_interest_total += interest_score - self.message_count += 1 - self.last_interaction_time = time.time() - self.focus_energy = self._calculate_dynamic_focus_energy() - def update_focus_energy(self): - """手动触发更新focus_energy""" - self.focus_energy = self._calculate_dynamic_focus_energy() - def record_action(self, is_reply: bool = False): - """记录动作执行""" - self.action_count += 1 - if is_reply: - self.reply_count += 1 - self.consecutive_no_reply = max(0, self.consecutive_no_reply - 1) - self.last_interaction_time = time.time() - self.focus_energy = self._calculate_dynamic_focus_energy() - - def record_no_reply(self): - """记录无回复动作""" - self.consecutive_no_reply += 1 - self.last_interaction_time = time.time() - self.focus_energy = self._calculate_dynamic_focus_energy() - - def get_adjusted_focus_energy(self) -> float: - """获取应用了afc调整的focus_energy""" - try: - from src.chat.message_manager.message_manager import message_manager - if self.stream_id in message_manager.stream_contexts: - context = message_manager.stream_contexts[self.stream_id] - afc_adjustment = context.get_afc_threshold_adjustment() - # 对动态计算的focus_energy应用AFC调整 - adjusted_energy = max(0.0, self.focus_energy - afc_adjustment) - return adjusted_energy - except Exception: - pass - return self.focus_energy class ChatManager: diff --git a/src/chat/planner_actions/action_manager.py b/src/chat/planner_actions/action_manager.py index f60146287..bf7174a52 100644 --- a/src/chat/planner_actions/action_manager.py +++ b/src/chat/planner_actions/action_manager.py @@ -1,7 +1,6 @@ import asyncio import traceback import time -import random from typing import Dict, Optional, Type, Any, Tuple @@ -210,8 +209,10 @@ class ChatterActionManager: target_message, ) - # 如果动作执行成功且不是no_action,重置打断计数 + # 记录执行的动作到目标消息 if success: + await self._record_action_to_message(chat_stream, action_name, target_message, action_data) + # 重置打断计数 await self._reset_interruption_count_after_action(chat_stream.stream_id) return { @@ -252,6 +253,9 @@ class ChatterActionManager: [], # actions ) + # 记录回复动作到目标消息 + await self._record_action_to_message(chat_stream, "reply", target_message, action_data) + # 回复成功,重置打断计数 await self._reset_interruption_count_after_action(chat_stream.stream_id) @@ -268,6 +272,45 @@ class ChatterActionManager: "error": str(e), } + async def _record_action_to_message(self, chat_stream, action_name, target_message, action_data): + """ + 记录执行的动作到目标消息中 + + Args: + chat_stream: ChatStream实例 + action_name: 动作名称 + target_message: 目标消息 + action_data: 动作数据 + """ + try: + from src.chat.message_manager.message_manager import message_manager + + # 获取目标消息ID + target_message_id = None + if target_message and isinstance(target_message, dict): + target_message_id = target_message.get("message_id") + elif action_data and isinstance(action_data, dict): + target_message_id = action_data.get("target_message_id") + + if not target_message_id: + logger.debug(f"无法获取目标消息ID,动作: {action_name}") + return + + # 通过message_manager更新消息的动作记录并刷新focus_energy + if chat_stream.stream_id in message_manager.stream_contexts: + message_manager.add_action_and_refresh_energy( + stream_id=chat_stream.stream_id, + message_id=target_message_id, + action=action_name + ) + logger.debug(f"已记录动作 {action_name} 到消息 {target_message_id} 并更新focus_energy") + else: + logger.debug(f"未找到stream_context: {chat_stream.stream_id}") + + except Exception as e: + logger.error(f"记录动作到消息失败: {e}") + # 不抛出异常,避免影响主要功能 + async def _reset_interruption_count_after_action(self, stream_id: str): """在动作执行成功后重置打断计数""" from src.chat.message_manager.message_manager import message_manager diff --git a/src/chat/planner_actions/action_modifier.py b/src/chat/planner_actions/action_modifier.py index 62d5d6dfd..6d9048ca5 100644 --- a/src/chat/planner_actions/action_modifier.py +++ b/src/chat/planner_actions/action_modifier.py @@ -7,7 +7,8 @@ from typing import List, Any, Dict, TYPE_CHECKING, Tuple from src.common.logger import get_logger from src.config.config import global_config, model_config from src.llm_models.utils_model import LLMRequest -from src.chat.message_receive.chat_stream import get_chat_manager, ChatMessageContext +from src.chat.message_receive.chat_stream import get_chat_manager +from src.common.data_models.message_manager_data_model import StreamContext from src.chat.planner_actions.action_manager import ChatterActionManager from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages from src.plugin_system.base.component_types import ActionInfo, ActionActivationType @@ -124,7 +125,7 @@ class ActionModifier: logger.debug(f"{self.log_prefix}阶段一移除动作: {disabled_action_name},原因: 用户自行禁用") # === 第二阶段:检查动作的关联类型 === - chat_context = self.chat_stream.context + chat_context = self.chat_stream.stream_context current_actions_s2 = self.action_manager.get_using_actions() type_mismatched_actions = self._check_action_associated_types(current_actions_s2, chat_context) @@ -166,7 +167,7 @@ class ActionModifier: logger.info(f"{self.log_prefix} 当前可用动作: {available_actions_text}||移除: {removals_summary}") - def _check_action_associated_types(self, all_actions: Dict[str, ActionInfo], chat_context: ChatMessageContext): + def _check_action_associated_types(self, all_actions: Dict[str, ActionInfo], chat_context: StreamContext): type_mismatched_actions: List[Tuple[str, str]] = [] for action_name, action_info in all_actions.items(): if action_info.associated_types and not chat_context.check_types(action_info.associated_types): diff --git a/src/common/data_models/database_data_model.py b/src/common/data_models/database_data_model.py index 4d2e00e3b..11468a814 100644 --- a/src/common/data_models/database_data_model.py +++ b/src/common/data_models/database_data_model.py @@ -95,6 +95,10 @@ class DatabaseMessages(BaseDataModel): chat_info_platform: str = "", chat_info_create_time: float = 0.0, chat_info_last_active_time: float = 0.0, + # 新增字段 + interest_degree: float = 0.0, + actions: Optional[list] = None, + should_reply: bool = False, **kwargs: Any, ): self.message_id = message_id @@ -103,6 +107,11 @@ class DatabaseMessages(BaseDataModel): self.reply_to = reply_to self.interest_value = interest_value + # 新增字段 + self.interest_degree = interest_degree + self.actions = actions + self.should_reply = should_reply + self.key_words = key_words self.key_words_lite = key_words_lite self.is_mentioned = is_mentioned @@ -191,6 +200,10 @@ class DatabaseMessages(BaseDataModel): "is_notify": self.is_notify, "selected_expressions": self.selected_expressions, "is_read": self.is_read, + # 新增字段 + "interest_degree": self.interest_degree, + "actions": self.actions, + "should_reply": self.should_reply, "user_id": self.user_info.user_id, "user_nickname": self.user_info.user_nickname, "user_cardname": self.user_info.user_cardname, @@ -208,6 +221,60 @@ class DatabaseMessages(BaseDataModel): "chat_info_user_cardname": self.chat_info.user_info.user_cardname, } + def update_message_info(self, interest_degree: float = None, actions: list = None, should_reply: bool = None): + """ + 更新消息信息 + + Args: + interest_degree: 兴趣度值 + actions: 执行的动作列表 + should_reply: 是否应该回复 + """ + if interest_degree is not None: + self.interest_degree = interest_degree + if actions is not None: + self.actions = actions + if should_reply is not None: + self.should_reply = should_reply + + def add_action(self, action: str): + """ + 添加执行的动作到消息中 + + Args: + action: 要添加的动作名称 + """ + if self.actions is None: + self.actions = [] + if action not in self.actions: # 避免重复添加 + self.actions.append(action) + + def get_actions(self) -> list: + """ + 获取执行的动作列表 + + Returns: + 动作列表,如果没有动作则返回空列表 + """ + return self.actions or [] + + def get_message_summary(self) -> Dict[str, Any]: + """ + 获取消息摘要信息 + + Returns: + 包含关键字段的消息摘要 + """ + return { + "message_id": self.message_id, + "time": self.time, + "interest_degree": self.interest_degree, + "actions": self.actions, + "should_reply": self.should_reply, + "user_nickname": self.user_info.user_nickname, + "display_message": self.display_message, + } + @dataclass(init=False) class DatabaseActionRecords(BaseDataModel): diff --git a/src/common/data_models/message_manager_data_model.py b/src/common/data_models/message_manager_data_model.py index 70da3591c..9bc4002b5 100644 --- a/src/common/data_models/message_manager_data_model.py +++ b/src/common/data_models/message_manager_data_model.py @@ -47,6 +47,11 @@ class StreamContext(BaseDataModel): next_check_time: float = field(default_factory=time.time) # 下次检查时间 distribution_interval: float = 5.0 # 当前分发周期(秒) + # 新增字段以替代ChatMessageContext功能 + current_message: Optional["DatabaseMessages"] = None + priority_mode: Optional[str] = None + priority_info: Optional[dict] = None + def add_message(self, message: "DatabaseMessages"): """添加消息到上下文""" message.is_read = False @@ -55,6 +60,48 @@ class StreamContext(BaseDataModel): # 自动检测和更新chat type self._detect_chat_type(message) + def update_message_info(self, message_id: str, interest_degree: float = None, actions: list = None, should_reply: bool = None): + """ + 更新消息信息 + + Args: + message_id: 消息ID + interest_degree: 兴趣度值 + actions: 执行的动作列表 + should_reply: 是否应该回复 + """ + # 在未读消息中查找并更新 + for message in self.unread_messages: + if message.message_id == message_id: + message.update_message_info(interest_degree, actions, should_reply) + break + + # 在历史消息中查找并更新 + for message in self.history_messages: + if message.message_id == message_id: + message.update_message_info(interest_degree, actions, should_reply) + break + + def add_action_to_message(self, message_id: str, action: str): + """ + 向指定消息添加执行的动作 + + Args: + message_id: 消息ID + action: 要添加的动作名称 + """ + # 在未读消息中查找并更新 + for message in self.unread_messages: + if message.message_id == message_id: + message.add_action(action) + break + + # 在历史消息中查找并更新 + for message in self.history_messages: + if message.message_id == message_id: + message.add_action(action) + break + def _detect_chat_type(self, message: "DatabaseMessages"): """根据消息内容自动检测聊天类型""" # 只有在第一次添加消息时才检测聊天类型,避免后续消息改变类型 @@ -150,6 +197,61 @@ class StreamContext(BaseDataModel): """获取当前的afc阈值调整量""" return self.afc_threshold_adjustment + def set_current_message(self, message: "DatabaseMessages"): + """设置当前消息""" + self.current_message = message + + def get_template_name(self) -> Optional[str]: + """获取模板名称""" + if self.current_message and hasattr(self.current_message, 'additional_config') and self.current_message.additional_config: + try: + import json + config = json.loads(self.current_message.additional_config) + if config.get('template_info') and not config.get('template_default', True): + return config.get('template_name') + except (json.JSONDecodeError, AttributeError): + pass + return None + + def get_last_message(self) -> Optional["DatabaseMessages"]: + """获取最后一条消息""" + if self.current_message: + return self.current_message + if self.unread_messages: + return self.unread_messages[-1] + if self.history_messages: + return self.history_messages[-1] + return None + + def check_types(self, types: list) -> bool: + """检查消息类型""" + if not self.current_message: + return False + + # 检查消息是否支持指定的类型 + # 这里简化处理,实际应该根据消息的格式信息检查 + if hasattr(self.current_message, 'additional_config') and self.current_message.additional_config: + try: + import json + config = json.loads(self.current_message.additional_config) + if 'format_info' in config and 'accept_format' in config['format_info']: + accept_format = config['format_info']['accept_format'] + for t in types: + if t not in accept_format: + return False + return True + except (json.JSONDecodeError, AttributeError): + pass + return False + + def get_priority_mode(self) -> Optional[str]: + """获取优先级模式""" + return self.priority_mode + + def get_priority_info(self) -> Optional[dict]: + """获取优先级信息""" + return self.priority_info + @dataclass class MessageManagerStats(BaseDataModel): diff --git a/src/plugins/built_in/affinity_flow_chatter/planner.py b/src/plugins/built_in/affinity_flow_chatter/planner.py index b3b86210c..36d3d300f 100644 --- a/src/plugins/built_in/affinity_flow_chatter/planner.py +++ b/src/plugins/built_in/affinity_flow_chatter/planner.py @@ -128,7 +128,6 @@ class ChatterActionPlanner: # 更新ChatStream的兴趣度数据 from src.plugin_system.apis.chat_api import get_chat_manager chat_stream = get_chat_manager().get_stream(self.chat_id) - chat_stream.add_message_interest(score) logger.debug(f"已更新聊天 {self.chat_id} 的ChatStream兴趣度,分数: {score:.3f}") # 更新情绪状态和ChatStream兴趣度数据 @@ -137,6 +136,39 @@ class ChatterActionPlanner: await chat_mood.update_mood_by_message(latest_message, score) logger.debug(f"已更新聊天 {self.chat_id} 的情绪状态,兴趣度: {score:.3f}") + # 为所有未读消息记录兴趣度信息 + for message in unread_messages: + # 查找对应的兴趣度评分 + message_score = next((s for s in interest_scores if s.message_id == message.message_id), None) + if message_score: + message.interest_degree = message_score.total_score + message.should_reply = self.interest_scoring.should_reply(message_score, message)[0] + logger.debug(f"已记录消息 {message.message_id} - 兴趣度: {message_score.total_score:.3f}, 应回复: {message.should_reply}") + + # 更新StreamContext中的消息信息并刷新focus_energy + if context: + from src.chat.message_manager.message_manager import message_manager + message_manager.update_message_and_refresh_energy( + stream_id=self.chat_id, + message_id=message.message_id, + interest_degree=message_score.total_score, + should_reply=message.should_reply + ) + else: + # 如果没有找到评分,设置默认值 + message.interest_degree = 0.0 + message.should_reply = False + + # 更新StreamContext中的消息信息并刷新focus_energy + if context: + from src.chat.message_manager.message_manager import message_manager + message_manager.update_message_and_refresh_energy( + stream_id=self.chat_id, + message_id=message.message_id, + interest_degree=0.0, + should_reply=False + ) + # base_threshold = self.interest_scoring.reply_threshold # 检查兴趣度是否达到非回复动作阈值 non_reply_action_interest_threshold = global_config.affinity_flow.non_reply_action_interest_threshold @@ -169,10 +201,13 @@ class ChatterActionPlanner: # 5. 使用 PlanExecutor 执行 Plan execution_result = await self.executor.execute(filtered_plan) - # 6. 根据执行结果更新统计信息 + # 6. 动作记录现在由ChatterActionManager统一处理 + # 动作记录逻辑已移至ChatterActionManager.execute_action方法中 + + # 7. 根据执行结果更新统计信息 self._update_stats_from_execution_result(execution_result) - # 7. 检查关系更新 + # 8. 检查关系更新 await self.relationship_tracker.check_and_update_relationships() # 8. 返回结果