feat:提供方法让HFC结束,当等待过久no_reply,会回到ABSENT模式
This commit is contained in:
@@ -3,6 +3,7 @@ import time
|
||||
import random
|
||||
from typing import Dict, Any, Optional, List
|
||||
import json # 导入 json 模块
|
||||
import functools # <-- 新增导入
|
||||
|
||||
# 导入日志模块
|
||||
from src.common.logger import get_module_logger, LogConfig, SUBHEARTFLOW_MANAGER_STYLE_CONFIG
|
||||
@@ -77,8 +78,17 @@ class SubHeartflowManager:
|
||||
return subflow
|
||||
|
||||
try:
|
||||
# 初始化子心流, 传入存储的 mai_state_info
|
||||
new_subflow = SubHeartflow(subheartflow_id, self.mai_state_info)
|
||||
# --- 使用 functools.partial 创建 HFC 回调 --- #
|
||||
# 将 manager 的 _handle_hfc_no_reply 方法与当前的 subheartflow_id 绑定
|
||||
hfc_callback = functools.partial(self._handle_hfc_no_reply, subheartflow_id)
|
||||
# --- 结束创建回调 --- #
|
||||
|
||||
# 初始化子心流, 传入 mai_state_info 和 partial 创建的回调
|
||||
new_subflow = SubHeartflow(
|
||||
subheartflow_id,
|
||||
self.mai_state_info,
|
||||
hfc_callback # <-- 传递 partial 创建的回调
|
||||
)
|
||||
|
||||
# 异步初始化
|
||||
await new_subflow.initialize()
|
||||
@@ -285,74 +295,11 @@ class SubHeartflowManager:
|
||||
) and final_subflow.chat_state.chat_status == ChatState.FOCUSED:
|
||||
current_focused_count += 1
|
||||
|
||||
async def randomly_deactivate_subflows(self, deactivation_probability: float = 0.1):
|
||||
"""以一定概率将 FOCUSED 或 CHAT 状态的子心流回退到 ABSENT 状态。"""
|
||||
log_prefix_manager = "[子心流管理器-随机停用]"
|
||||
logger.debug(f"{log_prefix_manager} 开始随机停用检查... (概率: {deactivation_probability:.0%})")
|
||||
|
||||
# 使用快照安全遍历
|
||||
subflows_snapshot = list(self.subheartflows.values())
|
||||
deactivated_count = 0
|
||||
|
||||
try:
|
||||
for sub_hf in subflows_snapshot:
|
||||
flow_id = sub_hf.subheartflow_id
|
||||
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
||||
log_prefix_flow = f"[{stream_name}]"
|
||||
current_state = sub_hf.chat_state.chat_status
|
||||
|
||||
# 只处理 FOCUSED 或 CHAT 状态
|
||||
if current_state not in [ChatState.FOCUSED, ChatState.CHAT]:
|
||||
continue
|
||||
|
||||
# 检查随机概率
|
||||
if random.random() < deactivation_probability:
|
||||
logger.info(
|
||||
f"{log_prefix_manager} {log_prefix_flow} 随机触发停用 (从 {current_state.value}) -> ABSENT"
|
||||
)
|
||||
|
||||
# 获取当前实例以检查最新状态
|
||||
current_subflow = self.subheartflows.get(flow_id)
|
||||
if not current_subflow or current_subflow.chat_state.chat_status != current_state:
|
||||
logger.warning(f"{log_prefix_manager} {log_prefix_flow} 尝试停用时状态已改变或实例消失,跳过。")
|
||||
continue
|
||||
|
||||
# --- 状态设置 --- #
|
||||
# 注意:这里传递的状态数量是 *停用前* 的状态数量
|
||||
await current_subflow.change_chat_state(ChatState.ABSENT)
|
||||
|
||||
# --- 状态验证 (可选) ---
|
||||
final_subflow = self.subheartflows.get(flow_id)
|
||||
if final_subflow:
|
||||
final_state = final_subflow.chat_state.chat_status
|
||||
if final_state == ChatState.ABSENT:
|
||||
logger.debug(
|
||||
f"{log_prefix_manager} {log_prefix_flow} 成功从 {current_state.value} 停用到 ABSENT 状态"
|
||||
)
|
||||
deactivated_count += 1
|
||||
else:
|
||||
logger.warning(
|
||||
f"{log_prefix_manager} {log_prefix_flow} 尝试停用到 ABSENT 后状态仍为 {final_state.value}"
|
||||
)
|
||||
else:
|
||||
logger.warning(f"{log_prefix_manager} {log_prefix_flow} 停用后验证时子心流 {flow_id} 消失")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"{log_prefix_manager} 随机停用周期出错: {e}", exc_info=True)
|
||||
|
||||
if deactivated_count > 0:
|
||||
logger.info(f"{log_prefix_manager} 随机停用周期结束, 成功停用 {deactivated_count} 个子心流。")
|
||||
else:
|
||||
logger.debug(f"{log_prefix_manager} 随机停用周期结束, 未停用任何子心流。")
|
||||
|
||||
async def evaluate_and_transition_subflows_by_llm(self):
|
||||
"""
|
||||
使用LLM评估每个子心流的状态,并根据LLM的判断执行状态转换(ABSENT <-> CHAT)。
|
||||
注意:此函数包含对假设的LLM函数的调用。
|
||||
"""
|
||||
log_prefix = "[LLM状态评估]"
|
||||
logger.info(f"{log_prefix} 开始基于LLM评估子心流状态...")
|
||||
|
||||
# 获取当前状态和限制,用于CHAT激活检查
|
||||
current_mai_state = self.mai_state_info.get_current_state()
|
||||
chat_limit = current_mai_state.get_normal_chat_max_num()
|
||||
@@ -366,33 +313,27 @@ class SubHeartflowManager:
|
||||
current_chat_count = self.count_subflows_by_state_nolock(ChatState.CHAT)
|
||||
|
||||
if not subflows_snapshot:
|
||||
logger.info(f"{log_prefix} 当前没有子心流需要评估。")
|
||||
logger.info("当前没有子心流需要评估。")
|
||||
return
|
||||
|
||||
for sub_hf in subflows_snapshot:
|
||||
flow_id = sub_hf.subheartflow_id
|
||||
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
||||
log_prefix = f"[{stream_name}]"
|
||||
current_subflow_state = sub_hf.chat_state.chat_status
|
||||
|
||||
# --- 获取观察内容 ---
|
||||
# 从 sub_hf.observations 获取 ChattingObservation 并提取信息
|
||||
|
||||
_observation_summary = "没有可用的观察信息。" # 默认值
|
||||
try:
|
||||
# 检查 observations 列表是否存在且不为空
|
||||
|
||||
# 假设第一个观察者是 ChattingObservation
|
||||
first_observation = sub_hf.observations[0]
|
||||
if isinstance(first_observation, ChattingObservation):
|
||||
# 组合中期记忆和当前聊天内容
|
||||
current_chat = first_observation.talking_message_str or "当前无聊天内容。"
|
||||
combined_summary = f"当前聊天内容:\n{current_chat}"
|
||||
else:
|
||||
logger.warning(f"{log_prefix} [{stream_name}] 第一个观察者不是 ChattingObservation 类型。")
|
||||
first_observation = sub_hf.observations[0]
|
||||
if isinstance(first_observation, ChattingObservation):
|
||||
# 组合中期记忆和当前聊天内容
|
||||
current_chat = first_observation.talking_message_str or "当前无聊天内容。"
|
||||
combined_summary = f"当前聊天内容:\n{current_chat}"
|
||||
else:
|
||||
logger.warning(f"{log_prefix} [{stream_name}] 第一个观察者不是 ChattingObservation 类型。")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"{log_prefix} [{stream_name}] 获取观察信息失败: {e}", exc_info=True)
|
||||
# 保留默认值或错误信息
|
||||
combined_summary = f"获取观察信息时出错: {e}"
|
||||
|
||||
# --- 获取麦麦状态 ---
|
||||
mai_state_description = f"麦麦当前状态: {current_mai_state.value}。"
|
||||
@@ -414,7 +355,7 @@ class SubHeartflowManager:
|
||||
# 调用LLM评估
|
||||
should_activate = await self._llm_evaluate_state_transition(prompt)
|
||||
if should_activate is None: # 处理解析失败或意外情况
|
||||
logger.warning(f"{log_prefix} [{stream_name}] LLM评估返回无效结果,跳过。")
|
||||
logger.warning(f"{log_prefix}LLM评估返回无效结果,跳过。")
|
||||
continue
|
||||
|
||||
if should_activate:
|
||||
@@ -423,17 +364,19 @@ class SubHeartflowManager:
|
||||
current_chat_count = self.count_subflows_by_state_nolock(ChatState.CHAT)
|
||||
if current_chat_count < chat_limit:
|
||||
logger.info(
|
||||
f"{log_prefix} [{stream_name}] LLM建议激活到CHAT状态,且未达上限({current_chat_count}/{chat_limit})。正在尝试转换..."
|
||||
f"{log_prefix}LLM建议激活到CHAT状态,且未达上限({current_chat_count}/{chat_limit})。正在尝试转换..."
|
||||
)
|
||||
await sub_hf.change_chat_state(ChatState.CHAT)
|
||||
if sub_hf.chat_state.chat_status == ChatState.CHAT:
|
||||
transitioned_to_chat += 1
|
||||
else:
|
||||
logger.warning(f"{log_prefix} [{stream_name}] 尝试激活到CHAT失败。")
|
||||
logger.warning(f"{log_prefix}尝试激活到CHAT失败。")
|
||||
else:
|
||||
logger.info(
|
||||
f"{log_prefix} [{stream_name}] LLM建议激活到CHAT状态,但已达到上限({current_chat_count}/{chat_limit})。跳过转换。"
|
||||
f"{log_prefix}LLM建议激活到CHAT状态,但已达到上限({current_chat_count}/{chat_limit})。跳过转换。"
|
||||
)
|
||||
else:
|
||||
logger.info(f"{log_prefix}LLM建议不激活到CHAT状态。")
|
||||
|
||||
# --- 针对 CHAT 状态 ---
|
||||
elif current_subflow_state == ChatState.CHAT:
|
||||
@@ -452,20 +395,18 @@ class SubHeartflowManager:
|
||||
# 调用LLM评估
|
||||
should_deactivate = await self._llm_evaluate_state_transition(prompt)
|
||||
if should_deactivate is None: # 处理解析失败或意外情况
|
||||
logger.warning(f"{log_prefix} [{stream_name}] LLM评估返回无效结果,跳过。")
|
||||
logger.warning(f"{log_prefix}LLM评估返回无效结果,跳过。")
|
||||
continue
|
||||
|
||||
if should_deactivate:
|
||||
logger.info(f"{log_prefix} [{stream_name}] LLM建议进入ABSENT状态。正在尝试转换...")
|
||||
logger.info(f"{log_prefix}LLM建议进入ABSENT状态。正在尝试转换...")
|
||||
await sub_hf.change_chat_state(ChatState.ABSENT)
|
||||
if sub_hf.chat_state.chat_status == ChatState.ABSENT:
|
||||
transitioned_to_absent += 1
|
||||
|
||||
logger.info(
|
||||
f"{log_prefix} LLM评估周期结束。"
|
||||
f" 成功转换到CHAT: {transitioned_to_chat}."
|
||||
f" 成功转换到ABSENT: {transitioned_to_absent}."
|
||||
)
|
||||
else:
|
||||
logger.info(f"{log_prefix}LLM建议不进入ABSENT状态。")
|
||||
|
||||
|
||||
|
||||
async def _llm_evaluate_state_transition(self, prompt: str) -> Optional[bool]:
|
||||
"""
|
||||
@@ -482,7 +423,8 @@ class SubHeartflowManager:
|
||||
try:
|
||||
# --- 真实的 LLM 调用 ---
|
||||
response_text, _ = await self.llm_state_evaluator.generate_response_async(prompt)
|
||||
logger.debug(f"{log_prefix} 使用模型 {self.llm_state_evaluator.model_name} 评估,原始响应: ```{response_text}```")
|
||||
logger.debug(f"{log_prefix} 使用模型 {self.llm_state_evaluator.model_name} 评估")
|
||||
logger.debug(f"{log_prefix} 原始响应: {response_text}")
|
||||
|
||||
# --- 解析 JSON 响应 ---
|
||||
try:
|
||||
@@ -573,3 +515,46 @@ class SubHeartflowManager:
|
||||
logger.error(f"删除 SubHeartflow {subheartflow_id} 时出错: {e}", exc_info=True)
|
||||
else:
|
||||
logger.warning(f"尝试删除不存在的 SubHeartflow: {subheartflow_id}")
|
||||
|
||||
# --- 新增:处理 HFC 无回复回调的专用方法 --- #
|
||||
async def _handle_hfc_no_reply(self, subheartflow_id: Any):
|
||||
"""处理来自 HeartFChatting 的连续无回复信号 (通过 partial 绑定 ID)"""
|
||||
# 注意:这里不需要再获取锁,因为 request_absent_transition 内部会处理锁
|
||||
logger.debug(f"[管理器 HFC 处理器] 接收到来自 {subheartflow_id} 的 HFC 无回复信号")
|
||||
await self.request_absent_transition(subheartflow_id)
|
||||
# --- 结束新增 --- #
|
||||
|
||||
# --- 新增:处理来自 HeartFChatting 的状态转换请求 --- #
|
||||
async def request_absent_transition(self, subflow_id: Any):
|
||||
"""
|
||||
接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 ABSENT。
|
||||
通常在连续多次 "no_reply" 后被调用。
|
||||
|
||||
Args:
|
||||
subflow_id: 需要转换状态的子心流 ID。
|
||||
"""
|
||||
async with self._lock:
|
||||
subflow = self.subheartflows.get(subflow_id)
|
||||
if not subflow:
|
||||
logger.warning(f"[状态转换请求] 尝试转换不存在的子心流 {subflow_id} 到 ABSENT")
|
||||
return
|
||||
|
||||
stream_name = chat_manager.get_stream_name(subflow_id) or subflow_id
|
||||
current_state = subflow.chat_state.chat_status
|
||||
|
||||
# 仅当子心流处于 FOCUSED 状态时才进行转换
|
||||
# 因为 HeartFChatting 只在 FOCUSED 状态下运行
|
||||
if current_state == ChatState.FOCUSED:
|
||||
logger.info(f"[状态转换请求] 接收到请求,将 {stream_name} (当前: {current_state.value}) 转换为 ABSENT")
|
||||
try:
|
||||
await subflow.change_chat_state(ChatState.ABSENT)
|
||||
logger.info(f"[状态转换请求] {stream_name} 状态已成功转换为 ABSENT")
|
||||
except Exception as e:
|
||||
logger.error(f"[状态转换请求] 转换 {stream_name} 到 ABSENT 时出错: {e}", exc_info=True)
|
||||
elif current_state == ChatState.ABSENT:
|
||||
logger.debug(f"[状态转换请求] {stream_name} 已处于 ABSENT 状态,无需转换")
|
||||
else:
|
||||
logger.warning(
|
||||
f"[状态转换请求] 收到对 {stream_name} 的请求,但其状态为 {current_state.value} (非 FOCUSED),不执行转换"
|
||||
)
|
||||
# --- 结束新增 --- #
|
||||
|
||||
Reference in New Issue
Block a user