Merge pull request #1097 from A0000Xz/dev

修复hfc在私聊情况下的糟糕表现,让no_reply对私聊不执行退出专注模式的逻辑
This commit is contained in:
SengokuCola
2025-07-07 20:35:10 +08:00
committed by GitHub
2 changed files with 13 additions and 106 deletions

View File

@@ -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:
@@ -484,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

View File

@@ -107,43 +107,13 @@ 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}秒,退出专注模式")
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,
@@ -289,15 +259,17 @@ class NoReplyAction(BaseAction):
frequency_block = ""
# 如果决定跳过LLM判断直接更新时间并继续等待
if should_skip_llm_judge:
last_judge_time = time.time() # 更新判断时间,避免立即重新判断
continue # 跳过本次LLM判断继续循环等待
# 构建判断上下文
chat_context = "QQ群" if self.is_group else "私聊"
judge_prompt = f"""
{identity_block}
你现在正在QQ群参与聊天,以下是聊天内容:
你现在正在{chat_context}参与聊天,以下是聊天内容:
{context_str}
在以上的聊天中,你选择了暂时不回复,现在,你看到了新的聊天消息如下:
{messages_text}
@@ -380,14 +352,17 @@ 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.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)
# 短暂等待后继续检查
@@ -405,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: