From 3a7a22cb16f9f0b925f7ff6e68326ef756c348fd Mon Sep 17 00:00:00 2001 From: A0000Xz <122650088+A0000Xz@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:28:36 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E8=AE=A9no=5Freply=E5=9C=A8=E7=A7=81?= =?UTF-8?q?=E8=81=8A=E7=8E=AF=E5=A2=83=E4=B8=8B=E4=B8=8D=E9=80=80=E5=87=BA?= =?UTF-8?q?=E4=B8=93=E6=B3=A8=EF=BC=8C=E6=9B=B4=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=B8=BAdebug=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BA=9B=E8=AE=B8prompt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/built_in/core_actions/no_reply.py | 131 ++++++++++-------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/src/plugins/built_in/core_actions/no_reply.py b/src/plugins/built_in/core_actions/no_reply.py index 3e98ed32e..0ce0adbd6 100644 --- a/src/plugins/built_in/core_actions/no_reply.py +++ b/src/plugins/built_in/core_actions/no_reply.py @@ -107,7 +107,7 @@ class NoReplyAction(BaseAction): current_time = time.time() elapsed_time = current_time - start_time - if global_config.chat.chat_mode == "auto": + if global_config.chat.chat_mode == "auto" and self.is_group: # 检查是否超时 if elapsed_time >= self._max_timeout: logger.info(f"{self.log_prefix} 达到最大等待时间{self._max_timeout}秒,退出专注模式") @@ -220,73 +220,81 @@ class NoReplyAction(BaseAction): frequency_block = "" should_skip_llm_judge = False # 是否跳过LLM判断 - try: - # 获取过去10分钟的所有消息 - past_10min_time = current_time - 600 # 10分钟前 - all_messages_10min = message_api.get_messages_by_time_in_chat( - chat_id=self.chat_id, - start_time=past_10min_time, - end_time=current_time, - ) + # 【新增】如果是私聊环境,跳过疲劳度检查 + if not self.is_group: + frequency_block = "你正在和别人私聊,你不会疲惫,正常聊天即可。" + should_skip_llm_judge = False + logger.debug(f"{self.log_prefix} 私聊环境,跳过疲劳度检查") - # 手动过滤bot自己的消息 - bot_message_count = 0 - if all_messages_10min: - user_id = global_config.bot.qq_account + else: - for message in all_messages_10min: - # 检查消息发送者是否是bot - sender_id = message.get("user_id", "") + try: + # 获取过去10分钟的所有消息 + past_10min_time = current_time - 600 # 10分钟前 + all_messages_10min = message_api.get_messages_by_time_in_chat( + chat_id=self.chat_id, + start_time=past_10min_time, + end_time=current_time, + ) - if sender_id == user_id: - bot_message_count += 1 + # 手动过滤bot自己的消息 + bot_message_count = 0 + if all_messages_10min: + user_id = global_config.bot.qq_account - talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10 + for message in all_messages_10min: + # 检查消息发送者是否是bot + sender_id = message.get("user_id", "") - if bot_message_count > talk_frequency_threshold: - over_count = bot_message_count - talk_frequency_threshold + if sender_id == user_id: + bot_message_count += 1 - # 根据超过的数量设置不同的提示词和跳过概率 - skip_probability = 0 - if over_count <= 3: - frequency_block = "你感觉稍微有些累,回复的有点多了。\n" - elif over_count <= 5: - frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" - elif over_count <= 8: - frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n" - skip_probability = self._skip_probability - else: - frequency_block = "你感觉非常累,想要安静一会儿。\n" - skip_probability = 1 + talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10 + + if bot_message_count > talk_frequency_threshold: + over_count = bot_message_count - talk_frequency_threshold + + # 根据超过的数量设置不同的提示词和跳过概率 + skip_probability = 0 + if over_count <= 3: + frequency_block = "你感觉稍微有些累,回复的有点多了。\n" + elif over_count <= 5: + frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" + elif over_count <= 8: + frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n" + skip_probability = self._skip_probability + else: + frequency_block = "你感觉非常累,想要安静一会儿。\n" + skip_probability = 1 + + # 根据配置和概率决定是否跳过LLM判断 + if self._skip_judge_when_tired and random.random() < skip_probability: + should_skip_llm_judge = True + logger.info( + f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" + ) - # 根据配置和概率决定是否跳过LLM判断 - if self._skip_judge_when_tired and random.random() < skip_probability: - should_skip_llm_judge = True logger.info( - f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" + f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示" + ) + else: + # 回复次数少时的正向提示 + under_count = talk_frequency_threshold - bot_message_count + + if under_count >= talk_frequency_threshold * 0.8: # 回复很少(少于20%) + frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n" + elif under_count >= talk_frequency_threshold * 0.5: # 回复较少(少于50%) + frequency_block = "你感觉状态不错。\n" + else: # 刚好达到阈值 + frequency_block = "" + + logger.info( + f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示" ) - logger.info( - f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示" - ) - else: - # 回复次数少时的正向提示 - under_count = talk_frequency_threshold - bot_message_count - - if under_count >= talk_frequency_threshold * 0.8: # 回复很少(少于20%) - frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n" - elif under_count >= talk_frequency_threshold * 0.5: # 回复较少(少于50%) - frequency_block = "你感觉状态不错。\n" - else: # 刚好达到阈值 - frequency_block = "" - - logger.info( - f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示" - ) - - except Exception as e: - logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}") - frequency_block = "" + except Exception as e: + logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}") + frequency_block = "" # 如果决定跳过LLM判断,直接更新时间并继续等待 if should_skip_llm_judge: @@ -294,10 +302,11 @@ class NoReplyAction(BaseAction): continue # 跳过本次LLM判断,继续循环等待 # 构建判断上下文 + chat_context = "QQ群" if self.is_group else "私聊" judge_prompt = f""" {identity_block} -你现在正在QQ群参与聊天,以下是聊天内容: +你现在正在{chat_context}参与聊天,以下是聊天内容: {context_str} 在以上的聊天中,你选择了暂时不回复,现在,你看到了新的聊天消息如下: {messages_text} @@ -383,11 +392,11 @@ class NoReplyAction(BaseAction): # 每10秒输出一次等待状态 if elapsed_time < 60: if int(elapsed_time) % 10 == 0 and int(elapsed_time) > 0: - logger.info(f"{self.log_prefix} 已等待{elapsed_time:.0f}秒,等待新消息...") + logger.debug(f"{self.log_prefix} 已等待{elapsed_time:.0f}秒,等待新消息...") await asyncio.sleep(1) else: if int(elapsed_time) % 60 == 0 and int(elapsed_time) > 0: - logger.info(f"{self.log_prefix} 已等待{elapsed_time / 60:.0f}分钟,等待新消息...") + logger.debug(f"{self.log_prefix} 已等待{elapsed_time / 60:.0f}分钟,等待新消息...") await asyncio.sleep(1) # 短暂等待后继续检查 From e564e9713a0f6ec61233c0e658a0c7ba6e54655f Mon Sep 17 00:00:00 2001 From: A0000Xz <122650088+A0000Xz@users.noreply.github.com> Date: Mon, 7 Jul 2025 16:36:42 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=A0=B9=E6=8D=AEno=5Freply=E7=9A=84?= =?UTF-8?q?=E8=B0=83=E6=95=B4=EF=BC=8C=E7=A7=BB=E9=99=A4=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/focus_chat/heartFC_chat.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/chat/focus_chat/heartFC_chat.py b/src/chat/focus_chat/heartFC_chat.py index c52e637fc..2fa1c4a4a 100644 --- a/src/chat/focus_chat/heartFC_chat.py +++ b/src/chat/focus_chat/heartFC_chat.py @@ -190,12 +190,6 @@ class HeartFChatting: if loop_info["loop_action_info"]["command"] == "stop_focus_chat": logger.info(f"{self.log_prefix} 麦麦决定停止专注聊天") - # 如果是私聊,则不停止,而是重置疲劳度并继续 - if not self.chat_stream.group_info: - logger.info(f"{self.log_prefix} 私聊模式下收到停止请求,不退出。") - continue # 继续下一次循环,而不是退出 - - # 如果是群聊,则执行原来的停止逻辑 # 如果设置了回调函数,则调用它 if self.on_stop_focus_chat: try: From f58d2adb0bf515e8b7d46aa96a18df5defbdf398 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Mon, 7 Jul 2025 20:33:29 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix=EF=BC=9A=E7=A7=BB=E9=99=A4=E9=80=80?= =?UTF-8?q?=E5=87=BA=E5=88=A4=E6=96=AD=E7=9A=84=E9=87=8D=E5=A4=8D=E6=A3=80?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/focus_chat/heartFC_chat.py | 4 - src/plugins/built_in/core_actions/no_reply.py | 234 ++++++------------ 2 files changed, 71 insertions(+), 167 deletions(-) diff --git a/src/chat/focus_chat/heartFC_chat.py b/src/chat/focus_chat/heartFC_chat.py index 2fa1c4a4a..08008bfe9 100644 --- a/src/chat/focus_chat/heartFC_chat.py +++ b/src/chat/focus_chat/heartFC_chat.py @@ -478,10 +478,6 @@ class HeartFChatting: ) # 设置系统命令,在下次循环检查时触发退出 command = "stop_focus_chat" - elif self._message_count >= current_threshold and global_config.chat.chat_mode != "auto": - logger.info( - f"{self.log_prefix} [非auto模式] 已发送 {self._message_count} 条消息,达到疲惫阈值 {current_threshold},但非auto模式不会自动退出" - ) else: if reply_text == "timeout": self.reply_timeout_count += 1 diff --git a/src/plugins/built_in/core_actions/no_reply.py b/src/plugins/built_in/core_actions/no_reply.py index 0ce0adbd6..d06c958a9 100644 --- a/src/plugins/built_in/core_actions/no_reply.py +++ b/src/plugins/built_in/core_actions/no_reply.py @@ -109,41 +109,11 @@ class NoReplyAction(BaseAction): if global_config.chat.chat_mode == "auto" and self.is_group: # 检查是否超时 - if elapsed_time >= self._max_timeout: - logger.info(f"{self.log_prefix} 达到最大等待时间{self._max_timeout}秒,退出专注模式") + if elapsed_time >= self._max_timeout or self._check_no_activity_and_exit_focus(current_time): + logger.info(f"{self.log_prefix} 等待时间过久({self._max_timeout}秒)或过去10分钟完全没有发言,退出专注模式") # 标记退出专注模式 self.action_data["_system_command"] = "stop_focus_chat" - exit_reason = f"{global_config.bot.nickname}(你)等待了{self._max_timeout}秒,感觉群里没有新内容,决定退出专注模式,稍作休息" - await self.store_action_info( - action_build_into_prompt=True, - action_prompt_display=exit_reason, - action_done=True, - ) - return True, exit_reason - - # **新增**:检查回复频率,决定是否退出专注模式 - should_exit_focus = await self._check_frequency_and_exit_focus(current_time) - if should_exit_focus: - logger.info(f"{self.log_prefix} 检测到回复频率过高,退出专注模式") - # 标记退出专注模式 - self.action_data["_system_command"] = "stop_focus_chat" - exit_reason = ( - f"{global_config.bot.nickname}(你)发现自己回复太频繁了,决定退出专注模式,稍作休息" - ) - await self.store_action_info( - action_build_into_prompt=True, - action_prompt_display=exit_reason, - action_done=True, - ) - return True, exit_reason - - # **新增**:检查过去10分钟是否完全没有发言,如果是则退出专注模式 - should_exit_no_activity = await self._check_no_activity_and_exit_focus(current_time) - if should_exit_no_activity: - logger.info(f"{self.log_prefix} 检测到过去10分钟完全没有发言,退出专注模式") - # 标记退出专注模式 - self.action_data["_system_command"] = "stop_focus_chat" - exit_reason = f"{global_config.bot.nickname}(你)发现自己过去10分钟完全没有说话,感觉可能不太活跃,决定退出专注模式" + exit_reason = f"{global_config.bot.nickname}(你)等待了{self._max_timeout}秒,或完全没有说话,感觉群里没有新内容,决定退出专注模式,稍作休息" await self.store_action_info( action_build_into_prompt=True, action_prompt_display=exit_reason, @@ -220,83 +190,76 @@ class NoReplyAction(BaseAction): frequency_block = "" should_skip_llm_judge = False # 是否跳过LLM判断 - # 【新增】如果是私聊环境,跳过疲劳度检查 - if not self.is_group: - frequency_block = "你正在和别人私聊,你不会疲惫,正常聊天即可。" - should_skip_llm_judge = False - logger.debug(f"{self.log_prefix} 私聊环境,跳过疲劳度检查") + try: + # 获取过去10分钟的所有消息 + past_10min_time = current_time - 600 # 10分钟前 + all_messages_10min = message_api.get_messages_by_time_in_chat( + chat_id=self.chat_id, + start_time=past_10min_time, + end_time=current_time, + ) - else: + # 手动过滤bot自己的消息 + bot_message_count = 0 + if all_messages_10min: + user_id = global_config.bot.qq_account - try: - # 获取过去10分钟的所有消息 - past_10min_time = current_time - 600 # 10分钟前 - all_messages_10min = message_api.get_messages_by_time_in_chat( - chat_id=self.chat_id, - start_time=past_10min_time, - end_time=current_time, + for message in all_messages_10min: + # 检查消息发送者是否是bot + sender_id = message.get("user_id", "") + + if sender_id == user_id: + bot_message_count += 1 + + talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10 + + if bot_message_count > talk_frequency_threshold: + over_count = bot_message_count - talk_frequency_threshold + + # 根据超过的数量设置不同的提示词和跳过概率 + skip_probability = 0 + if over_count <= 3: + frequency_block = "你感觉稍微有些累,回复的有点多了。\n" + elif over_count <= 5: + frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" + elif over_count <= 8: + frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n" + skip_probability = self._skip_probability + else: + frequency_block = "你感觉非常累,想要安静一会儿。\n" + skip_probability = 1 + + # 根据配置和概率决定是否跳过LLM判断 + if self._skip_judge_when_tired and random.random() < skip_probability: + should_skip_llm_judge = True + logger.info( + f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" + ) + + logger.info( + f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示" + ) + else: + # 回复次数少时的正向提示 + under_count = talk_frequency_threshold - bot_message_count + + if under_count >= talk_frequency_threshold * 0.8: # 回复很少(少于20%) + frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n" + elif under_count >= talk_frequency_threshold * 0.5: # 回复较少(少于50%) + frequency_block = "你感觉状态不错。\n" + else: # 刚好达到阈值 + frequency_block = "" + + logger.info( + f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示" ) - # 手动过滤bot自己的消息 - bot_message_count = 0 - if all_messages_10min: - user_id = global_config.bot.qq_account - - for message in all_messages_10min: - # 检查消息发送者是否是bot - sender_id = message.get("user_id", "") - - if sender_id == user_id: - bot_message_count += 1 - - talk_frequency_threshold = global_config.chat.get_current_talk_frequency(self.chat_id) * 10 - - if bot_message_count > talk_frequency_threshold: - over_count = bot_message_count - talk_frequency_threshold - - # 根据超过的数量设置不同的提示词和跳过概率 - skip_probability = 0 - if over_count <= 3: - frequency_block = "你感觉稍微有些累,回复的有点多了。\n" - elif over_count <= 5: - frequency_block = "你今天说话比较多,感觉有点疲惫,想要稍微休息一下。\n" - elif over_count <= 8: - frequency_block = "你发现自己说话太多了,感觉很累,想要安静一会儿,除非有重要的事情否则不想回复。\n" - skip_probability = self._skip_probability - else: - frequency_block = "你感觉非常累,想要安静一会儿。\n" - skip_probability = 1 - - # 根据配置和概率决定是否跳过LLM判断 - if self._skip_judge_when_tired and random.random() < skip_probability: - should_skip_llm_judge = True - logger.info( - f"{self.log_prefix} 发言过多(超过{over_count}条),随机决定跳过此次LLM判断(概率{skip_probability * 100:.0f}%)" - ) - - logger.info( - f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,超过阈值{talk_frequency_threshold},添加疲惫提示" - ) - else: - # 回复次数少时的正向提示 - under_count = talk_frequency_threshold - bot_message_count - - if under_count >= talk_frequency_threshold * 0.8: # 回复很少(少于20%) - frequency_block = "你感觉精力充沛,状态很好,积极参与聊天。\n" - elif under_count >= talk_frequency_threshold * 0.5: # 回复较少(少于50%) - frequency_block = "你感觉状态不错。\n" - else: # 刚好达到阈值 - frequency_block = "" - - logger.info( - f"{self.log_prefix} 过去10分钟发言{bot_message_count}条,未超过阈值{talk_frequency_threshold},添加正向提示" - ) - - except Exception as e: - logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}") - frequency_block = "" + except Exception as e: + logger.warning(f"{self.log_prefix} 检查发言频率时出错: {e}") + frequency_block = "" # 如果决定跳过LLM判断,直接更新时间并继续等待 + if should_skip_llm_judge: last_judge_time = time.time() # 更新判断时间,避免立即重新判断 continue # 跳过本次LLM判断,继续循环等待 @@ -389,7 +352,10 @@ class NoReplyAction(BaseAction): logger.error(f"{self.log_prefix} 模型判断异常: {e},继续等待") last_judge_time = time.time() # 异常时也更新时间,避免频繁重试 + + # 每10秒输出一次等待状态 + logger.info(f"{self.log_prefix} 开始等待新消息...") if elapsed_time < 60: if int(elapsed_time) % 10 == 0 and int(elapsed_time) > 0: logger.debug(f"{self.log_prefix} 已等待{elapsed_time:.0f}秒,等待新消息...") @@ -414,65 +380,7 @@ class NoReplyAction(BaseAction): ) return False, f"不回复动作执行失败: {e}" - async def _check_frequency_and_exit_focus(self, current_time: float) -> bool: - """检查回复频率,决定是否退出专注模式 - - Args: - current_time: 当前时间戳 - - Returns: - bool: 是否应该退出专注模式 - """ - try: - # 只在auto模式下进行频率检查 - if global_config.chat.chat_mode != "auto": - return False - - # 获取检查窗口内的所有消息 - window_start_time = current_time - self._frequency_check_window - all_messages = message_api.get_messages_by_time_in_chat( - chat_id=self.chat_id, - start_time=window_start_time, - end_time=current_time, - ) - - if not all_messages: - return False - - # 统计bot自己的回复数量 - bot_message_count = 0 - user_id = global_config.bot.qq_account - - for message in all_messages: - sender_id = message.get("user_id", "") - if sender_id == user_id: - bot_message_count += 1 - - # 计算当前回复频率(每分钟回复数) - window_minutes = self._frequency_check_window / 60 - current_frequency = bot_message_count / window_minutes - - # 计算阈值频率:使用 exit_focus_threshold * 1.5 - threshold_multiplier = global_config.chat.exit_focus_threshold * 1.5 - threshold_frequency = global_config.chat.get_current_talk_frequency(self.chat_id) * threshold_multiplier - - # 判断是否超过阈值 - if current_frequency > threshold_frequency: - logger.info( - f"{self.log_prefix} 回复频率检查:当前频率 {current_frequency:.2f}/分钟,超过阈值 {threshold_frequency:.2f}/分钟 (exit_threshold={global_config.chat.exit_focus_threshold} * 1.5),准备退出专注模式" - ) - return True - else: - logger.debug( - f"{self.log_prefix} 回复频率检查:当前频率 {current_frequency:.2f}/分钟,未超过阈值 {threshold_frequency:.2f}/分钟 (exit_threshold={global_config.chat.exit_focus_threshold} * 1.5)" - ) - return False - - except Exception as e: - logger.error(f"{self.log_prefix} 检查回复频率时出错: {e}") - return False - - async def _check_no_activity_and_exit_focus(self, current_time: float) -> bool: + def _check_no_activity_and_exit_focus(self, current_time: float) -> bool: """检查过去10分钟是否完全没有发言,决定是否退出专注模式 Args: