This commit is contained in:
tt-P607
2025-10-18 17:09:35 +08:00
14 changed files with 85 additions and 86 deletions

View File

@@ -7,7 +7,7 @@ import asyncio
import random
import time
from collections import defaultdict, deque
from typing import TYPE_CHECKING, Any, Dict
from typing import TYPE_CHECKING, Any
from src.chat.chatter_manager import ChatterManager
from src.chat.message_receive.chat_stream import ChatStream
@@ -21,7 +21,6 @@ from src.plugin_system.apis.chat_api import get_chat_manager
from .distribution_manager import stream_loop_manager
from .sleep_system.state_manager import SleepState, sleep_state_manager
if TYPE_CHECKING:
pass
@@ -44,8 +43,8 @@ class MessageManager:
self.chatter_manager = ChatterManager(self.action_manager)
# 消息缓存系统 - 直接集成到消息管理器
self.message_caches: Dict[str, deque] = defaultdict(deque) # 每个流的消息缓存
self.stream_processing_status: Dict[str, bool] = defaultdict(bool) # 流的处理状态
self.message_caches: dict[str, deque] = defaultdict(deque) # 每个流的消息缓存
self.stream_processing_status: dict[str, bool] = defaultdict(bool) # 流的处理状态
self.cache_stats = {
"total_cached_messages": 0,
"total_flushed_messages": 0,

View File

@@ -1,10 +1,10 @@
from datetime import datetime, time, timedelta
import random
from typing import Optional, Tuple
from datetime import datetime, timedelta
from src.common.logger import get_logger
from src.config.config import global_config
from src.schedule.schedule_manager import schedule_manager
from .state_manager import SleepState, sleep_state_manager
logger = get_logger("sleep_logic")
@@ -77,7 +77,7 @@ class SleepLogic:
logger.info(f"当前时间 {now.strftime('%H:%M')} 已到达或超过预定起床时间 {wake_up_time.strftime('%H:%M')}")
sleep_state_manager.set_state(SleepState.AWAKE)
def _should_be_sleeping(self, now: datetime) -> Tuple[bool, Optional[datetime]]:
def _should_be_sleeping(self, now: datetime) -> tuple[bool, datetime | None]:
"""
判断在当前时刻,是否应该处于睡眠时间。
@@ -108,10 +108,10 @@ class SleepLogic:
return True, wake_up_time
# 如果当前时间大于入睡时间,说明已经进入睡眠窗口
return True, wake_up_time
return False, None
def _get_fixed_sleep_times(self, now: datetime) -> Tuple[Optional[datetime], Optional[datetime]]:
def _get_fixed_sleep_times(self, now: datetime) -> tuple[datetime | None, datetime | None]:
"""
当使用“固定时间”模式时,从此方法计算睡眠和起床时间。
会加入配置中的随机偏移量,让作息更自然。
@@ -129,7 +129,7 @@ class SleepLogic:
wake_up_t = datetime.strptime(sleep_config.fixed_wake_up_time, "%H:%M").time()
sleep_time = datetime.combine(now.date(), sleep_t) + timedelta(minutes=sleep_offset)
# 如果起床时间比睡觉时间早,说明是第二天
wake_up_day = now.date() + timedelta(days=1) if wake_up_t < sleep_t else now.date()
wake_up_time = datetime.combine(wake_up_day, wake_up_t) + timedelta(minutes=wake_up_offset)
@@ -139,7 +139,7 @@ class SleepLogic:
logger.error(f"解析固定睡眠时间失败: {e}")
return None, None
def _get_sleep_times_from_schedule(self, now: datetime) -> Tuple[Optional[datetime], Optional[datetime]]:
def _get_sleep_times_from_schedule(self, now: datetime) -> tuple[datetime | None, datetime | None]:
"""
当使用“日程表”模式时,从此方法获取睡眠时间。
实现了核心逻辑:
@@ -164,8 +164,8 @@ class SleepLogic:
wake_up_time = None
return sleep_time, wake_up_time
def _get_wakeup_times_from_schedule(self, now: datetime) -> Tuple[Optional[datetime], Optional[datetime]]:
def _get_wakeup_times_from_schedule(self, now: datetime) -> tuple[datetime | None, datetime | None]:
"""
当使用“日程表”模式时,从此方法获取睡眠时间。
实现了核心逻辑:
@@ -192,4 +192,4 @@ class SleepLogic:
# 全局单例
sleep_logic = SleepLogic()
sleep_logic = SleepLogic()

View File

@@ -1,6 +1,6 @@
import enum
from datetime import datetime, timedelta
from typing import Any, Dict, Optional
from typing import Any
from src.common.logger import get_logger
from src.manager.local_store_manager import local_storage
@@ -43,7 +43,7 @@ class SleepStateManager:
"""
初始化状态管理器,定义状态数据结构并从本地加载历史状态。
"""
self.state: Dict[str, Any] = {}
self.state: dict[str, Any] = {}
self._default_state()
self.load_state()
@@ -115,9 +115,9 @@ class SleepStateManager:
def set_state(
self,
new_state: SleepState,
duration_seconds: Optional[float] = None,
sleep_start: Optional[datetime] = None,
wake_up: Optional[datetime] = None,
duration_seconds: float | None = None,
sleep_start: datetime | None = None,
wake_up: datetime | None = None,
):
"""
核心函数:切换到新的睡眠状态,并更新相关的状态数据。
@@ -132,7 +132,7 @@ class SleepStateManager:
if new_state == SleepState.AWAKE:
self._default_state() # 醒来时重置所有状态
self.state["state"] = SleepState.AWAKE # 确保状态正确
elif new_state == SleepState.SLEEPING:
self.state["sleep_start_time"] = (sleep_start or datetime.now()).isoformat()
self.state["wake_up_time"] = wake_up.isoformat() if wake_up else None
@@ -153,7 +153,7 @@ class SleepStateManager:
self.state["last_checked"] = datetime.now().isoformat()
self.save_state()
def get_wake_up_time(self) -> Optional[datetime]:
def get_wake_up_time(self) -> datetime | None:
"""获取预定的起床时间,如果已设置的话。"""
wake_up_str = self.state.get("wake_up_time")
if wake_up_str:
@@ -163,7 +163,7 @@ class SleepStateManager:
return None
return None
def get_sleep_start_time(self) -> Optional[datetime]:
def get_sleep_start_time(self) -> datetime | None:
"""获取本次睡眠的开始时间,如果已设置的话。"""
sleep_start_str = self.state.get("sleep_start_time")
if sleep_start_str:
@@ -187,4 +187,4 @@ class SleepStateManager:
# 全局单例
sleep_state_manager = SleepStateManager()
sleep_state_manager = SleepStateManager()

View File

@@ -1,5 +1,6 @@
from src.common.logger import get_logger
from src.manager.async_task_manager import AsyncTask, async_task_manager
from .sleep_logic import sleep_logic
logger = get_logger("sleep_tasks")

View File

@@ -11,7 +11,7 @@ from src.common.data_models.message_manager_data_model import StreamContext
from src.common.logger import get_logger
from src.config.config import global_config, model_config
from src.llm_models.utils_model import LLMRequest
from src.plugin_system.base.component_types import ActionActivationType, ActionInfo
from src.plugin_system.base.component_types import ActionInfo
from src.plugin_system.core.global_announcement_manager import global_announcement_manager
if TYPE_CHECKING:
@@ -207,18 +207,18 @@ class ActionModifier:
List[Tuple[str, str]]: 需要停用的 (action_name, reason) 元组列表
"""
deactivated_actions = []
# 获取 Action 类注册表
from src.plugin_system.core.component_registry import component_registry
from src.plugin_system.base.component_types import ComponentType
from src.plugin_system.core.component_registry import component_registry
actions_to_check = list(actions_with_info.items())
random.shuffle(actions_to_check)
# 创建并行任务列表
activation_tasks = []
task_action_names = []
for action_name, action_info in actions_to_check:
# 获取 Action 类
action_class = component_registry.get_component_class(action_name, ComponentType.ACTION)
@@ -226,7 +226,7 @@ class ActionModifier:
logger.warning(f"{self.log_prefix}未找到 Action 类: {action_name},默认不激活")
deactivated_actions.append((action_name, "未找到 Action 类"))
continue
# 创建一个临时实例来调用 go_activate 方法
# 注意:这里只是为了调用 go_activate不需要完整的初始化
try:
@@ -237,24 +237,24 @@ class ActionModifier:
action_instance.log_prefix = self.log_prefix
# 设置聊天内容,用于激活判断
action_instance._activation_chat_content = chat_content
# 调用 go_activate 方法(不再需要传入 chat_content
task = action_instance.go_activate(
llm_judge_model=self.llm_judge,
)
activation_tasks.append(task)
task_action_names.append(action_name)
except Exception as e:
logger.error(f"{self.log_prefix}创建 Action 实例 {action_name} 失败: {e}")
deactivated_actions.append((action_name, f"创建实例失败: {e}"))
# 并行执行所有激活判断
if activation_tasks:
logger.debug(f"{self.log_prefix}并行执行激活判断,任务数: {len(activation_tasks)}")
try:
task_results = await asyncio.gather(*activation_tasks, return_exceptions=True)
# 处理结果
for action_name, result in zip(task_action_names, task_results, strict=False):
if isinstance(result, Exception):
@@ -267,7 +267,7 @@ class ActionModifier:
else:
# go_activate 返回 True激活
logger.debug(f"{self.log_prefix}激活动作: {action_name}")
except Exception as e:
logger.error(f"{self.log_prefix}并行激活判断失败: {e}")
# 如果并行执行失败,为所有任务默认不激活

View File

@@ -298,14 +298,14 @@ def random_remove_punctuation(text: str) -> str:
def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
"""识别并保护数学公式和代码块,返回处理后的文本和映射"""
placeholder_map = {}
# 第一层防护优先保护标准Markdown格式
# 使用 re.S 来让 . 匹配换行符
markdown_patterns = {
'code': r"```.*?```",
'math': r"\$\$.*?\$\$",
"code": r"```.*?```",
"math": r"\$\$.*?\$\$",
}
placeholder_idx = 0
for block_type, pattern in markdown_patterns.items():
matches = re.findall(pattern, text, re.S)
@@ -318,7 +318,7 @@ def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
# 第二层防护:保护非标准的、可能是公式或代码的片段
# 这个正则表达式寻找连续5个以上的、主要由非中文字符组成的片段
general_pattern = r"(?:[a-zA-Z0-9\s.,;:(){}\[\]_+\-*/=<>^|&%?!'\"√²³ⁿ∑∫≠≥≤]){5,}"
# 为了避免与已保护的占位符冲突,我们在剩余的文本上进行查找
# 这是一个简化的处理,更稳妥的方式是分段查找,但目前这样足以应对多数情况
try:
@@ -327,7 +327,7 @@ def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
# 避免将包含占位符的片段再次保护
if "__SPECIAL_" in match:
continue
placeholder = f"__SPECIAL_GENERAL_{placeholder_idx}__"
text = text.replace(match, placeholder, 1)
placeholder_map[placeholder] = match
@@ -352,23 +352,23 @@ def protect_quoted_content(text: str) -> tuple[str, dict[str, str]]:
placeholder_map = {}
# 匹配中英文单双引号,使用非贪婪模式
quote_pattern = re.compile(r'(".*?")|(\'.*?\')|(“.*?”)|(.*?)')
matches = quote_pattern.finditer(text)
# 为了避免替换时索引错乱,我们从后往前替换
# finditer 找到的是 match 对象,我们需要转换为 list 来反转
match_list = list(matches)
for idx, match in enumerate(reversed(match_list)):
original_quoted_text = match.group(0)
placeholder = f"__QUOTE_{len(match_list) - 1 - idx}__"
# 直接在原始文本上操作,替换 match 对象的 span
start, end = match.span()
text = text[:start] + placeholder + text[end:]
placeholder_map[placeholder] = original_quoted_text
return text, placeholder_map
@@ -389,13 +389,13 @@ def process_llm_response(text: str, enable_splitter: bool = True, enable_chinese
# --- 三层防护系统 ---
# 第一层:保护颜文字
protected_text, kaomoji_mapping = protect_kaomoji(text) if global_config.response_splitter.enable_kaomoji_protection else (text, {})
# 第二层:保护引号内容
protected_text, quote_mapping = protect_quoted_content(protected_text)
# 第三层:保护数学公式和代码块
protected_text, special_blocks_mapping = protect_special_blocks(protected_text)
# 提取被 () 或 [] 或 ()包裹且包含中文的内容
pattern = re.compile(r"[(\[](?=.*[一-鿿]).*?[)\]]")
_extracted_contents = pattern.findall(protected_text)
@@ -412,7 +412,7 @@ def process_llm_response(text: str, enable_splitter: bool = True, enable_chinese
# 对清理后的文本进行进一步处理
max_sentence_num = global_config.response_splitter.max_sentence_num
# --- 移除总长度检查 ---
# 原有的总长度检查会导致长回复被直接丢弃,现已移除,由后续的智能合并逻辑处理。
# max_length = global_config.response_splitter.max_length * 2
@@ -472,7 +472,7 @@ def process_llm_response(text: str, enable_splitter: bool = True, enable_chinese
break
# 寻找最短的相邻句子对
min_len = float('inf')
min_len = float("inf")
merge_idx = -1
for i in range(len(sentences) - 1):
combined_len = len(sentences[i]) + len(sentences[i+1])
@@ -488,7 +488,7 @@ def process_llm_response(text: str, enable_splitter: bool = True, enable_chinese
sentences[merge_idx] = merged_sentence
# 删除后一个句子
del sentences[merge_idx + 1]
logger.info(f"智能合并完成,最终消息数量: {len(sentences)}")
# if extracted_contents: