refactor(chat): 异步化聊天系统并重构兴趣值计算机制
将同步调用改为异步调用以提升性能,重构兴趣值计算流程以支持更灵活的组件化架构。主要改进包括: - 异步化ChatManager相关方法,避免阻塞主线程 - 重构兴趣值计算系统,从插件内部计算改为通过兴趣管理器统一处理 - 新增should_act字段支持更细粒度的动作决策 - 优化初始化逻辑,避免构造函数中的异步操作 - 扩展插件系统支持兴趣计算器组件注册 - 更新数据库模型以支持新的兴趣值相关字段 这些改进提升了系统的响应性能和可扩展性,同时保持了API的向后兼容性。
This commit is contained in:
223
src/chat/interest_system/interest_manager.py
Normal file
223
src/chat/interest_system/interest_manager.py
Normal file
@@ -0,0 +1,223 @@
|
||||
"""兴趣值计算组件管理器
|
||||
|
||||
管理兴趣值计算组件的生命周期,确保系统只能有一个兴趣值计算组件实例运行
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.base.base_interest_calculator import BaseInterestCalculator, InterestCalculationResult
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.common.data_models.database_data_model import DatabaseMessages
|
||||
|
||||
logger = get_logger("interest_manager")
|
||||
|
||||
|
||||
class InterestManager:
|
||||
"""兴趣值计算组件管理器"""
|
||||
|
||||
_instance = None
|
||||
_initialized = False
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
if not self._initialized:
|
||||
self._current_calculator: BaseInterestCalculator | None = None
|
||||
self._calculator_lock = asyncio.Lock()
|
||||
self._last_calculation_time = 0.0
|
||||
self._total_calculations = 0
|
||||
self._failed_calculations = 0
|
||||
self._calculation_queue = asyncio.Queue()
|
||||
self._worker_task = None
|
||||
self._shutdown_event = asyncio.Event()
|
||||
self._initialized = True
|
||||
|
||||
async def initialize(self):
|
||||
"""初始化管理器"""
|
||||
if self._worker_task is None:
|
||||
self._worker_task = asyncio.create_task(self._calculation_worker())
|
||||
logger.info("兴趣值管理器已启动")
|
||||
|
||||
async def shutdown(self):
|
||||
"""关闭管理器"""
|
||||
self._shutdown_event.set()
|
||||
if self._worker_task:
|
||||
self._worker_task.cancel()
|
||||
try:
|
||||
await self._worker_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
if self._current_calculator:
|
||||
await self._current_calculator.cleanup()
|
||||
self._current_calculator = None
|
||||
|
||||
logger.info("兴趣值管理器已关闭")
|
||||
|
||||
async def register_calculator(self, calculator: BaseInterestCalculator) -> bool:
|
||||
"""注册兴趣值计算组件(系统只能有一个活跃的兴趣值计算器)
|
||||
|
||||
Args:
|
||||
calculator: 兴趣值计算组件实例
|
||||
|
||||
Returns:
|
||||
bool: 注册是否成功
|
||||
"""
|
||||
async with self._calculator_lock:
|
||||
try:
|
||||
# 检查是否已有相同的计算器
|
||||
if self._current_calculator and self._current_calculator.component_name == calculator.component_name:
|
||||
logger.warning(f"兴趣值计算组件 {calculator.component_name} 已经注册,跳过重复注册")
|
||||
return True
|
||||
|
||||
# 如果已有组件在运行,先清理并替换
|
||||
if self._current_calculator:
|
||||
logger.info(f"替换现有兴趣值计算组件: {self._current_calculator.component_name} -> {calculator.component_name}")
|
||||
await self._current_calculator.cleanup()
|
||||
else:
|
||||
logger.info(f"注册新的兴趣值计算组件: {calculator.component_name}")
|
||||
|
||||
# 初始化新组件
|
||||
if await calculator.initialize():
|
||||
self._current_calculator = calculator
|
||||
logger.info(f"兴趣值计算组件注册成功: {calculator.component_name} v{calculator.component_version}")
|
||||
logger.info("系统现在只有一个活跃的兴趣值计算器")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"兴趣值计算组件初始化失败: {calculator.component_name}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"注册兴趣值计算组件失败: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
async def calculate_interest(self, message: "DatabaseMessages") -> InterestCalculationResult:
|
||||
"""计算消息兴趣值
|
||||
|
||||
Args:
|
||||
message: 数据库消息对象
|
||||
|
||||
Returns:
|
||||
InterestCalculationResult: 计算结果
|
||||
"""
|
||||
if not self._current_calculator:
|
||||
# 返回默认结果
|
||||
return InterestCalculationResult(
|
||||
success=False,
|
||||
message_id=getattr(message, 'message_id', ''),
|
||||
interest_value=0.3,
|
||||
error_message="没有可用的兴趣值计算组件"
|
||||
)
|
||||
|
||||
# 异步执行计算,避免阻塞
|
||||
future = asyncio.create_task(self._async_calculate(message))
|
||||
return await future
|
||||
|
||||
async def _async_calculate(self, message: "DatabaseMessages") -> InterestCalculationResult:
|
||||
"""异步执行兴趣值计算"""
|
||||
start_time = time.time()
|
||||
self._total_calculations += 1
|
||||
|
||||
try:
|
||||
# 使用组件的安全执行方法
|
||||
result = await self._current_calculator._safe_execute(message)
|
||||
|
||||
if result.success:
|
||||
self._last_calculation_time = time.time()
|
||||
logger.debug(f"兴趣值计算完成: {result.interest_value:.3f} (耗时: {result.calculation_time:.3f}s)")
|
||||
else:
|
||||
self._failed_calculations += 1
|
||||
logger.warning(f"兴趣值计算失败: {result.error_message}")
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
self._failed_calculations += 1
|
||||
logger.error(f"兴趣值计算异常: {e}", exc_info=True)
|
||||
return InterestCalculationResult(
|
||||
success=False,
|
||||
message_id=getattr(message, 'message_id', ''),
|
||||
interest_value=0.0,
|
||||
error_message=f"计算异常: {str(e)}",
|
||||
calculation_time=time.time() - start_time
|
||||
)
|
||||
|
||||
async def _calculation_worker(self):
|
||||
"""计算工作线程(预留用于批量处理)"""
|
||||
while not self._shutdown_event.is_set():
|
||||
try:
|
||||
# 等待计算任务或关闭信号
|
||||
await asyncio.wait_for(
|
||||
self._calculation_queue.get(),
|
||||
timeout=1.0
|
||||
)
|
||||
|
||||
# 处理计算任务
|
||||
# 这里可以实现批量处理逻辑
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
# 超时继续循环
|
||||
continue
|
||||
except asyncio.CancelledError:
|
||||
# 任务被取消,退出循环
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"计算工作线程异常: {e}", exc_info=True)
|
||||
|
||||
def get_current_calculator(self) -> BaseInterestCalculator | None:
|
||||
"""获取当前活跃的兴趣值计算组件"""
|
||||
return self._current_calculator
|
||||
|
||||
def get_statistics(self) -> dict:
|
||||
"""获取管理器统计信息"""
|
||||
success_rate = 1.0 - (self._failed_calculations / max(1, self._total_calculations))
|
||||
|
||||
stats = {
|
||||
"manager_statistics": {
|
||||
"total_calculations": self._total_calculations,
|
||||
"failed_calculations": self._failed_calculations,
|
||||
"success_rate": success_rate,
|
||||
"last_calculation_time": self._last_calculation_time,
|
||||
"current_calculator": self._current_calculator.component_name if self._current_calculator else None
|
||||
}
|
||||
}
|
||||
|
||||
# 添加当前组件的统计信息
|
||||
if self._current_calculator:
|
||||
stats["calculator_statistics"] = self._current_calculator.get_statistics()
|
||||
|
||||
return stats
|
||||
|
||||
async def health_check(self) -> bool:
|
||||
"""健康检查"""
|
||||
if not self._current_calculator:
|
||||
return False
|
||||
|
||||
try:
|
||||
# 检查组件是否还活跃
|
||||
return self._current_calculator.is_enabled
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def has_calculator(self) -> bool:
|
||||
"""检查是否有可用的计算组件"""
|
||||
return self._current_calculator is not None and self._current_calculator.is_enabled
|
||||
|
||||
|
||||
# 全局实例
|
||||
_interest_manager = None
|
||||
|
||||
|
||||
def get_interest_manager() -> InterestManager:
|
||||
"""获取兴趣值管理器实例"""
|
||||
global _interest_manager
|
||||
if _interest_manager is None:
|
||||
_interest_manager = InterestManager()
|
||||
return _interest_manager
|
||||
Reference in New Issue
Block a user