dev:让麦麦更愿意说话

This commit is contained in:
SengokuCola
2025-04-26 21:00:21 +08:00
parent 3763a0ed9e
commit c012d29cbf
2 changed files with 112 additions and 63 deletions

View File

@@ -103,7 +103,7 @@ class SubMind:
individuality = Individuality.get_instance() individuality = Individuality.get_instance()
# 构建个性部分 # 构建个性部分
prompt_personality = f"的名字是{individuality.personality.bot_nickname},你" prompt_personality = f"正在扮演名为{individuality.personality.bot_nickname}的人类,你"
prompt_personality += individuality.personality.personality_core prompt_personality += individuality.personality.personality_core
# 随机添加个性侧面 # 随机添加个性侧面

View File

@@ -19,9 +19,10 @@ from .observation import ChattingObservation
# 导入LLM请求工具 # 导入LLM请求工具
from src.plugins.models.utils_model import LLMRequest from src.plugins.models.utils_model import LLMRequest
from src.config.config import global_config from src.config.config import global_config
from src.individuality.individuality import Individuality
import traceback import traceback
# 初始化日志记录器 # 初始化日志记录器
subheartflow_manager_log_config = LogConfig( subheartflow_manager_log_config = LogConfig(
@@ -110,24 +111,53 @@ class SubHeartflowManager:
logger.error(f"创建子心流 {subheartflow_id} 失败: {e}", exc_info=True) logger.error(f"创建子心流 {subheartflow_id} 失败: {e}", exc_info=True)
return None return None
# --- 新增:内部方法,用于尝试将单个子心流设置为 ABSENT ---
async def _try_set_subflow_absent_internal(self, subflow: "SubHeartflow", log_prefix: str) -> bool:
"""
尝试将给定的子心流对象状态设置为 ABSENT (内部方法,不处理锁)。
Args:
subflow: 子心流对象。
log_prefix: 用于日志记录的前缀 (例如 "[子心流管理]""[停用]")。
Returns:
bool: 如果状态成功变为 ABSENT 或原本就是 ABSENT返回 True否则返回 False。
"""
flow_id = subflow.subheartflow_id
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
if subflow.chat_state.chat_status != ChatState.ABSENT:
logger.debug(f"{log_prefix} 设置 {stream_name} 状态为 ABSENT")
try:
await subflow.change_chat_state(ChatState.ABSENT)
# 再次检查以确认状态已更改 (change_chat_state 内部应确保)
if subflow.chat_state.chat_status == ChatState.ABSENT:
return True
else:
logger.warning(f"{log_prefix} 调用 change_chat_state 后,{stream_name} 状态仍为 {subflow.chat_state.chat_status.value}")
return False
except Exception as e:
logger.error(f"{log_prefix} 设置 {stream_name} 状态为 ABSENT 时失败: {e}", exc_info=True)
return False
else:
logger.debug(f"{log_prefix} {stream_name} 已是 ABSENT 状态")
return True # 已经是目标状态,视为成功
# --- 结束新增 ---
async def sleep_subheartflow(self, subheartflow_id: Any, reason: str) -> bool: async def sleep_subheartflow(self, subheartflow_id: Any, reason: str) -> bool:
"""停止指定的子心流并清理资源""" """停止指定的子心流并将其状态设置为 ABSENT"""
subheartflow = self.subheartflows.get(subheartflow_id) log_prefix = "[子心流管理]"
if not subheartflow: async with self._lock: # 加锁以安全访问字典
return False subheartflow = self.subheartflows.get(subheartflow_id)
stream_name = chat_manager.get_stream_name(subheartflow_id) or subheartflow_id stream_name = chat_manager.get_stream_name(subheartflow_id) or subheartflow_id
logger.info(f"[子心流管理] 正在停止 {stream_name}, 原因: {reason}") logger.info(f"{log_prefix} 正在停止 {stream_name}, 原因: {reason}")
try: # 调用内部方法处理状态变更
# 设置状态为ABSENT释放资源 success = await self._try_set_subflow_absent_internal(subheartflow, log_prefix)
if subheartflow.chat_state.chat_status != ChatState.ABSENT:
logger.debug(f"[子心流管理] 设置 {stream_name} 状态为ABSENT") return success
await subheartflow.change_chat_state(ChatState.ABSENT) # 锁在此处自动释放
else:
logger.debug(f"[子心流管理] {stream_name} 已是ABSENT状态")
except Exception as e:
logger.error(f"[子心流管理] 设置ABSENT状态失败: {e}")
def get_inactive_subheartflows(self, max_age_seconds=INACTIVE_THRESHOLD_SECONDS): def get_inactive_subheartflows(self, max_age_seconds=INACTIVE_THRESHOLD_SECONDS):
"""识别并返回需要清理的不活跃(处于ABSENT状态超过一小时)子心流(id, 原因)""" """识别并返回需要清理的不活跃(处于ABSENT状态超过一小时)子心流(id, 原因)"""
@@ -195,44 +225,37 @@ class SubHeartflowManager:
async def deactivate_all_subflows(self): async def deactivate_all_subflows(self):
"""将所有子心流的状态更改为 ABSENT (例如主状态变为OFFLINE时调用)""" """将所有子心流的状态更改为 ABSENT (例如主状态变为OFFLINE时调用)"""
# logger.info("[停用] 开始将所有子心流状态设置为 ABSENT") log_prefix = "[停用]"
# 使用 list() 创建一个当前值的快照,防止在迭代时修改字典
flows_to_update = list(self.subheartflows.values())
if not flows_to_update:
logger.debug("[停用] 无活跃子心流,无需操作")
return
changed_count = 0 changed_count = 0
for subflow in flows_to_update: processed_count = 0
flow_id = subflow.subheartflow_id
stream_name = chat_manager.get_stream_name(flow_id) or flow_id
# 再次检查子心流是否仍然存在于管理器中,以防万一在迭代过程中被移除
if subflow.chat_state.chat_status != ChatState.ABSENT: async with self._lock: # 获取锁以安全迭代
logger.debug( # 使用 list() 创建一个当前值的快照,防止在迭代时修改字典
f"正在将子心流 {stream_name} 的状态从 {subflow.chat_state.chat_status.value} 更改为 ABSENT" flows_to_update = list(self.subheartflows.values())
) processed_count = len(flows_to_update)
try: if not flows_to_update:
# 调用 change_chat_state 将状态设置为 ABSENT logger.debug(f"{log_prefix} 无活跃子心流,无需操作")
await subflow.change_chat_state(ChatState.ABSENT) return
# 验证状态是否真的改变了
if ( for subflow in flows_to_update:
flow_id in self.subheartflows # 记录原始状态,以便统计实际改变的数量
and self.subheartflows[flow_id].chat_state.chat_status == ChatState.ABSENT original_state_was_absent = (subflow.chat_state.chat_status == ChatState.ABSENT)
):
success = await self._try_set_subflow_absent_internal(subflow, log_prefix)
# 如果成功设置为 ABSENT 且原始状态不是 ABSENT则计数
if success and not original_state_was_absent:
if subflow.chat_state.chat_status == ChatState.ABSENT:
changed_count += 1 changed_count += 1
else: else:
logger.warning( # 这种情况理论上不应发生,如果内部方法返回 True 的话
f"[停用] 尝试更改子心流 {stream_name} 状态后,状态仍未变为 ABSENT 或子心流已消失。" stream_name = chat_manager.get_stream_name(subflow.subheartflow_id) or subflow.subheartflow_id
) logger.warning(f"{log_prefix} 内部方法声称成功但 {stream_name} 状态未变为 ABSENT。")
except Exception as e: # 锁在此处自动释放
logger.error(f"[停用] 更改子心流 {stream_name} 状态为 ABSENT 时出错: {e}", exc_info=True)
else:
logger.debug(f"[停用] 子心流 {stream_name} 已处于 ABSENT 状态,无需更改。")
logger.info( logger.info(
f"下限完成,共处理 {len(flows_to_update)} 个子心流,成功将 {changed_count} 个子心流的状态更改为 ABSENT。" f"{log_prefix} 完成,共处理 {processed_count} 个子心流,成功将 {changed_count}非 ABSENT 子心流的状态更改为 ABSENT。"
) )
async def evaluate_interest_and_promote(self): async def evaluate_interest_and_promote(self):
@@ -328,6 +351,7 @@ class SubHeartflowManager:
first_observation = sub_hf.observations[0] first_observation = sub_hf.observations[0]
if isinstance(first_observation, ChattingObservation): if isinstance(first_observation, ChattingObservation):
# 组合中期记忆和当前聊天内容 # 组合中期记忆和当前聊天内容
first_observation.observe()
current_chat = first_observation.talking_message_str or "当前无聊天内容。" current_chat = first_observation.talking_message_str or "当前无聊天内容。"
combined_summary = f"当前聊天内容:\n{current_chat}" combined_summary = f"当前聊天内容:\n{current_chat}"
else: else:
@@ -336,19 +360,40 @@ class SubHeartflowManager:
# --- 获取麦麦状态 --- # --- 获取麦麦状态 ---
mai_state_description = f"麦麦当前状态: {current_mai_state.value}" mai_state_description = f"当前状态: {current_mai_state.value}"
# 获取个性化信息
individuality = Individuality.get_instance()
# 构建个性部分
prompt_personality = f"你正在扮演名为{individuality.personality.bot_nickname}的人类,你"
prompt_personality += individuality.personality.personality_core
# 随机添加个性侧面
if individuality.personality.personality_sides:
random_side = random.choice(individuality.personality.personality_sides)
prompt_personality += f"{random_side}"
# 随机添加身份细节
if individuality.identity.identity_detail:
random_detail = random.choice(individuality.identity.identity_detail)
prompt_personality += f"{random_detail}"
# --- 针对 ABSENT 状态 --- # --- 针对 ABSENT 状态 ---
if current_subflow_state == ChatState.ABSENT: if current_subflow_state == ChatState.ABSENT:
# 构建Prompt # 构建Prompt
prompt = ( prompt = (
f"子心流 [{stream_name}] 当前处于非活跃(ABSENT)状态.\n" f"{prompt_personality}\n"
f"你当前没有在: [{stream_name}] 群中聊天。\n"
f"{mai_state_description}\n" f"{mai_state_description}\n"
f"最近观察到的内容摘要:\n---\n{combined_summary}\n---\n" f"这个群里最近的聊天内容是:\n---\n{combined_summary}\n---\n"
f"基于以上信息,该子心流是否表现出足够的活跃迹象或重要性" f"基于以上信息,请判断你是否愿意在这个群开始闲聊"
f"值得将其唤醒并进入常规聊天(CHAT)状态?\n" f"进入常规聊天(CHAT)状态?\n"
f"请以 JSON 格式回答,包含一个键 'decision',其值为 true 或 false.\n" f"给出你的判断,和理由,然后以 JSON 格式回答"
f"例如:{{\"decision\": true}}\n" f"包含键 'decision',如果要开始聊天,值为 true ,否则为 false.\n"
f"包含键 'reason',其值为你的理由。\n"
f"例如:{{\"decision\": true, \"reason\": \"因为我想聊天\"}}\n"
f"请只输出有效的 JSON 对象。" f"请只输出有效的 JSON 对象。"
) )
@@ -382,13 +427,16 @@ class SubHeartflowManager:
elif current_subflow_state == ChatState.CHAT: elif current_subflow_state == ChatState.CHAT:
# 构建Prompt # 构建Prompt
prompt = ( prompt = (
f"子心流 [{stream_name}] 当前处于常规聊天(CHAT)状态.\n" f"{prompt_personality}\n"
f"你正在在: [{stream_name}] 群中聊天。\n"
f"{mai_state_description}\n" f"{mai_state_description}\n"
f"最近观察到的内容摘要:\n---\n{combined_summary}\n---\n" f"这个群里最近的聊天内容是:\n---\n{combined_summary}\n---\n"
f"基于以上信息,该子心流是否表现出不活跃、对话结束或不再需要关注的迹象" f"基于以上信息,请判断你是否愿意在这个群继续闲聊"
f"应该让其进入休眠(ABSENT)状态?\n" f"还是暂时离开聊天,进入休眠状态?\n"
f"请以 JSON 格式回答,包含一个键 'decision',其值为 true (表示应休眠) 或 false (表示不应休眠).\n" f"给出你的判断,和理由,然后以 JSON 格式回答"
f"例如:{{\"decision\": true}}\n" f"包含键 'decision',如果要离开聊天,值为 true ,否则为 false.\n"
f"包含键 'reason',其值为你的理由。\n"
f"例如:{{\"decision\": true, \"reason\": \"因为我想休息\"}}\n"
f"请只输出有效的 JSON 对象。" f"请只输出有效的 JSON 对象。"
) )
@@ -423,7 +471,8 @@ class SubHeartflowManager:
try: try:
# --- 真实的 LLM 调用 --- # --- 真实的 LLM 调用 ---
response_text, _ = await self.llm_state_evaluator.generate_response_async(prompt) response_text, _ = await self.llm_state_evaluator.generate_response_async(prompt)
logger.debug(f"{log_prefix} 使用模型 {self.llm_state_evaluator.model_name} 评估") # logger.debug(f"{log_prefix} 使用模型 {self.llm_state_evaluator.model_name} 评估")
logger.debug(f"{log_prefix} 原始输入: {prompt}")
logger.debug(f"{log_prefix} 原始响应: {response_text}") logger.debug(f"{log_prefix} 原始响应: {response_text}")
# --- 解析 JSON 响应 --- # --- 解析 JSON 响应 ---