From c92581afe76e6d84ec6c9d36c1ac3f0e27cecbc5 Mon Sep 17 00:00:00 2001 From: xiaoxi68 <3520824673@qq.com> Date: Sat, 7 Feb 2026 19:48:11 +0800 Subject: [PATCH] =?UTF-8?q?brain=5Fchat=E6=97=A0=E6=96=B0=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E9=99=90=E5=AE=9A=E5=8A=A8=E4=BD=9C:reply/wait,comple?= =?UTF-8?q?te=5Ftalk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/brain_chat/brain_chat.py | 14 ++++---- src/chat/brain_chat/brain_planner.py | 52 ++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/chat/brain_chat/brain_chat.py b/src/chat/brain_chat/brain_chat.py index cc8d7ce2..c5353eea 100644 --- a/src/chat/brain_chat/brain_chat.py +++ b/src/chat/brain_chat/brain_chat.py @@ -104,7 +104,7 @@ class BrainChatting: # side-effect 动作幂等缓存,避免同一触发消息在短时间内重复执行。 self._recent_side_effect_actions: Dict[str, float] = {} - self._side_effect_dedupe_window_sec = 100.0 + self._side_effect_dedupe_window_sec = 10.0 async def start(self): """检查是否需要启动主循环,如果未激活则启动。""" @@ -213,13 +213,11 @@ class BrainChatting: filter_intercept_message_level=1, ) - # 没有新增用户消息时,直接等待下一轮,避免对旧上下文反复规划。 - if not recent_messages_list: - await asyncio.sleep(0.2) - return True - - self.last_read_time = time.time() - self._new_message_event.set() # 触发新消息事件,打断正在进行的 wait + # 仅在有新消息时更新读取时间并触发事件。 + # 无新消息时仍允许继续思考,具体动作由 Planner 限制为 reply/wait。 + if recent_messages_list: + self.last_read_time = time.time() + self._new_message_event.set() # 触发新消息事件,打断正在进行的 wait should_continue = await self._observe(recent_messages_list=recent_messages_list) diff --git a/src/chat/brain_chat/brain_planner.py b/src/chat/brain_chat/brain_planner.py index 070a1f40..bdc594e4 100644 --- a/src/chat/brain_chat/brain_planner.py +++ b/src/chat/brain_chat/brain_planner.py @@ -330,14 +330,16 @@ class BrainPlanner: for msg in message_list_before_now ) if not has_new_user_message: - non_side_effect_actions = {"reply", "wait", "wait_time", "listening", "complete_talk", "no_reply"} - side_effect_actions = [a.action_type for a in actions if a.action_type not in non_side_effect_actions] - if side_effect_actions: + actions, dropped_actions = self._restrict_actions_without_new_user_message( + actions=actions, + available_actions=available_actions, + message_id_list=message_id_list, + ) + if dropped_actions: logger.info( - f"{self.log_prefix}检测到无新用户消息,跳过副作用动作: {' '.join(side_effect_actions)}" + f"{self.log_prefix}检测到无新用户消息,仅保留 reply/wait/complete_talk,移除动作: {' '.join(dropped_actions)}" ) - actions = self._create_complete_talk("没有新的用户消息,跳过副作用动作", available_actions) - reasoning = f"{reasoning};检测到无新用户消息,已跳过副作用动作" + reasoning = f"{reasoning};检测到无新用户消息,仅保留 reply/wait/complete_talk" # 记录和展示计划日志 logger.info( @@ -611,6 +613,44 @@ class BrainPlanner: ) ] + def _restrict_actions_without_new_user_message( + self, + actions: List[ActionPlannerInfo], + available_actions: Dict[str, ActionInfo], + message_id_list: List[Tuple[str, "DatabaseMessages"]], + ) -> Tuple[List[ActionPlannerInfo], List[str]]: + """无新用户消息时,仅保留 reply/wait/complete_talk。""" + allowed_actions: List[ActionPlannerInfo] = [] + dropped_actions: List[str] = [] + + for action in actions: + if action.action_type in {"reply", "complete_talk"}: + allowed_actions.append(action) + continue + + if action.action_type in {"wait", "listening", "wait_time"}: + action.action_type = "wait" + action.action_data = action.action_data or {} + action.action_data.setdefault("wait_seconds", 5) + allowed_actions.append(action) + continue + + dropped_actions.append(action.action_type) + + if allowed_actions: + return allowed_actions, dropped_actions + + target_message = message_id_list[-1][1] if message_id_list else None + fallback_wait = ActionPlannerInfo( + action_type="wait", + reasoning="没有新的用户消息,进入等待", + action_data={"wait_seconds": 5}, + action_message=target_message, + available_actions=available_actions, + ) + + return [fallback_wait], dropped_actions + def add_plan_log(self, reasoning: str, actions: List[ActionPlannerInfo]): """添加计划日志""" self.plan_log.append((reasoning, time.time(), actions))