diff --git a/src/chat/focus_chat/heartFC_chat.py b/src/chat/focus_chat/heartFC_chat.py index 2fef2a44..3fc15bc7 100644 --- a/src/chat/focus_chat/heartFC_chat.py +++ b/src/chat/focus_chat/heartFC_chat.py @@ -383,8 +383,21 @@ class HeartFChatting: task_to_name_map = {} processor_time_costs = {} # 新增: 记录每个处理器耗时 + # 获取聊天类型 + chat_stream = await asyncio.to_thread(chat_manager.get_stream, self.stream_id) + is_group_chat = chat_stream.group_info is not None + + # 根据聊天类型选择处理器 + selected_processors = [] for processor in self.processors: processor_name = processor.__class__.log_prefix + # 私聊时跳过某些处理器 + if not is_group_chat and processor_name in ["MindProcessor", "ToolProcessor"]: + continue + selected_processors.append(processor) + + for processor in selected_processors: + processor_name = processor.__class__.log_prefix async def run_with_timeout(proc=processor): return await asyncio.wait_for( @@ -465,9 +478,14 @@ class HeartFChatting: self.all_observations = observations + # 获取聊天类型 + chat_stream = await asyncio.to_thread(chat_manager.get_stream, self.stream_id) + is_group_chat = chat_stream.group_info is not None + with Timer("调整动作", cycle_timers): # 处理特殊的观察 - await self.action_modifier.modify_actions(observations=observations) + if is_group_chat: # 只在群聊中调整动作 + await self.action_modifier.modify_actions(observations=observations) await self.action_observation.observe() observations.append(self.action_observation) @@ -497,59 +515,41 @@ class HeartFChatting: } with Timer("规划器", cycle_timers): - plan_result = await self.action_planner.plan(all_plan_info, running_memorys) + # 私聊时使用简单规划 + if not is_group_chat: + plan_result = await self.action_planner.plan_simple(all_plan_info, running_memorys) + else: + plan_result = await self.action_planner.plan(all_plan_info, running_memorys) - loop_plan_info = { - "action_result": plan_result.get("action_result", {}), - "current_mind": plan_result.get("current_mind", ""), - "observed_messages": plan_result.get("observed_messages", ""), - } + loop_plan_info = { + "action_result": plan_result, + } with Timer("执行动作", cycle_timers): - action_type, action_data, reasoning = ( - plan_result.get("action_result", {}).get("action_type", "error"), - plan_result.get("action_result", {}).get("action_data", {}), - plan_result.get("action_result", {}).get("reasoning", "未提供理由"), + action_taken, action_command, action_reason = await self._handle_action( + action=plan_result["action_type"], + reasoning=plan_result["reasoning"], + action_data=plan_result["action_data"], + cycle_timers=cycle_timers, + thinking_id=thinking_id, ) - if action_type == "reply": - action_str = "回复" - elif action_type == "no_reply": - action_str = "不回复" - else: - action_str = action_type + loop_action_info = { + "action_taken": action_taken, + "command": action_command, + "reason": action_reason, + } - logger.debug(f"{self.log_prefix} 麦麦想要:'{action_str}', 原因'{reasoning}'") - - success, reply_text, command = await self._handle_action( - action_type, reasoning, action_data, cycle_timers, thinking_id - ) - - loop_action_info = { - "action_taken": success, - "reply_text": reply_text, - "command": command, - "taken_time": time.time(), - } - - loop_info = { + return { "loop_observation_info": loop_observation_info, "loop_processor_info": loop_processor_info, "loop_plan_info": loop_plan_info, "loop_action_info": loop_action_info, } - - return loop_info - except Exception as e: - logger.error(f"{self.log_prefix} FOCUS聊天处理失败: {e}") - logger.error(traceback.format_exc()) - return { - "loop_observation_info": {}, - "loop_processor_info": {}, - "loop_plan_info": {}, - "loop_action_info": {"action_taken": False, "reply_text": "", "command": ""}, - } + logger.error(f"{self.log_prefix} 循环处理出错: {e}") + traceback.print_exc() + raise async def _handle_action( self, diff --git a/src/chat/focus_chat/planners/planner.py b/src/chat/focus_chat/planners/planner.py index 298da311..ebaf6ae5 100644 --- a/src/chat/focus_chat/planners/planner.py +++ b/src/chat/focus_chat/planners/planner.py @@ -16,6 +16,8 @@ from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.individuality.individuality import individuality from src.chat.focus_chat.planners.action_manager import ActionManager from json_repair import repair_json +from src.chat.focus_chat.info.chat_info import ChattingInfo +from src.chat.focus_chat.info.workingmemory_info import WorkingMemoryInfo logger = get_logger("planner") @@ -85,6 +87,61 @@ class ActionPlanner: self.action_manager = action_manager + async def plan_simple(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]]) -> Dict[str, Any]: + """ + 为私聊提供的简单规划方法。 + 主要关注ChattingInfo和WorkingMemory,不考虑复杂的心智状态和工具使用。 + + Args: + all_plan_info: 所有处理器提供的信息 + running_memorys: 当前激活的记忆 + + Returns: + Dict[str, Any]: 包含action_type, action_data和reasoning的字典 + """ + # 提取聊天信息 + chatting_info = None + working_memory_info = None + for info in all_plan_info: + if isinstance(info, ChattingInfo): + chatting_info = info + elif isinstance(info, WorkingMemoryInfo): + working_memory_info = info + + if not chatting_info: + return { + "action_type": "no_reply", + "action_data": {}, + "reasoning": "没有检测到新的聊天信息", + } + + # 检查是否有新消息需要回复 + if not chatting_info.new_messages: + return { + "action_type": "no_reply", + "action_data": {}, + "reasoning": "没有新消息需要回复", + } + + # 获取最新消息 + latest_message = chatting_info.new_messages[-1] + + # 检查工作记忆中是否有相关上下文 + context = "" + if working_memory_info and working_memory_info.related_memory: + context = working_memory_info.related_memory + + # 构建回复动作 + return { + "action_type": "reply", + "action_data": { + "message": latest_message, + "context": context, + "style": "direct", # 私聊使用直接回复风格 + }, + "reasoning": "收到新的私聊消息,直接回复", + } + async def plan(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]]) -> Dict[str, Any]: """ 规划器 (Planner): 使用LLM根据上下文决定做出什么动作。 diff --git a/src/chat/heart_flow/subheartflow_manager.py b/src/chat/heart_flow/subheartflow_manager.py index bad4393c..f24031ac 100644 --- a/src/chat/heart_flow/subheartflow_manager.py +++ b/src/chat/heart_flow/subheartflow_manager.py @@ -219,7 +219,7 @@ class SubHeartflowManager: """ 接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 NORMAL。 通常在连续多次 "no_reply" 后被调用。 - 对于私聊和群聊,都转换为 NORMAL。 + 对于群聊转换为 NORMAL,对于私聊转换为 ABSENT。 Args: subflow_id: 需要转换状态的子心流 ID。 @@ -234,8 +234,9 @@ class SubHeartflowManager: current_state = subflow.chat_state.chat_status if current_state == ChatState.FOCUSED: - target_state = ChatState.NORMAL - log_reason = "转为NORMAL" + # 根据聊天类型决定目标状态 + target_state = ChatState.NORMAL if subflow.is_group_chat else ChatState.ABSENT + log_reason = "转为NORMAL" if subflow.is_group_chat else "转为ABSENT(私聊)" logger.info( f"[状态转换请求] 接收到请求,将 {stream_name} (当前: {current_state.value}) 尝试转换为 {target_state.value} ({log_reason})"