diff --git a/src/chat/focus_chat/heartFC_chat.py b/src/chat/focus_chat/heartFC_chat.py index 08008bfe9..70cda57c6 100644 --- a/src/chat/focus_chat/heartFC_chat.py +++ b/src/chat/focus_chat/heartFC_chat.py @@ -4,20 +4,21 @@ import time import traceback from collections import deque from typing import List, Optional, Dict, Any, Deque, Callable, Awaitable -from src.chat.message_receive.chat_stream import get_chat_manager from rich.traceback import install -from src.chat.utils.prompt_builder import global_prompt_manager + +from src.config.config import global_config from src.common.logger import get_logger +from src.chat.message_receive.chat_stream import get_chat_manager +from src.chat.utils.prompt_builder import global_prompt_manager from src.chat.utils.timer_calculator import Timer -from src.chat.focus_chat.focus_loop_info import FocusLoopInfo from src.chat.planner_actions.planner import ActionPlanner from src.chat.planner_actions.action_modifier import ActionModifier from src.chat.planner_actions.action_manager import ActionManager -from src.config.config import global_config +from src.chat.focus_chat.focus_loop_info import FocusLoopInfo from src.chat.focus_chat.hfc_performance_logger import HFCPerformanceLogger -from src.person_info.relationship_builder_manager import relationship_builder_manager from src.chat.focus_chat.hfc_utils import CycleDetail - +from src.person_info.relationship_builder_manager import relationship_builder_manager +from src.plugin_system.base.component_types import ChatMode install(extra_lines=3) @@ -134,8 +135,7 @@ class HeartFChatting: def _handle_loop_completion(self, task: asyncio.Task): """当 _hfc_loop 任务完成时执行的回调。""" try: - exception = task.exception() - if exception: + if exception := task.exception(): logger.error(f"{self.log_prefix} HeartFChatting: 脱离了聊天(异常): {exception}") logger.error(traceback.format_exc()) # Log full traceback for exceptions else: @@ -342,7 +342,7 @@ class HeartFChatting: # 调用完整的动作修改流程 await self.action_modifier.modify_actions( loop_info=self.loop_info, - mode="focus", + mode=ChatMode.FOCUS, ) except Exception as e: logger.error(f"{self.log_prefix} 动作修改失败: {e}") diff --git a/src/chat/heart_flow/chat_state_info.py b/src/chat/heart_flow/chat_state_info.py index 33936186b..871516d49 100644 --- a/src/chat/heart_flow/chat_state_info.py +++ b/src/chat/heart_flow/chat_state_info.py @@ -5,6 +5,9 @@ class ChatState(enum.Enum): ABSENT = "没在看群" NORMAL = "随便水群" FOCUSED = "认真水群" + + def __str__(self): + return self.name class ChatStateInfo: diff --git a/src/chat/heart_flow/heartflow.py b/src/chat/heart_flow/heartflow.py index ca6e8be7b..fdcfba6a3 100644 --- a/src/chat/heart_flow/heartflow.py +++ b/src/chat/heart_flow/heartflow.py @@ -16,14 +16,11 @@ class Heartflow: async def get_or_create_subheartflow(self, subheartflow_id: Any) -> Optional["SubHeartflow"]: """获取或创建一个新的SubHeartflow实例""" if subheartflow_id in self.subheartflows: - subflow = self.subheartflows.get(subheartflow_id) - if subflow: + if subflow := self.subheartflows.get(subheartflow_id): return subflow try: - new_subflow = SubHeartflow( - subheartflow_id, - ) + new_subflow = SubHeartflow(subheartflow_id) await new_subflow.initialize() diff --git a/src/chat/heart_flow/heartflow_message_processor.py b/src/chat/heart_flow/heartflow_message_processor.py index fc4337887..d01775168 100644 --- a/src/chat/heart_flow/heartflow_message_processor.py +++ b/src/chat/heart_flow/heartflow_message_processor.py @@ -123,7 +123,7 @@ class HeartFCMessageReceiver: logger.debug(f"[{mes_name}][当前时段回复频率: {current_talk_frequency}]") - # 8. 关系处理 + # 4. 关系处理 if global_config.relationship.enable_relationship: await _process_relationship(message) diff --git a/src/chat/heart_flow/sub_heartflow.py b/src/chat/heart_flow/sub_heartflow.py index 9ef357379..9f6a49895 100644 --- a/src/chat/heart_flow/sub_heartflow.py +++ b/src/chat/heart_flow/sub_heartflow.py @@ -72,27 +72,28 @@ class SubHeartflow: 停止 NormalChat 实例 切出 CHAT 状态时使用 """ - if self.normal_chat_instance: - logger.info(f"{self.log_prefix} 离开normal模式") - try: - logger.debug(f"{self.log_prefix} 开始调用 stop_chat()") - # 使用更短的超时时间,强制快速停止 - await asyncio.wait_for(self.normal_chat_instance.stop_chat(), timeout=3.0) - logger.debug(f"{self.log_prefix} stop_chat() 调用完成") - except asyncio.TimeoutError: - logger.warning(f"{self.log_prefix} 停止 NormalChat 超时,强制清理") - # 超时时强制清理实例 + if not self.normal_chat_instance: + return + logger.info(f"{self.log_prefix} 离开normal模式") + try: + logger.debug(f"{self.log_prefix} 开始调用 stop_chat()") + # 使用更短的超时时间,强制快速停止 + await asyncio.wait_for(self.normal_chat_instance.stop_chat(), timeout=3.0) + logger.debug(f"{self.log_prefix} stop_chat() 调用完成") + except asyncio.TimeoutError: + logger.warning(f"{self.log_prefix} 停止 NormalChat 超时,强制清理") + # 超时时强制清理实例 + self.normal_chat_instance = None + except Exception as e: + logger.error(f"{self.log_prefix} 停止 NormalChat 监控任务时出错: {e}") + # 出错时也要清理实例,避免状态不一致 + self.normal_chat_instance = None + finally: + # 确保实例被清理 + if self.normal_chat_instance: + logger.warning(f"{self.log_prefix} 强制清理 NormalChat 实例") self.normal_chat_instance = None - except Exception as e: - logger.error(f"{self.log_prefix} 停止 NormalChat 监控任务时出错: {e}") - # 出错时也要清理实例,避免状态不一致 - self.normal_chat_instance = None - finally: - # 确保实例被清理 - if self.normal_chat_instance: - logger.warning(f"{self.log_prefix} 强制清理 NormalChat 实例") - self.normal_chat_instance = None - logger.debug(f"{self.log_prefix} _stop_normal_chat 完成") + logger.debug(f"{self.log_prefix} _stop_normal_chat 完成") async def _start_normal_chat(self, rewind=False) -> bool: """ @@ -348,6 +349,4 @@ class SubHeartflow: if elapsed_since_exit >= cooldown_duration: return 1.0 # 冷却完成 - # 计算进度:0表示刚开始冷却,1表示冷却完成 - progress = elapsed_since_exit / cooldown_duration - return progress + return elapsed_since_exit / cooldown_duration diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index 4704cb238..b5e9890eb 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -1,28 +1,30 @@ import asyncio import time +import traceback from random import random from typing import List, Optional +from maim_message import UserInfo, Seg + from src.config.config import global_config from src.common.logger import get_logger -from src.person_info.person_info import get_person_info_manager -from src.plugin_system.apis import generator_api -from maim_message import UserInfo, Seg -from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager -from src.chat.utils.timer_calculator import Timer from src.common.message_repository import count_messages -from src.chat.utils.prompt_builder import global_prompt_manager -from ..message_receive.message import MessageSending, MessageRecv, MessageThinking, MessageSet +from src.plugin_system.apis import generator_api +from src.plugin_system.base.component_types import ChatMode +from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager +from src.chat.message_receive.message import MessageSending, MessageRecv, MessageThinking, MessageSet from src.chat.message_receive.normal_message_sender import message_manager from src.chat.normal_chat.willing.willing_manager import get_willing_manager from src.chat.planner_actions.action_manager import ActionManager -from src.person_info.relationship_builder_manager import relationship_builder_manager -from .priority_manager import PriorityManager -import traceback from src.chat.planner_actions.planner import ActionPlanner from src.chat.planner_actions.action_modifier import ActionModifier - from src.chat.utils.utils import get_chat_type_and_target_info +from src.chat.utils.prompt_builder import global_prompt_manager +from src.chat.utils.timer_calculator import Timer from src.mood.mood_manager import mood_manager +from src.person_info.person_info import get_person_info_manager +from src.person_info.relationship_builder_manager import relationship_builder_manager +from .priority_manager import PriorityManager + willing_manager = get_willing_manager() @@ -70,7 +72,7 @@ class NormalChat: # Planner相关初始化 self.action_manager = ActionManager() - self.planner = ActionPlanner(self.stream_id, self.action_manager, mode="normal") + self.planner = ActionPlanner(self.stream_id, self.action_manager, mode=ChatMode.NORMAL) self.action_modifier = ActionModifier(self.action_manager, self.stream_id) self.enable_planner = global_config.normal_chat.enable_planner # 从配置中读取是否启用planner @@ -126,13 +128,8 @@ class NormalChat: continue # 条目已被其他任务处理 message, interest_value, _ = value - if not self._disabled: - # 更新消息段信息 - # self._update_user_message_segments(message) - - # 添加消息到优先级管理器 - if self.priority_manager: - self.priority_manager.add_message(message, interest_value) + if not self._disabled and self.priority_manager: + self.priority_manager.add_message(message, interest_value) except Exception: logger.error( @@ -564,8 +561,8 @@ class NormalChat: available_actions = None if self.enable_planner: try: - await self.action_modifier.modify_actions(mode="normal", message_content=message.processed_plain_text) - available_actions = self.action_manager.get_using_actions_for_mode("normal") + await self.action_modifier.modify_actions(mode=ChatMode.NORMAL, message_content=message.processed_plain_text) + available_actions = self.action_manager.get_using_actions_for_mode(ChatMode.NORMAL) except Exception as e: logger.warning(f"[{self.stream_name}] 获取available_actions失败: {e}") available_actions = None diff --git a/src/chat/normal_chat/priority_manager.py b/src/chat/normal_chat/priority_manager.py index 9e1ef76c2..0296017ff 100644 --- a/src/chat/normal_chat/priority_manager.py +++ b/src/chat/normal_chat/priority_manager.py @@ -2,7 +2,8 @@ import time import heapq import math from typing import List, Dict, Optional -from ..message_receive.message import MessageRecv + +from src.chat.message_receive.message import MessageRecv from src.common.logger import get_logger logger = get_logger("normal_chat") diff --git a/src/chat/planner_actions/action_manager.py b/src/chat/planner_actions/action_manager.py index 3918831ca..3937d1d14 100644 --- a/src/chat/planner_actions/action_manager.py +++ b/src/chat/planner_actions/action_manager.py @@ -3,14 +3,10 @@ from src.plugin_system.base.base_action import BaseAction from src.chat.message_receive.chat_stream import ChatStream from src.common.logger import get_logger from src.plugin_system.core.component_registry import component_registry -from src.plugin_system.base.component_types import ComponentType +from src.plugin_system.base.component_types import ComponentType, ActionActivationType, ChatMode, ActionInfo logger = get_logger("action_manager") -# 定义动作信息类型 -ActionInfo = Dict[str, Any] - - class ActionManager: """ 动作管理器,用于管理各种类型的动作 @@ -20,8 +16,8 @@ class ActionManager: # 类常量 DEFAULT_RANDOM_PROBABILITY = 0.3 - DEFAULT_MODE = "all" - DEFAULT_ACTIVATION_TYPE = "always" + DEFAULT_MODE = ChatMode.ALL + DEFAULT_ACTIVATION_TYPE = ActionActivationType.ALWAYS def __init__(self): """初始化动作管理器""" @@ -54,11 +50,8 @@ class ActionManager: def _load_plugin_system_actions(self) -> None: """从插件系统的component_registry加载Action组件""" try: - from src.plugin_system.core.component_registry import component_registry - from src.plugin_system.base.component_types import ComponentType - # 获取所有Action组件 - action_components = component_registry.get_components_by_type(ComponentType.ACTION) + action_components: Dict[str, ActionInfo] = component_registry.get_components_by_type(ComponentType.ACTION) for action_name, action_info in action_components.items(): if action_name in self._registered_actions: @@ -181,28 +174,28 @@ class ActionManager: """获取当前正在使用的动作集合""" return self._using_actions.copy() - def get_using_actions_for_mode(self, mode: str) -> Dict[str, ActionInfo]: + def get_using_actions_for_mode(self, mode: ChatMode) -> Dict[str, ActionInfo]: """ 根据聊天模式获取可用的动作集合 Args: - mode: 聊天模式 ("focus", "normal", "all") + mode: 聊天模式 (ChatMode.FOCUS, ChatMode.NORMAL, ChatMode.ALL) Returns: Dict[str, ActionInfo]: 在指定模式下可用的动作集合 """ - filtered_actions = {} + enabled_actions = {} for action_name, action_info in self._using_actions.items(): - action_mode = action_info.get("mode_enable", "all") + action_mode = action_info.mode_enable # 检查动作是否在当前模式下启用 - if action_mode == "all" or action_mode == mode: - filtered_actions[action_name] = action_info + if action_mode in [ChatMode.ALL, mode]: + enabled_actions[action_name] = action_info logger.debug(f"动作 {action_name} 在模式 {mode} 下可用 (mode_enable: {action_mode})") - logger.debug(f"模式 {mode} 下可用动作: {list(filtered_actions.keys())}") - return filtered_actions + logger.debug(f"模式 {mode} 下可用动作: {list(enabled_actions.keys())}") + return enabled_actions def add_action_to_using(self, action_name: str) -> bool: """ diff --git a/src/chat/planner_actions/action_modifier.py b/src/chat/planner_actions/action_modifier.py index a2e0066cf..4b15cbdb0 100644 --- a/src/chat/planner_actions/action_modifier.py +++ b/src/chat/planner_actions/action_modifier.py @@ -1,15 +1,17 @@ -from typing import List, Optional, Any, Dict -from src.common.logger import get_logger -from src.chat.focus_chat.focus_loop_info import FocusLoopInfo -from src.chat.message_receive.chat_stream import get_chat_manager -from src.config.config import global_config -from src.llm_models.utils_model import LLMRequest import random import asyncio import hashlib import time +from typing import List, Optional, Any, Dict + +from src.common.logger import get_logger +from src.config.config import global_config +from src.llm_models.utils_model import LLMRequest +from src.chat.focus_chat.focus_loop_info import FocusLoopInfo +from src.chat.message_receive.chat_stream import get_chat_manager from src.chat.planner_actions.action_manager import ActionManager from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages +from src.plugin_system.base.component_types import ChatMode logger = get_logger("action_manager") @@ -44,7 +46,7 @@ class ActionModifier: async def modify_actions( self, loop_info=None, - mode: str = "focus", + mode: ChatMode = ChatMode.FOCUS, message_content: str = "", ): """ @@ -528,7 +530,7 @@ class ActionModifier: def get_available_actions_count(self) -> int: """获取当前可用动作数量(排除默认的no_action)""" - current_actions = self.action_manager.get_using_actions_for_mode("normal") + current_actions = self.action_manager.get_using_actions_for_mode(ChatMode.NORMAL) # 排除no_action(如果存在) filtered_actions = {k: v for k, v in current_actions.items() if k != "no_action"} return len(filtered_actions) diff --git a/src/chat/planner_actions/planner.py b/src/chat/planner_actions/planner.py index edd5d010d..db7001b14 100644 --- a/src/chat/planner_actions/planner.py +++ b/src/chat/planner_actions/planner.py @@ -1,18 +1,21 @@ -import json # <--- 确保导入 json +import json +import time import traceback from typing import Dict, Any, Optional from rich.traceback import install +from datetime import datetime +from json_repair import repair_json + from src.llm_models.utils_model import LLMRequest from src.config.config import global_config from src.common.logger import get_logger from src.chat.utils.prompt_builder import Prompt, global_prompt_manager -from src.chat.planner_actions.action_manager import ActionManager -from json_repair import repair_json -from src.chat.utils.utils import get_chat_type_and_target_info -from datetime import datetime -from src.chat.message_receive.chat_stream import get_chat_manager from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat -import time +from src.chat.utils.utils import get_chat_type_and_target_info +from src.chat.planner_actions.action_manager import ActionManager +from src.chat.message_receive.chat_stream import get_chat_manager +from src.plugin_system.base.component_types import ChatMode + logger = get_logger("planner") @@ -54,7 +57,7 @@ def init_prompt(): class ActionPlanner: - def __init__(self, chat_id: str, action_manager: ActionManager, mode: str = "focus"): + def __init__(self, chat_id: str, action_manager: ActionManager, mode: ChatMode = ChatMode.FOCUS): self.chat_id = chat_id self.log_prefix = f"[{get_chat_manager().get_stream_name(chat_id) or chat_id}]" self.mode = mode @@ -62,7 +65,7 @@ class ActionPlanner: # LLM规划器配置 self.planner_llm = LLMRequest( model=global_config.model.planner, - request_type=f"{self.mode}.planner", # 用于动作规划 + request_type=f"{self.mode.value}.planner", # 用于动作规划 ) self.last_obs_time_mark = 0.0 @@ -224,7 +227,7 @@ class ActionPlanner: self.last_obs_time_mark = time.time() - if self.mode == "focus": + if self.mode == ChatMode.FOCUS: by_what = "聊天内容" no_action_block = "" else: diff --git a/src/plugin_system/base/component_types.py b/src/plugin_system/base/component_types.py index b69aaac2a..f720823c6 100644 --- a/src/plugin_system/base/component_types.py +++ b/src/plugin_system/base/component_types.py @@ -23,6 +23,9 @@ class ActionActivationType(Enum): RANDOM = "random" # 随机启用action到planner KEYWORD = "keyword" # 关键词触发启用action到planner + def __str__(self): + return self.value + # 聊天模式枚举 class ChatMode(Enum): @@ -32,6 +35,9 @@ class ChatMode(Enum): NORMAL = "normal" # Normal聊天模式 ALL = "all" # 所有聊天模式 + def __str__(self): + return self.value + @dataclass class PythonDependency: diff --git a/start_lpmm.bat b/start_lpmm.bat deleted file mode 100644 index eacaa2eb1..000000000 --- a/start_lpmm.bat +++ /dev/null @@ -1,88 +0,0 @@ -@echo off -CHCP 65001 > nul -setlocal enabledelayedexpansion - -echo 你需要选择启动方式,输入字母来选择: -echo V = 不知道什么意思就输入 V -echo C = 输入 C 使用 Conda 环境 -echo. -choice /C CV /N /M "不知道什么意思就输入 V (C/V)?" /T 10 /D V - -set "ENV_TYPE=" -if %ERRORLEVEL% == 1 set "ENV_TYPE=CONDA" -if %ERRORLEVEL% == 2 set "ENV_TYPE=VENV" - -if "%ENV_TYPE%" == "CONDA" goto activate_conda -if "%ENV_TYPE%" == "VENV" goto activate_venv - -REM 如果 choice 超时或返回意外值,默认使用 venv -echo WARN: Invalid selection or timeout from choice. Defaulting to VENV. -set "ENV_TYPE=VENV" -goto activate_venv - -:activate_conda - set /p CONDA_ENV_NAME="请输入要使用的 Conda 环境名称: " - if not defined CONDA_ENV_NAME ( - echo 错误: 未输入 Conda 环境名称. - pause - exit /b 1 - ) - echo 选择: Conda '!CONDA_ENV_NAME!' - REM 激活Conda环境 - call conda activate !CONDA_ENV_NAME! - if !ERRORLEVEL! neq 0 ( - echo 错误: Conda环境 '!CONDA_ENV_NAME!' 激活失败. 请确保Conda已安装并正确配置, 且 '!CONDA_ENV_NAME!' 环境存在. - pause - exit /b 1 - ) - goto env_activated - -:activate_venv - echo Selected: venv (default or selected) - REM 查找venv虚拟环境 - set "venv_path=%~dp0venv\Scripts\activate.bat" - if not exist "%venv_path%" ( - echo Error: venv not found. Ensure the venv directory exists alongside the script. - pause - exit /b 1 - ) - REM 激活虚拟环境 - call "%venv_path%" - if %ERRORLEVEL% neq 0 ( - echo Error: Failed to activate venv virtual environment. - pause - exit /b 1 - ) - goto env_activated - -:env_activated -echo Environment activated successfully! - -REM --- 后续脚本执行 --- - -REM 运行预处理脚本 -python "%~dp0scripts\raw_data_preprocessor.py" -if %ERRORLEVEL% neq 0 ( - echo Error: raw_data_preprocessor.py execution failed. - pause - exit /b 1 -) - -REM 运行信息提取脚本 -python "%~dp0scripts\info_extraction.py" -if %ERRORLEVEL% neq 0 ( - echo Error: info_extraction.py execution failed. - pause - exit /b 1 -) - -REM 运行OpenIE导入脚本 -python "%~dp0scripts\import_openie.py" -if %ERRORLEVEL% neq 0 ( - echo Error: import_openie.py execution failed. - pause - exit /b 1 -) - -echo All processing steps completed! -pause \ No newline at end of file