better:重整配置,分离表达,聊天模式区分
重整配置文件路径,添加更多配置选项 分离了人设表达方式和学习到的表达方式 将聊天模式区分为normal focus和auto
This commit is contained in:
@@ -4,7 +4,7 @@ from typing import Optional, Coroutine, Callable, Any, List
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.chat.heart_flow.mai_state_manager import MaiStateManager, MaiStateInfo
|
||||
from src.chat.heart_flow.subheartflow_manager import SubHeartflowManager
|
||||
|
||||
from src.config.config import global_config
|
||||
|
||||
logger = get_logger("background_tasks")
|
||||
|
||||
@@ -94,13 +94,6 @@ class BackgroundTaskManager:
|
||||
f"清理任务已启动 间隔:{CLEANUP_INTERVAL_SECONDS}s",
|
||||
"_cleanup_task",
|
||||
),
|
||||
# 新增兴趣评估任务配置
|
||||
(
|
||||
self._run_into_focus_cycle,
|
||||
"debug", # 设为debug,避免过多日志
|
||||
f"专注评估任务已启动 间隔:{INTEREST_EVAL_INTERVAL_SECONDS}s",
|
||||
"_into_focus_task",
|
||||
),
|
||||
# 新增私聊激活任务配置
|
||||
(
|
||||
# Use lambda to pass the interval to the runner function
|
||||
@@ -111,6 +104,19 @@ class BackgroundTaskManager:
|
||||
),
|
||||
]
|
||||
|
||||
# 根据 chat_mode 条件添加专注评估任务
|
||||
if not (global_config.chat.chat_mode == "normal"):
|
||||
task_configs.append(
|
||||
(
|
||||
self._run_into_focus_cycle,
|
||||
"debug", # 设为debug,避免过多日志
|
||||
f"专注评估任务已启动 间隔:{INTEREST_EVAL_INTERVAL_SECONDS}s",
|
||||
"_into_focus_task",
|
||||
)
|
||||
)
|
||||
else:
|
||||
logger.info("聊天模式为 normal,跳过启动专注评估任务")
|
||||
|
||||
# 统一启动所有任务
|
||||
for task_func, log_level, log_msg, task_attr_name in task_configs:
|
||||
# 检查任务变量是否存在且未完成
|
||||
@@ -183,7 +189,6 @@ class BackgroundTaskManager:
|
||||
logger.info("检测到离线,停用所有子心流")
|
||||
await self.subheartflow_manager.deactivate_all_subflows()
|
||||
|
||||
|
||||
async def _perform_cleanup_work(self):
|
||||
"""执行子心流清理任务
|
||||
1. 获取需要清理的不活跃子心流列表
|
||||
@@ -209,18 +214,15 @@ class BackgroundTaskManager:
|
||||
# 记录最终清理结果
|
||||
logger.info(f"[清理任务] 清理完成, 共停止 {stopped_count}/{len(flows_to_stop)} 个子心流")
|
||||
|
||||
|
||||
# --- 新增兴趣评估工作函数 ---
|
||||
async def _perform_into_focus_work(self):
|
||||
"""执行一轮子心流兴趣评估与提升检查。"""
|
||||
# 直接调用 subheartflow_manager 的方法,并传递当前状态信息
|
||||
await self.subheartflow_manager.sbhf_absent_into_focus()
|
||||
|
||||
await self.subheartflow_manager.sbhf_normal_into_focus()
|
||||
|
||||
async def _run_state_update_cycle(self, interval: int):
|
||||
await _run_periodic_loop(task_name="State Update", interval=interval, task_func=self._perform_state_update_work)
|
||||
|
||||
|
||||
|
||||
async def _run_cleanup_cycle(self):
|
||||
await _run_periodic_loop(
|
||||
task_name="Subflow Cleanup", interval=CLEANUP_INTERVAL_SECONDS, task_func=self._perform_cleanup_work
|
||||
|
||||
@@ -4,13 +4,13 @@ import enum
|
||||
|
||||
class ChatState(enum.Enum):
|
||||
ABSENT = "没在看群"
|
||||
CHAT = "随便水群"
|
||||
NORMAL = "随便水群"
|
||||
FOCUSED = "认真水群"
|
||||
|
||||
|
||||
class ChatStateInfo:
|
||||
def __init__(self):
|
||||
self.chat_status: ChatState = ChatState.CHAT
|
||||
self.chat_status: ChatState = ChatState.NORMAL
|
||||
self.current_state_time = 120
|
||||
|
||||
self.mood_manager = mood_manager
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
from src.chat.heart_flow.sub_heartflow import SubHeartflow, ChatState
|
||||
from src.chat.models.utils_model import LLMRequest
|
||||
from src.config.config import global_config
|
||||
from src.common.logger_manager import get_logger
|
||||
from typing import Any, Optional
|
||||
from src.tools.tool_use import ToolUser
|
||||
from src.chat.heart_flow.mai_state_manager import MaiStateInfo, MaiStateManager
|
||||
from src.chat.heart_flow.subheartflow_manager import SubHeartflowManager
|
||||
from src.chat.heart_flow.background_tasks import BackgroundTaskManager # Import BackgroundTaskManager
|
||||
|
||||
@@ -4,21 +4,10 @@ import random
|
||||
from typing import List, Tuple, Optional
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.manager.mood_manager import mood_manager
|
||||
from src.config.config import global_config
|
||||
|
||||
logger = get_logger("mai_state")
|
||||
|
||||
|
||||
# -- 状态相关的可配置参数 (可以从 glocal_config 加载) --
|
||||
# The line `enable_unlimited_hfc_chat = False` is setting a configuration parameter that controls
|
||||
# whether a specific debugging feature is enabled or not. When `enable_unlimited_hfc_chat` is set to
|
||||
# `False`, it means that the debugging feature for unlimited focused chatting is disabled.
|
||||
# enable_unlimited_hfc_chat = True # 调试用:无限专注聊天
|
||||
enable_unlimited_hfc_chat = False
|
||||
prevent_offline_state = True
|
||||
# 目前默认不启用OFFLINE状
|
||||
|
||||
|
||||
class MaiState(enum.Enum):
|
||||
"""
|
||||
聊天状态:
|
||||
@@ -141,10 +130,6 @@ class MaiStateManager:
|
||||
)
|
||||
next_state = resolved_candidate
|
||||
|
||||
if enable_unlimited_hfc_chat:
|
||||
logger.debug("调试用:开挂了,强制切换到专注聊天")
|
||||
next_state = MaiState.FOCUSED_CHAT
|
||||
|
||||
if next_state is not None and next_state != current_status:
|
||||
return next_state
|
||||
else:
|
||||
|
||||
@@ -57,7 +57,7 @@ class ChattingObservation(Observation):
|
||||
self.talking_message_str_truncate = ""
|
||||
self.name = global_config.bot.nickname
|
||||
self.nick_name = global_config.bot.alias_names
|
||||
self.max_now_obs_len = global_config.chat.observation_context_size
|
||||
self.max_now_obs_len = global_config.focus_chat.observation_context_size
|
||||
self.overlap_len = global_config.focus_chat.compressed_length
|
||||
self.mid_memories = []
|
||||
self.max_mid_memory_len = global_config.focus_chat.compress_length_limit
|
||||
|
||||
@@ -18,7 +18,7 @@ class HFCloopObservation:
|
||||
self.last_observe_time = datetime.now().timestamp() # 初始化为当前时间
|
||||
self.history_loop: List[CycleDetail] = []
|
||||
self.action_manager: ActionManager = None
|
||||
|
||||
|
||||
self.all_actions = {}
|
||||
|
||||
def get_observe_info(self):
|
||||
|
||||
@@ -2,7 +2,7 @@ from .observation.observation import Observation
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
import asyncio
|
||||
import time
|
||||
from typing import Optional, List, Dict, Tuple, Callable, Coroutine
|
||||
from typing import Optional, List, Dict, Tuple
|
||||
import traceback
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.chat.message_receive.message import MessageRecv
|
||||
@@ -23,7 +23,6 @@ class SubHeartflow:
|
||||
self,
|
||||
subheartflow_id,
|
||||
mai_states: MaiStateInfo,
|
||||
hfc_no_reply_callback: Callable[[], Coroutine[None, None, None]],
|
||||
):
|
||||
"""子心流初始化函数
|
||||
|
||||
@@ -35,7 +34,6 @@ class SubHeartflow:
|
||||
# 基础属性,两个值是一样的
|
||||
self.subheartflow_id = subheartflow_id
|
||||
self.chat_id = subheartflow_id
|
||||
self.hfc_no_reply_callback = hfc_no_reply_callback
|
||||
|
||||
# 麦麦的状态
|
||||
self.mai_states = mai_states
|
||||
@@ -92,7 +90,7 @@ class SubHeartflow:
|
||||
# 创建并初始化 normal_chat_instance
|
||||
chat_stream = chat_manager.get_stream(self.chat_id)
|
||||
if chat_stream:
|
||||
self.normal_chat_instance = NormalChat(chat_stream=chat_stream,interest_dict=self.get_interest_dict())
|
||||
self.normal_chat_instance = NormalChat(chat_stream=chat_stream, interest_dict=self.get_interest_dict())
|
||||
await self.normal_chat_instance.initialize()
|
||||
await self.normal_chat_instance.start_chat()
|
||||
logger.info(f"{self.log_prefix} NormalChat 实例已创建并启动。")
|
||||
@@ -189,7 +187,7 @@ class SubHeartflow:
|
||||
# 创建 HeartFChatting 实例,并传递 从构造函数传入的 回调函数
|
||||
self.heart_fc_instance = HeartFChatting(
|
||||
chat_id=self.subheartflow_id,
|
||||
observations=self.observations,
|
||||
observations=self.observations,
|
||||
)
|
||||
|
||||
# 初始化并启动 HeartFChatting
|
||||
@@ -216,7 +214,7 @@ class SubHeartflow:
|
||||
state_changed = False
|
||||
log_prefix = f"[{self.log_prefix}]"
|
||||
|
||||
if new_state == ChatState.CHAT:
|
||||
if new_state == ChatState.NORMAL:
|
||||
logger.debug(f"{log_prefix} 准备进入或保持 普通聊天 状态")
|
||||
if await self._start_normal_chat():
|
||||
logger.debug(f"{log_prefix} 成功进入或保持 NormalChat 状态。")
|
||||
|
||||
@@ -2,13 +2,11 @@ import asyncio
|
||||
import time
|
||||
import random
|
||||
from typing import Dict, Any, Optional, List
|
||||
import functools
|
||||
from src.common.logger_manager import get_logger
|
||||
from src.chat.message_receive.chat_stream import chat_manager
|
||||
from src.chat.heart_flow.sub_heartflow import SubHeartflow, ChatState
|
||||
from src.chat.heart_flow.mai_state_manager import MaiStateInfo
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
from src.config.config import global_config
|
||||
|
||||
|
||||
# 初始化日志记录器
|
||||
@@ -62,7 +60,6 @@ class SubHeartflowManager:
|
||||
self._lock = asyncio.Lock() # 用于保护 self.subheartflows 的访问
|
||||
self.mai_state_info: MaiStateInfo = mai_state_info # 存储传入的 MaiStateInfo 实例
|
||||
|
||||
|
||||
async def force_change_state(self, subflow_id: Any, target_state: ChatState) -> bool:
|
||||
"""强制改变指定子心流的状态"""
|
||||
async with self._lock:
|
||||
@@ -101,16 +98,10 @@ class SubHeartflowManager:
|
||||
return subflow
|
||||
|
||||
try:
|
||||
# --- 使用 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 创建的回调
|
||||
# 初始化子心流, 传入 mai_state_info
|
||||
new_subflow = SubHeartflow(
|
||||
subheartflow_id,
|
||||
self.mai_state_info,
|
||||
hfc_callback, # <-- 传递 partial 创建的回调
|
||||
)
|
||||
|
||||
# 异步初始化
|
||||
@@ -199,22 +190,14 @@ class SubHeartflowManager:
|
||||
f"{log_prefix} 完成,共处理 {processed_count} 个子心流,成功将 {changed_count} 个非 ABSENT 子心流的状态更改为 ABSENT。"
|
||||
)
|
||||
|
||||
async def sbhf_absent_into_focus(self):
|
||||
async def sbhf_normal_into_focus(self):
|
||||
"""评估子心流兴趣度,满足条件则提升到FOCUSED状态(基于start_hfc_probability)"""
|
||||
try:
|
||||
current_state = self.mai_state_info.get_current_state()
|
||||
|
||||
# 检查是否允许进入 FOCUS 模式
|
||||
if not global_config.chat.allow_focus_mode:
|
||||
if int(time.time()) % 60 == 0: # 每60秒输出一次日志避免刷屏
|
||||
logger.trace("未开启 FOCUSED 状态 (allow_focus_mode=False)")
|
||||
return
|
||||
|
||||
for sub_hf in list(self.subheartflows.values()):
|
||||
flow_id = sub_hf.subheartflow_id
|
||||
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
||||
|
||||
# 跳过非CHAT状态或已经是FOCUSED状态的子心流
|
||||
# 跳过已经是FOCUSED状态的子心流
|
||||
if sub_hf.chat_state.chat_status == ChatState.FOCUSED:
|
||||
continue
|
||||
|
||||
@@ -225,13 +208,6 @@ class SubHeartflowManager:
|
||||
f"{stream_name},现在状态: {sub_hf.chat_state.chat_status.value},进入专注概率: {sub_hf.interest_chatting.start_hfc_probability}"
|
||||
)
|
||||
|
||||
# 调试用
|
||||
from .mai_state_manager import enable_unlimited_hfc_chat
|
||||
|
||||
if not enable_unlimited_hfc_chat:
|
||||
if sub_hf.chat_state.chat_status != ChatState.CHAT:
|
||||
continue
|
||||
|
||||
if random.random() >= sub_hf.interest_chatting.start_hfc_probability:
|
||||
continue
|
||||
|
||||
@@ -250,12 +226,11 @@ class SubHeartflowManager:
|
||||
except Exception as e:
|
||||
logger.error(f"启动HFC 兴趣评估失败: {e}", exc_info=True)
|
||||
|
||||
|
||||
async def sbhf_focus_into_absent_or_chat(self, subflow_id: Any):
|
||||
async def sbhf_focus_into_normal(self, subflow_id: Any):
|
||||
"""
|
||||
接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 CHAT。
|
||||
接收来自 HeartFChatting 的请求,将特定子心流的状态转换为 NORMAL。
|
||||
通常在连续多次 "no_reply" 后被调用。
|
||||
对于私聊和群聊,都转换为 CHAT。
|
||||
对于私聊和群聊,都转换为 NORMAL。
|
||||
|
||||
Args:
|
||||
subflow_id: 需要转换状态的子心流 ID。
|
||||
@@ -263,15 +238,15 @@ class SubHeartflowManager:
|
||||
async with self._lock:
|
||||
subflow = self.subheartflows.get(subflow_id)
|
||||
if not subflow:
|
||||
logger.warning(f"[状态转换请求] 尝试转换不存在的子心流 {subflow_id} 到 CHAT")
|
||||
logger.warning(f"[状态转换请求] 尝试转换不存在的子心流 {subflow_id} 到 NORMAL")
|
||||
return
|
||||
|
||||
stream_name = chat_manager.get_stream_name(subflow_id) or subflow_id
|
||||
current_state = subflow.chat_state.chat_status
|
||||
|
||||
if current_state == ChatState.FOCUSED:
|
||||
target_state = ChatState.CHAT
|
||||
log_reason = "转为CHAT"
|
||||
target_state = ChatState.NORMAL
|
||||
log_reason = "转为NORMAL"
|
||||
|
||||
logger.info(
|
||||
f"[状态转换请求] 接收到请求,将 {stream_name} (当前: {current_state.value}) 尝试转换为 {target_state.value} ({log_reason})"
|
||||
@@ -292,34 +267,10 @@ class SubHeartflowManager:
|
||||
f"[状态转换请求] 转换 {stream_name} 到 {target_state.value} 时出错: {e}", exc_info=True
|
||||
)
|
||||
elif current_state == ChatState.ABSENT:
|
||||
logger.debug(f"[状态转换请求] {stream_name} 处于 ABSENT 状态,尝试转为 CHAT")
|
||||
await subflow.change_chat_state(ChatState.CHAT)
|
||||
logger.debug(f"[状态转换请求] {stream_name} 处于 ABSENT 状态,尝试转为 NORMAL")
|
||||
await subflow.change_chat_state(ChatState.NORMAL)
|
||||
else:
|
||||
logger.debug(
|
||||
f"[状态转换请求] {stream_name} 当前状态为 {current_state.value},无需转换"
|
||||
)
|
||||
|
||||
def count_subflows_by_state(self, state: ChatState) -> int:
|
||||
"""统计指定状态的子心流数量"""
|
||||
count = 0
|
||||
# 遍历所有子心流实例
|
||||
for subheartflow in self.subheartflows.values():
|
||||
# 检查子心流状态是否匹配
|
||||
if subheartflow.chat_state.chat_status == state:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def count_subflows_by_state_nolock(self, state: ChatState) -> int:
|
||||
"""
|
||||
统计指定状态的子心流数量 (不上锁版本)。
|
||||
警告:仅应在已持有 self._lock 的上下文中使用此方法。
|
||||
"""
|
||||
count = 0
|
||||
for subheartflow in self.subheartflows.values():
|
||||
if subheartflow.chat_state.chat_status == state:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
logger.debug(f"[状态转换请求] {stream_name} 当前状态为 {current_state.value},无需转换")
|
||||
|
||||
async def delete_subflow(self, subheartflow_id: Any):
|
||||
"""删除指定的子心流。"""
|
||||
@@ -336,28 +287,14 @@ class SubHeartflowManager:
|
||||
else:
|
||||
logger.warning(f"尝试删除不存在的 SubHeartflow: {subheartflow_id}")
|
||||
|
||||
|
||||
async def _handle_hfc_no_reply(self, subheartflow_id: Any):
|
||||
"""处理来自 HeartFChatting 的连续无回复信号 (通过 partial 绑定 ID)"""
|
||||
# 注意:这里不需要再获取锁,因为 sbhf_focus_into_absent_or_chat 内部会处理锁
|
||||
logger.debug(f"[管理器 HFC 处理器] 接收到来自 {subheartflow_id} 的 HFC 无回复信号")
|
||||
await self.sbhf_focus_into_absent_or_chat(subheartflow_id)
|
||||
|
||||
# --- 新增:处理私聊从 ABSENT 直接到 FOCUSED 的逻辑 --- #
|
||||
async def sbhf_absent_private_into_focus(self):
|
||||
"""检查 ABSENT 状态的私聊子心流是否有新活动,若有且未达 FOCUSED 上限,则直接转换为 FOCUSED。"""
|
||||
"""检查 ABSENT 状态的私聊子心流是否有新活动,若有则直接转换为 FOCUSED。"""
|
||||
log_prefix_task = "[私聊激活检查]"
|
||||
transitioned_count = 0
|
||||
checked_count = 0
|
||||
|
||||
# --- 检查是否允许 FOCUS 模式 --- #
|
||||
if not global_config.chat.allow_focus_mode:
|
||||
return
|
||||
|
||||
async with self._lock:
|
||||
# --- 获取当前 FOCUSED 计数 (不上锁版本) --- #
|
||||
current_focused_count = self.count_subflows_by_state_nolock(ChatState.FOCUSED)
|
||||
|
||||
# --- 筛选出所有 ABSENT 状态的私聊子心流 --- #
|
||||
eligible_subflows = [
|
||||
hf
|
||||
@@ -372,7 +309,6 @@ class SubHeartflowManager:
|
||||
|
||||
# --- 遍历评估每个符合条件的私聊 --- #
|
||||
for sub_hf in eligible_subflows:
|
||||
|
||||
flow_id = sub_hf.subheartflow_id
|
||||
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
|
||||
log_prefix = f"[{stream_name}]({log_prefix_task})"
|
||||
@@ -393,13 +329,12 @@ class SubHeartflowManager:
|
||||
else:
|
||||
logger.warning(f"{log_prefix} 无法获取主要观察者来检查活动状态。")
|
||||
|
||||
# --- 如果活跃且未达上限,则尝试转换 --- #
|
||||
# --- 如果活跃,则尝试转换 --- #
|
||||
if is_active:
|
||||
await sub_hf.change_chat_state(ChatState.FOCUSED)
|
||||
# 确认转换成功
|
||||
if sub_hf.chat_state.chat_status == ChatState.FOCUSED:
|
||||
transitioned_count += 1
|
||||
current_focused_count += 1 # 更新计数器以供本轮后续检查
|
||||
logger.info(f"{log_prefix} 成功进入 FOCUSED 状态。")
|
||||
else:
|
||||
logger.warning(
|
||||
|
||||
Reference in New Issue
Block a user