🤖 自动格式化代码 [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 = tk.Scrollbar(self.frame_mind_history)
self.mind_text_scroll.pack(side=tk.RIGHT, fill=tk.Y) self.mind_text_scroll.pack(side=tk.RIGHT, fill=tk.Y)
self.mind_text = tk.Text( self.mind_text = tk.Text(
self.frame_mind_history, height=25, state="disabled", wrap="word", font=("微软雅黑", 12), self.frame_mind_history,
yscrollcommand=self.mind_text_scroll.set 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.pack(side=tk.LEFT, fill=tk.BOTH, expand=1, padx=5, pady=5)
self.mind_text_scroll.config(command=self.mind_text.yview) self.mind_text_scroll.config(command=self.mind_text.yview)

View File

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

View File

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