🤖 自动格式化代码 [skip ci]

This commit is contained in:
github-actions[bot]
2025-04-30 01:41:00 +00:00
parent 42505960e1
commit ed3d809841
3 changed files with 57 additions and 38 deletions

View File

@@ -156,8 +156,12 @@ class InterestMonitorApp:
self.mind_text_scroll = tk.Scrollbar(self.frame_mind_history)
self.mind_text_scroll.pack(side=tk.RIGHT, fill=tk.Y)
self.mind_text = tk.Text(
self.frame_mind_history, height=25, state="disabled", wrap="word", font=("微软雅黑", 12),
yscrollcommand=self.mind_text_scroll.set
self.frame_mind_history,
height=25,
state="disabled",
wrap="word",
font=("微软雅黑", 12),
yscrollcommand=self.mind_text_scroll.set,
)
self.mind_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=1, padx=5, pady=5)
self.mind_text_scroll.config(command=self.mind_text.yview)

View File

@@ -9,9 +9,9 @@ logger = get_logger("mai_state")
# -- 状态相关的可配置参数 (可以从 glocal_config 加载) --
enable_unlimited_hfc_chat = True # 调试用:无限专注聊天
enable_unlimited_hfc_chat = True # 调试用:无限专注聊天
# enable_unlimited_hfc_chat = False
prevent_offline_state = True # 调试用:防止进入离线状态
prevent_offline_state = True # 调试用:防止进入离线状态
# 不同状态下普通聊天的最大消息数
MAX_NORMAL_CHAT_NUM_PEEKING = 30
@@ -25,6 +25,7 @@ MAX_FOCUSED_CHAT_NUM_FOCUSED = 40
# -- 状态定义 --
class MaiState(enum.Enum):
"""
聊天状态:
@@ -204,8 +205,10 @@ class MaiStateManager:
if time_limit_exceeded:
next_state_candidate = random.choices(choices_list, weights=weights, k=1)[0]
resolved_candidate = _resolve_offline(next_state_candidate)
logger.debug(f"规则{rule_id}:时间到,随机选择 {next_state_candidate.value}resolve 为 {resolved_candidate.value}")
next_state = resolved_candidate # 直接使用解析后的状态
logger.debug(
f"规则{rule_id}:时间到,随机选择 {next_state_candidate.value}resolve 为 {resolved_candidate.value}"
)
next_state = resolved_candidate # 直接使用解析后的状态
# 注意enable_unlimited_hfc_chat 优先级高于 prevent_offline_state
# 如果触发了这个它会覆盖上面规则2设置的 next_state

View File

@@ -1,7 +1,7 @@
import asyncio
import time
import traceback
import random # <--- 添加导入
import random # <--- 添加导入
from typing import List, Optional, Dict, Any, Deque, Callable, Coroutine
from collections import deque
from src.plugins.chat.message import MessageRecv, BaseMessageInfo, MessageThinking, MessageSending
@@ -32,7 +32,7 @@ from src.individuality.individuality import Individuality
INITIAL_DURATION = 60.0
WAITING_TIME_THRESHOLD = 300 # 等待新消息时间阈值,单位秒
WAITING_TIME_THRESHOLD = 300 # 等待新消息时间阈值,单位秒
logger = get_logger("interest") # Logger Name Changed
@@ -48,11 +48,11 @@ class ActionManager:
def __init__(self):
# 初始化为默认动作集
self._available_actions: Dict[str, str] = DEFAULT_ACTIONS.copy()
self._original_actions_backup: Optional[Dict[str, str]] = None # 用于临时移除时的备份
self._original_actions_backup: Optional[Dict[str, str]] = None # 用于临时移除时的备份
def get_available_actions(self) -> Dict[str, str]:
"""获取当前可用的动作集"""
return self._available_actions.copy() # 返回副本以防外部修改
return self._available_actions.copy() # 返回副本以防外部修改
def add_action(self, action_name: str, description: str) -> bool:
"""
@@ -518,7 +518,7 @@ class HeartFChatting:
logger.error(f"{self.log_prefix} 处理{action}时出错: {e}")
# 出错时也重置计数器
self._lian_xu_bu_hui_fu_ci_shu = 0
self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间
self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间
return False, ""
async def _handle_text_reply(self, reasoning: str, emoji_query: str, cycle_timers: dict) -> tuple[bool, str]:
@@ -541,7 +541,7 @@ class HeartFChatting:
"""
# 重置连续不回复计数器
self._lian_xu_bu_hui_fu_ci_shu = 0
self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间
self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间
# 获取锚点消息
anchor_message = await self._get_anchor_message()
@@ -597,7 +597,7 @@ class HeartFChatting:
bool: 是否发送成功
"""
logger.info(f"{self.log_prefix} 决定回复表情({emoji_query}): {reasoning}")
self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间(即使不计数也保持一致性)
self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间(即使不计数也保持一致性)
try:
anchor = await self._get_anchor_message()
@@ -633,17 +633,16 @@ class HeartFChatting:
observation = self.observations[0] if self.observations else None
try:
dang_qian_deng_dai = 0.0 # 初始化本次等待时间
dang_qian_deng_dai = 0.0 # 初始化本次等待时间
with Timer("等待新消息", cycle_timers):
# 等待新消息、超时或关闭信号,并获取结果
await self._wait_for_new_message(observation, planner_start_db_time, self.log_prefix)
# 从计时器获取实际等待时间
dang_qian_deng_dai = cycle_timers.get("等待新消息", 0.0)
if not self._shutting_down:
self._lian_xu_bu_hui_fu_ci_shu += 1
self._lian_xu_deng_dai_shi_jian += dang_qian_deng_dai # 累加等待时间
self._lian_xu_deng_dai_shi_jian += dang_qian_deng_dai # 累加等待时间
logger.debug(
f"{self.log_prefix} 连续不回复计数增加: {self._lian_xu_bu_hui_fu_ci_shu}/{self.CONSECUTIVE_NO_REPLY_THRESHOLD}, "
f"本次等待: {dang_qian_deng_dai:.2f}秒, 累计等待: {self._lian_xu_deng_dai_shi_jian:.2f}"
@@ -651,8 +650,10 @@ class HeartFChatting:
# 检查是否同时达到次数和时间阈值
time_threshold = 0.66 * WAITING_TIME_THRESHOLD * self.CONSECUTIVE_NO_REPLY_THRESHOLD
if (self._lian_xu_bu_hui_fu_ci_shu >= self.CONSECUTIVE_NO_REPLY_THRESHOLD and
self._lian_xu_deng_dai_shi_jian >= time_threshold):
if (
self._lian_xu_bu_hui_fu_ci_shu >= self.CONSECUTIVE_NO_REPLY_THRESHOLD
and self._lian_xu_deng_dai_shi_jian >= time_threshold
):
logger.info(
f"{self.log_prefix} 连续不回复达到阈值 ({self._lian_xu_bu_hui_fu_ci_shu}次) "
f"且累计等待时间达到 {self._lian_xu_deng_dai_shi_jian:.2f}秒 (阈值 {time_threshold}秒)"
@@ -668,7 +669,6 @@ class HeartFChatting:
)
# else: 次数和时间都未达到阈值,不做处理
return True
except asyncio.CancelledError:
@@ -793,9 +793,9 @@ class HeartFChatting:
logger.info(f"{self.log_prefix}[Planner] 开始{'重新' if is_re_planned else ''}执行规划器")
# --- 新增:检查历史动作并调整可用动作 ---
lian_xu_wen_ben_hui_fu = 0 # 连续文本回复次数
lian_xu_wen_ben_hui_fu = 0 # 连续文本回复次数
actions_to_remove_temporarily = []
probability_roll = random.random() # 在循环外掷骰子一次,用于概率判断
probability_roll = random.random() # 在循环外掷骰子一次,用于概率判断
# 反向遍历最近的循环历史
for cycle in reversed(self._cycle_history):
@@ -804,9 +804,11 @@ class HeartFChatting:
if cycle.action_type == "text_reply":
lian_xu_wen_ben_hui_fu += 1
else:
break # 遇到非文本回复,中断计数
break # 遇到非文本回复,中断计数
# 检查最近的3个循环即可避免检查过多历史 (如果历史很长)
if len(self._cycle_history) > 0 and cycle.cycle_id <= self._cycle_history[0].cycle_id + (len(self._cycle_history) - 4):
if len(self._cycle_history) > 0 and cycle.cycle_id <= self._cycle_history[0].cycle_id + (
len(self._cycle_history) - 4
):
break
logger.debug(f"{self.log_prefix}[Planner] 检测到连续文本回复次数: {lian_xu_wen_ben_hui_fu}")
@@ -816,13 +818,15 @@ class HeartFChatting:
logger.info(f"{self.log_prefix}[Planner] 连续回复 >= 3 次,强制移除 text_reply 和 emoji_reply")
actions_to_remove_temporarily.extend(["text_reply", "emoji_reply"])
elif lian_xu_wen_ben_hui_fu == 2:
if probability_roll < 0.8: # 80% 概率
if probability_roll < 0.8: # 80% 概率
logger.info(f"{self.log_prefix}[Planner] 连续回复 2 次80% 概率移除 text_reply 和 emoji_reply (触发)")
actions_to_remove_temporarily.extend(["text_reply", "emoji_reply"])
else:
logger.info(f"{self.log_prefix}[Planner] 连续回复 2 次80% 概率移除 text_reply 和 emoji_reply (未触发)")
logger.info(
f"{self.log_prefix}[Planner] 连续回复 2 次80% 概率移除 text_reply 和 emoji_reply (未触发)"
)
elif lian_xu_wen_ben_hui_fu == 1:
if probability_roll < 0.4: # 40% 概率
if probability_roll < 0.4: # 40% 概率
logger.info(f"{self.log_prefix}[Planner] 连续回复 1 次40% 概率移除 text_reply (触发)")
actions_to_remove_temporarily.append("text_reply")
else:
@@ -847,7 +851,9 @@ class HeartFChatting:
# --- 新增:应用临时动作移除 ---
if actions_to_remove_temporarily:
self.action_manager.temporarily_remove_actions(actions_to_remove_temporarily)
logger.debug(f"{self.log_prefix}[Planner] 临时移除的动作: {actions_to_remove_temporarily}, 当前可用: {list(self.action_manager.get_available_actions().keys())}")
logger.debug(
f"{self.log_prefix}[Planner] 临时移除的动作: {actions_to_remove_temporarily}, 当前可用: {list(self.action_manager.get_available_actions().keys())}"
)
# --- 构建提示词 ---
replan_prompt_str = ""
@@ -862,7 +868,7 @@ class HeartFChatting:
# --- 调用 LLM ---
try:
planner_tools = self.action_manager.get_planner_tool_definition()
logger.debug(f"{self.log_prefix}[Planner] 本次使用的工具定义: {planner_tools}") # 记录本次使用的工具
logger.debug(f"{self.log_prefix}[Planner] 本次使用的工具定义: {planner_tools}") # 记录本次使用的工具
_response_text, _reasoning_content, tool_calls = await self.planner_llm.generate_response_tool_async(
prompt=prompt,
tools=planner_tools,
@@ -914,13 +920,15 @@ class HeartFChatting:
action = "no_reply"
reasoning = f"LLM返回了当前不可用的动作: {extracted_action}"
emoji_query = ""
llm_error = False # 视为逻辑修正而非 LLM 错误
llm_error = False # 视为逻辑修正而非 LLM 错误
# --- 检查 'no_reply' 是否也恰好被移除了 (极端情况) ---
if "no_reply" not in self.action_manager.get_available_actions():
logger.error(f"{self.log_prefix}[Planner] 严重错误:'no_reply' 动作也不可用!无法执行任何动作。")
action = "error" # 回退到错误状态
reasoning = "无法执行任何有效动作,包括 no_reply"
llm_error = True
logger.error(
f"{self.log_prefix}[Planner] 严重错误:'no_reply' 动作也不可用!无法执行任何动作。"
)
action = "error" # 回退到错误状态
reasoning = "无法执行任何有效动作,包括 no_reply"
llm_error = True
else:
# 动作有效且可用,使用提取的值
action = extracted_action
@@ -944,11 +952,13 @@ class HeartFChatting:
# 如果没有有效的工具调用,我们需要检查 'no_reply' 是否是当前唯一可用的动作
available_actions = list(self.action_manager.get_available_actions().keys())
if available_actions == ["no_reply"]:
logger.info(f"{self.log_prefix}[Planner] LLM未返回工具调用但当前唯一可用动作是 'no_reply',将执行 'no_reply'")
logger.info(
f"{self.log_prefix}[Planner] LLM未返回工具调用但当前唯一可用动作是 'no_reply',将执行 'no_reply'"
)
action = "no_reply"
reasoning = "LLM未返回工具调用且当前仅 'no_reply' 可用"
emoji_query = ""
llm_error = False # 视为逻辑选择而非错误
llm_error = False # 视为逻辑选择而非错误
else:
reasoning = "LLM未返回有效的工具调用"
logger.warning(f"{self.log_prefix}[Planner] {reasoning}")
@@ -963,9 +973,11 @@ class HeartFChatting:
llm_error = True
# --- 新增:确保动作恢复 ---
finally:
if actions_to_remove_temporarily: # 只有当确实移除了动作时才需要恢复
self.action_manager.restore_actions()
logger.debug(f"{self.log_prefix}[Planner] 恢复了原始动作集, 当前可用: {list(self.action_manager.get_available_actions().keys())}")
if actions_to_remove_temporarily: # 只有当确实移除了动作时才需要恢复
self.action_manager.restore_actions()
logger.debug(
f"{self.log_prefix}[Planner] 恢复了原始动作集, 当前可用: {list(self.action_manager.get_available_actions().keys())}"
)
# --- 结束:确保动作恢复 ---
# --- 结束 LLM 决策 --- #