ruff ci
This commit is contained in:
@@ -3,7 +3,6 @@ import random
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from src.plugin_system import (
|
from src.plugin_system import (
|
||||||
ActionActivationType,
|
|
||||||
BaseAction,
|
BaseAction,
|
||||||
BaseEventHandler,
|
BaseEventHandler,
|
||||||
BasePlugin,
|
BasePlugin,
|
||||||
@@ -133,11 +132,11 @@ class CombinedActivationExampleAction(BaseAction):
|
|||||||
# 先尝试随机激活
|
# 先尝试随机激活
|
||||||
if await self._random_activation(0.2):
|
if await self._random_activation(0.2):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# 如果随机未激活,尝试关键词匹配
|
# 如果随机未激活,尝试关键词匹配
|
||||||
if await self._keyword_match(chat_content, ["表情", "emoji", "😊"], case_sensitive=False):
|
if await self._keyword_match(chat_content, ["表情", "emoji", "😊"], case_sensitive=False):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# 都不满足则不激活
|
# 都不满足则不激活
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import orjson
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import orjson
|
||||||
|
|
||||||
# 将脚本所在的目录添加到系统路径中,以便导入项目模块
|
# 将脚本所在的目录添加到系统路径中,以便导入项目模块
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
@@ -14,7 +15,7 @@ def convert_and_copy_plugin(plugin_dir: Path, output_dir: Path):
|
|||||||
"""
|
"""
|
||||||
转换插件的 _manifest.json 文件,并将其整个目录复制到输出位置。
|
转换插件的 _manifest.json 文件,并将其整个目录复制到输出位置。
|
||||||
"""
|
"""
|
||||||
manifest_path = plugin_dir / '_manifest.json'
|
manifest_path = plugin_dir / "_manifest.json"
|
||||||
if not manifest_path.is_file():
|
if not manifest_path.is_file():
|
||||||
logger.warning(f"在目录 '{plugin_dir.name}' 中未找到 '_manifest.json',已跳过。")
|
logger.warning(f"在目录 '{plugin_dir.name}' 中未找到 '_manifest.json',已跳过。")
|
||||||
return
|
return
|
||||||
@@ -28,16 +29,16 @@ def convert_and_copy_plugin(plugin_dir: Path, output_dir: Path):
|
|||||||
logger.info(f"已将插件 '{plugin_dir.name}' 完整复制到 '{target_plugin_dir}'")
|
logger.info(f"已将插件 '{plugin_dir.name}' 完整复制到 '{target_plugin_dir}'")
|
||||||
|
|
||||||
# 2. 读取 manifest 并生成 __init__.py 内容
|
# 2. 读取 manifest 并生成 __init__.py 内容
|
||||||
with open(manifest_path, 'rb') as f:
|
with open(manifest_path, "rb") as f:
|
||||||
manifest = orjson.loads(f.read())
|
manifest = orjson.loads(f.read())
|
||||||
|
|
||||||
plugin_name = manifest.get('name', 'Unknown Plugin')
|
plugin_name = manifest.get("name", "Unknown Plugin")
|
||||||
description = manifest.get('description', 'No description provided.')
|
description = manifest.get("description", "No description provided.")
|
||||||
version = manifest.get('version', '0.0.0')
|
version = manifest.get("version", "0.0.0")
|
||||||
author = manifest.get('author', {}).get('name', 'Unknown Author')
|
author = manifest.get("author", {}).get("name", "Unknown Author")
|
||||||
license_type = manifest.get('license', 'N/A')
|
license_type = manifest.get("license", "N/A")
|
||||||
|
|
||||||
meta_template = f'''from src.plugin_system.base.plugin_metadata import PluginMetadata
|
meta_template = f"""from src.plugin_system.base.plugin_metadata import PluginMetadata
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
__plugin_meta__ = PluginMetadata(
|
||||||
name="{plugin_name}",
|
name="{plugin_name}",
|
||||||
@@ -47,14 +48,14 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
author="{author}",
|
author="{author}",
|
||||||
license="{license_type}",
|
license="{license_type}",
|
||||||
)
|
)
|
||||||
'''
|
"""
|
||||||
# 3. 在复制后的目录中创建或覆盖 __init__.py
|
# 3. 在复制后的目录中创建或覆盖 __init__.py
|
||||||
output_init_path = target_plugin_dir / '__init__.py'
|
output_init_path = target_plugin_dir / "__init__.py"
|
||||||
with open(output_init_path, 'w', encoding='utf-8') as f:
|
with open(output_init_path, "w", encoding="utf-8") as f:
|
||||||
f.write(meta_template)
|
f.write(meta_template)
|
||||||
|
|
||||||
# 4. 删除复制后的 _manifest.json
|
# 4. 删除复制后的 _manifest.json
|
||||||
copied_manifest_path = target_plugin_dir / '_manifest.json'
|
copied_manifest_path = target_plugin_dir / "_manifest.json"
|
||||||
if copied_manifest_path.is_file():
|
if copied_manifest_path.is_file():
|
||||||
copied_manifest_path.unlink()
|
copied_manifest_path.unlink()
|
||||||
|
|
||||||
@@ -89,8 +90,8 @@ def main():
|
|||||||
if item.is_dir():
|
if item.is_dir():
|
||||||
logger.info(f"发现插件目录: '{item.name}',开始处理...")
|
logger.info(f"发现插件目录: '{item.name}',开始处理...")
|
||||||
convert_and_copy_plugin(item, output_path)
|
convert_and_copy_plugin(item, output_path)
|
||||||
|
|
||||||
logger.info("所有插件处理完成。")
|
logger.info("所有插件处理完成。")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import asyncio
|
|||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
from collections import defaultdict, deque
|
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.chatter_manager import ChatterManager
|
||||||
from src.chat.message_receive.chat_stream import ChatStream
|
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 .distribution_manager import stream_loop_manager
|
||||||
from .sleep_system.state_manager import SleepState, sleep_state_manager
|
from .sleep_system.state_manager import SleepState, sleep_state_manager
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -44,8 +43,8 @@ class MessageManager:
|
|||||||
self.chatter_manager = ChatterManager(self.action_manager)
|
self.chatter_manager = ChatterManager(self.action_manager)
|
||||||
|
|
||||||
# 消息缓存系统 - 直接集成到消息管理器
|
# 消息缓存系统 - 直接集成到消息管理器
|
||||||
self.message_caches: Dict[str, deque] = defaultdict(deque) # 每个流的消息缓存
|
self.message_caches: dict[str, deque] = defaultdict(deque) # 每个流的消息缓存
|
||||||
self.stream_processing_status: Dict[str, bool] = defaultdict(bool) # 流的处理状态
|
self.stream_processing_status: dict[str, bool] = defaultdict(bool) # 流的处理状态
|
||||||
self.cache_stats = {
|
self.cache_stats = {
|
||||||
"total_cached_messages": 0,
|
"total_cached_messages": 0,
|
||||||
"total_flushed_messages": 0,
|
"total_flushed_messages": 0,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from datetime import datetime, time, timedelta
|
|
||||||
import random
|
import random
|
||||||
from typing import Optional, Tuple
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
from src.schedule.schedule_manager import schedule_manager
|
from src.schedule.schedule_manager import schedule_manager
|
||||||
|
|
||||||
from .state_manager import SleepState, sleep_state_manager
|
from .state_manager import SleepState, sleep_state_manager
|
||||||
|
|
||||||
logger = get_logger("sleep_logic")
|
logger = get_logger("sleep_logic")
|
||||||
@@ -77,7 +77,7 @@ class SleepLogic:
|
|||||||
logger.info(f"当前时间 {now.strftime('%H:%M')} 已到达或超过预定起床时间 {wake_up_time.strftime('%H:%M')}。")
|
logger.info(f"当前时间 {now.strftime('%H:%M')} 已到达或超过预定起床时间 {wake_up_time.strftime('%H:%M')}。")
|
||||||
sleep_state_manager.set_state(SleepState.AWAKE)
|
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 True, wake_up_time
|
return True, wake_up_time
|
||||||
|
|
||||||
return False, None
|
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()
|
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)
|
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_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)
|
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}")
|
logger.error(f"解析固定睡眠时间失败: {e}")
|
||||||
return None, None
|
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
|
wake_up_time = None
|
||||||
|
|
||||||
return sleep_time, wake_up_time
|
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()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import enum
|
import enum
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.manager.local_store_manager import local_storage
|
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._default_state()
|
||||||
self.load_state()
|
self.load_state()
|
||||||
|
|
||||||
@@ -115,9 +115,9 @@ class SleepStateManager:
|
|||||||
def set_state(
|
def set_state(
|
||||||
self,
|
self,
|
||||||
new_state: SleepState,
|
new_state: SleepState,
|
||||||
duration_seconds: Optional[float] = None,
|
duration_seconds: float | None = None,
|
||||||
sleep_start: Optional[datetime] = None,
|
sleep_start: datetime | None = None,
|
||||||
wake_up: Optional[datetime] = None,
|
wake_up: datetime | None = None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
核心函数:切换到新的睡眠状态,并更新相关的状态数据。
|
核心函数:切换到新的睡眠状态,并更新相关的状态数据。
|
||||||
@@ -132,7 +132,7 @@ class SleepStateManager:
|
|||||||
if new_state == SleepState.AWAKE:
|
if new_state == SleepState.AWAKE:
|
||||||
self._default_state() # 醒来时重置所有状态
|
self._default_state() # 醒来时重置所有状态
|
||||||
self.state["state"] = SleepState.AWAKE # 确保状态正确
|
self.state["state"] = SleepState.AWAKE # 确保状态正确
|
||||||
|
|
||||||
elif new_state == SleepState.SLEEPING:
|
elif new_state == SleepState.SLEEPING:
|
||||||
self.state["sleep_start_time"] = (sleep_start or datetime.now()).isoformat()
|
self.state["sleep_start_time"] = (sleep_start or datetime.now()).isoformat()
|
||||||
self.state["wake_up_time"] = wake_up.isoformat() if wake_up else None
|
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.state["last_checked"] = datetime.now().isoformat()
|
||||||
self.save_state()
|
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")
|
wake_up_str = self.state.get("wake_up_time")
|
||||||
if wake_up_str:
|
if wake_up_str:
|
||||||
@@ -163,7 +163,7 @@ class SleepStateManager:
|
|||||||
return None
|
return None
|
||||||
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")
|
sleep_start_str = self.state.get("sleep_start_time")
|
||||||
if sleep_start_str:
|
if sleep_start_str:
|
||||||
@@ -187,4 +187,4 @@ class SleepStateManager:
|
|||||||
|
|
||||||
|
|
||||||
# 全局单例
|
# 全局单例
|
||||||
sleep_state_manager = SleepStateManager()
|
sleep_state_manager = SleepStateManager()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.manager.async_task_manager import AsyncTask, async_task_manager
|
from src.manager.async_task_manager import AsyncTask, async_task_manager
|
||||||
|
|
||||||
from .sleep_logic import sleep_logic
|
from .sleep_logic import sleep_logic
|
||||||
|
|
||||||
logger = get_logger("sleep_tasks")
|
logger = get_logger("sleep_tasks")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from src.common.data_models.message_manager_data_model import StreamContext
|
|||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.config.config import global_config, model_config
|
from src.config.config import global_config, model_config
|
||||||
from src.llm_models.utils_model import LLMRequest
|
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
|
from src.plugin_system.core.global_announcement_manager import global_announcement_manager
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -207,18 +207,18 @@ class ActionModifier:
|
|||||||
List[Tuple[str, str]]: 需要停用的 (action_name, reason) 元组列表
|
List[Tuple[str, str]]: 需要停用的 (action_name, reason) 元组列表
|
||||||
"""
|
"""
|
||||||
deactivated_actions = []
|
deactivated_actions = []
|
||||||
|
|
||||||
# 获取 Action 类注册表
|
# 获取 Action 类注册表
|
||||||
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
|
||||||
|
from src.plugin_system.core.component_registry import component_registry
|
||||||
|
|
||||||
actions_to_check = list(actions_with_info.items())
|
actions_to_check = list(actions_with_info.items())
|
||||||
random.shuffle(actions_to_check)
|
random.shuffle(actions_to_check)
|
||||||
|
|
||||||
# 创建并行任务列表
|
# 创建并行任务列表
|
||||||
activation_tasks = []
|
activation_tasks = []
|
||||||
task_action_names = []
|
task_action_names = []
|
||||||
|
|
||||||
for action_name, action_info in actions_to_check:
|
for action_name, action_info in actions_to_check:
|
||||||
# 获取 Action 类
|
# 获取 Action 类
|
||||||
action_class = component_registry.get_component_class(action_name, ComponentType.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},默认不激活")
|
logger.warning(f"{self.log_prefix}未找到 Action 类: {action_name},默认不激活")
|
||||||
deactivated_actions.append((action_name, "未找到 Action 类"))
|
deactivated_actions.append((action_name, "未找到 Action 类"))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 创建一个临时实例来调用 go_activate 方法
|
# 创建一个临时实例来调用 go_activate 方法
|
||||||
# 注意:这里只是为了调用 go_activate,不需要完整的初始化
|
# 注意:这里只是为了调用 go_activate,不需要完整的初始化
|
||||||
try:
|
try:
|
||||||
@@ -237,24 +237,24 @@ class ActionModifier:
|
|||||||
action_instance.log_prefix = self.log_prefix
|
action_instance.log_prefix = self.log_prefix
|
||||||
# 设置聊天内容,用于激活判断
|
# 设置聊天内容,用于激活判断
|
||||||
action_instance._activation_chat_content = chat_content
|
action_instance._activation_chat_content = chat_content
|
||||||
|
|
||||||
# 调用 go_activate 方法(不再需要传入 chat_content)
|
# 调用 go_activate 方法(不再需要传入 chat_content)
|
||||||
task = action_instance.go_activate(
|
task = action_instance.go_activate(
|
||||||
llm_judge_model=self.llm_judge,
|
llm_judge_model=self.llm_judge,
|
||||||
)
|
)
|
||||||
activation_tasks.append(task)
|
activation_tasks.append(task)
|
||||||
task_action_names.append(action_name)
|
task_action_names.append(action_name)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.log_prefix}创建 Action 实例 {action_name} 失败: {e}")
|
logger.error(f"{self.log_prefix}创建 Action 实例 {action_name} 失败: {e}")
|
||||||
deactivated_actions.append((action_name, f"创建实例失败: {e}"))
|
deactivated_actions.append((action_name, f"创建实例失败: {e}"))
|
||||||
|
|
||||||
# 并行执行所有激活判断
|
# 并行执行所有激活判断
|
||||||
if activation_tasks:
|
if activation_tasks:
|
||||||
logger.debug(f"{self.log_prefix}并行执行激活判断,任务数: {len(activation_tasks)}")
|
logger.debug(f"{self.log_prefix}并行执行激活判断,任务数: {len(activation_tasks)}")
|
||||||
try:
|
try:
|
||||||
task_results = await asyncio.gather(*activation_tasks, return_exceptions=True)
|
task_results = await asyncio.gather(*activation_tasks, return_exceptions=True)
|
||||||
|
|
||||||
# 处理结果
|
# 处理结果
|
||||||
for action_name, result in zip(task_action_names, task_results, strict=False):
|
for action_name, result in zip(task_action_names, task_results, strict=False):
|
||||||
if isinstance(result, Exception):
|
if isinstance(result, Exception):
|
||||||
@@ -267,7 +267,7 @@ class ActionModifier:
|
|||||||
else:
|
else:
|
||||||
# go_activate 返回 True,激活
|
# go_activate 返回 True,激活
|
||||||
logger.debug(f"{self.log_prefix}激活动作: {action_name}")
|
logger.debug(f"{self.log_prefix}激活动作: {action_name}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.log_prefix}并行激活判断失败: {e}")
|
logger.error(f"{self.log_prefix}并行激活判断失败: {e}")
|
||||||
# 如果并行执行失败,为所有任务默认不激活
|
# 如果并行执行失败,为所有任务默认不激活
|
||||||
|
|||||||
@@ -298,14 +298,14 @@ def random_remove_punctuation(text: str) -> str:
|
|||||||
def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
|
def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
|
||||||
"""识别并保护数学公式和代码块,返回处理后的文本和映射"""
|
"""识别并保护数学公式和代码块,返回处理后的文本和映射"""
|
||||||
placeholder_map = {}
|
placeholder_map = {}
|
||||||
|
|
||||||
# 第一层防护:优先保护标准Markdown格式
|
# 第一层防护:优先保护标准Markdown格式
|
||||||
# 使用 re.S 来让 . 匹配换行符
|
# 使用 re.S 来让 . 匹配换行符
|
||||||
markdown_patterns = {
|
markdown_patterns = {
|
||||||
'code': r"```.*?```",
|
"code": r"```.*?```",
|
||||||
'math': r"\$\$.*?\$\$",
|
"math": r"\$\$.*?\$\$",
|
||||||
}
|
}
|
||||||
|
|
||||||
placeholder_idx = 0
|
placeholder_idx = 0
|
||||||
for block_type, pattern in markdown_patterns.items():
|
for block_type, pattern in markdown_patterns.items():
|
||||||
matches = re.findall(pattern, text, re.S)
|
matches = re.findall(pattern, text, re.S)
|
||||||
@@ -318,7 +318,7 @@ def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
|
|||||||
# 第二层防护:保护非标准的、可能是公式或代码的片段
|
# 第二层防护:保护非标准的、可能是公式或代码的片段
|
||||||
# 这个正则表达式寻找连续5个以上的、主要由非中文字符组成的片段
|
# 这个正则表达式寻找连续5个以上的、主要由非中文字符组成的片段
|
||||||
general_pattern = r"(?:[a-zA-Z0-9\s.,;:(){}\[\]_+\-*/=<>^|&%?!'\"√²³ⁿ∑∫≠≥≤]){5,}"
|
general_pattern = r"(?:[a-zA-Z0-9\s.,;:(){}\[\]_+\-*/=<>^|&%?!'\"√²³ⁿ∑∫≠≥≤]){5,}"
|
||||||
|
|
||||||
# 为了避免与已保护的占位符冲突,我们在剩余的文本上进行查找
|
# 为了避免与已保护的占位符冲突,我们在剩余的文本上进行查找
|
||||||
# 这是一个简化的处理,更稳妥的方式是分段查找,但目前这样足以应对多数情况
|
# 这是一个简化的处理,更稳妥的方式是分段查找,但目前这样足以应对多数情况
|
||||||
try:
|
try:
|
||||||
@@ -327,7 +327,7 @@ def protect_special_blocks(text: str) -> tuple[str, dict[str, str]]:
|
|||||||
# 避免将包含占位符的片段再次保护
|
# 避免将包含占位符的片段再次保护
|
||||||
if "__SPECIAL_" in match:
|
if "__SPECIAL_" in match:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
placeholder = f"__SPECIAL_GENERAL_{placeholder_idx}__"
|
placeholder = f"__SPECIAL_GENERAL_{placeholder_idx}__"
|
||||||
text = text.replace(match, placeholder, 1)
|
text = text.replace(match, placeholder, 1)
|
||||||
placeholder_map[placeholder] = match
|
placeholder_map[placeholder] = match
|
||||||
@@ -352,23 +352,23 @@ def protect_quoted_content(text: str) -> tuple[str, dict[str, str]]:
|
|||||||
placeholder_map = {}
|
placeholder_map = {}
|
||||||
# 匹配中英文单双引号,使用非贪婪模式
|
# 匹配中英文单双引号,使用非贪婪模式
|
||||||
quote_pattern = re.compile(r'(".*?")|(\'.*?\')|(“.*?”)|(‘.*?’)')
|
quote_pattern = re.compile(r'(".*?")|(\'.*?\')|(“.*?”)|(‘.*?’)')
|
||||||
|
|
||||||
matches = quote_pattern.finditer(text)
|
matches = quote_pattern.finditer(text)
|
||||||
|
|
||||||
# 为了避免替换时索引错乱,我们从后往前替换
|
# 为了避免替换时索引错乱,我们从后往前替换
|
||||||
# finditer 找到的是 match 对象,我们需要转换为 list 来反转
|
# finditer 找到的是 match 对象,我们需要转换为 list 来反转
|
||||||
match_list = list(matches)
|
match_list = list(matches)
|
||||||
|
|
||||||
for idx, match in enumerate(reversed(match_list)):
|
for idx, match in enumerate(reversed(match_list)):
|
||||||
original_quoted_text = match.group(0)
|
original_quoted_text = match.group(0)
|
||||||
placeholder = f"__QUOTE_{len(match_list) - 1 - idx}__"
|
placeholder = f"__QUOTE_{len(match_list) - 1 - idx}__"
|
||||||
|
|
||||||
# 直接在原始文本上操作,替换 match 对象的 span
|
# 直接在原始文本上操作,替换 match 对象的 span
|
||||||
start, end = match.span()
|
start, end = match.span()
|
||||||
text = text[:start] + placeholder + text[end:]
|
text = text[:start] + placeholder + text[end:]
|
||||||
|
|
||||||
placeholder_map[placeholder] = original_quoted_text
|
placeholder_map[placeholder] = original_quoted_text
|
||||||
|
|
||||||
return text, placeholder_map
|
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, 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, quote_mapping = protect_quoted_content(protected_text)
|
||||||
|
|
||||||
# 第三层:保护数学公式和代码块
|
# 第三层:保护数学公式和代码块
|
||||||
protected_text, special_blocks_mapping = protect_special_blocks(protected_text)
|
protected_text, special_blocks_mapping = protect_special_blocks(protected_text)
|
||||||
|
|
||||||
# 提取被 () 或 [] 或 ()包裹且包含中文的内容
|
# 提取被 () 或 [] 或 ()包裹且包含中文的内容
|
||||||
pattern = re.compile(r"[(\[(](?=.*[一-鿿]).*?[)\])]")
|
pattern = re.compile(r"[(\[(](?=.*[一-鿿]).*?[)\])]")
|
||||||
_extracted_contents = pattern.findall(protected_text)
|
_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_sentence_num = global_config.response_splitter.max_sentence_num
|
||||||
|
|
||||||
# --- 移除总长度检查 ---
|
# --- 移除总长度检查 ---
|
||||||
# 原有的总长度检查会导致长回复被直接丢弃,现已移除,由后续的智能合并逻辑处理。
|
# 原有的总长度检查会导致长回复被直接丢弃,现已移除,由后续的智能合并逻辑处理。
|
||||||
# max_length = global_config.response_splitter.max_length * 2
|
# 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
|
break
|
||||||
|
|
||||||
# 寻找最短的相邻句子对
|
# 寻找最短的相邻句子对
|
||||||
min_len = float('inf')
|
min_len = float("inf")
|
||||||
merge_idx = -1
|
merge_idx = -1
|
||||||
for i in range(len(sentences) - 1):
|
for i in range(len(sentences) - 1):
|
||||||
combined_len = len(sentences[i]) + len(sentences[i+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
|
sentences[merge_idx] = merged_sentence
|
||||||
# 删除后一个句子
|
# 删除后一个句子
|
||||||
del sentences[merge_idx + 1]
|
del sentences[merge_idx + 1]
|
||||||
|
|
||||||
logger.info(f"智能合并完成,最终消息数量: {len(sentences)}")
|
logger.info(f"智能合并完成,最终消息数量: {len(sentences)}")
|
||||||
|
|
||||||
# if extracted_contents:
|
# if extracted_contents:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from rich.traceback import install
|
|||||||
|
|
||||||
from src.chat.emoji_system.emoji_manager import get_emoji_manager
|
from src.chat.emoji_system.emoji_manager import get_emoji_manager
|
||||||
from src.chat.memory_system.memory_manager import memory_manager
|
from src.chat.memory_system.memory_manager import memory_manager
|
||||||
|
from src.chat.message_manager.sleep_system.tasks import start_sleep_system_tasks
|
||||||
from src.chat.message_receive.bot import chat_bot
|
from src.chat.message_receive.bot import chat_bot
|
||||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||||
from src.chat.utils.statistic import OnlineTimeRecordTask, StatisticOutputTask
|
from src.chat.utils.statistic import OnlineTimeRecordTask, StatisticOutputTask
|
||||||
@@ -29,7 +30,6 @@ from src.plugin_system.core.event_manager import event_manager
|
|||||||
from src.plugin_system.core.plugin_manager import plugin_manager
|
from src.plugin_system.core.plugin_manager import plugin_manager
|
||||||
from src.schedule.monthly_plan_manager import monthly_plan_manager
|
from src.schedule.monthly_plan_manager import monthly_plan_manager
|
||||||
from src.schedule.schedule_manager import schedule_manager
|
from src.schedule.schedule_manager import schedule_manager
|
||||||
from src.chat.message_manager.sleep_system.tasks import start_sleep_system_tasks
|
|
||||||
|
|
||||||
# 插件系统现在使用统一的插件加载器
|
# 插件系统现在使用统一的插件加载器
|
||||||
install(extra_lines=3)
|
install(extra_lines=3)
|
||||||
|
|||||||
@@ -615,15 +615,15 @@ class BaseAction(ABC):
|
|||||||
"""
|
"""
|
||||||
# 尝试从不同的实例属性中获取聊天内容
|
# 尝试从不同的实例属性中获取聊天内容
|
||||||
# 优先级:_activation_chat_content > action_data['chat_content'] > ""
|
# 优先级:_activation_chat_content > action_data['chat_content'] > ""
|
||||||
|
|
||||||
# 1. 如果有专门设置的激活用聊天内容(由 ActionModifier 设置)
|
# 1. 如果有专门设置的激活用聊天内容(由 ActionModifier 设置)
|
||||||
if hasattr(self, '_activation_chat_content'):
|
if hasattr(self, "_activation_chat_content"):
|
||||||
return getattr(self, '_activation_chat_content', "")
|
return getattr(self, "_activation_chat_content", "")
|
||||||
|
|
||||||
# 2. 尝试从 action_data 中获取
|
# 2. 尝试从 action_data 中获取
|
||||||
if hasattr(self, 'action_data') and isinstance(self.action_data, dict):
|
if hasattr(self, "action_data") and isinstance(self.action_data, dict):
|
||||||
return self.action_data.get('chat_content', "")
|
return self.action_data.get("chat_content", "")
|
||||||
|
|
||||||
# 3. 默认返回空字符串
|
# 3. 默认返回空字符串
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@@ -729,7 +729,7 @@ class BaseAction(ABC):
|
|||||||
|
|
||||||
# 自动获取聊天内容
|
# 自动获取聊天内容
|
||||||
chat_content = self._get_chat_content()
|
chat_content = self._get_chat_content()
|
||||||
|
|
||||||
search_text = chat_content
|
search_text = chat_content
|
||||||
if not case_sensitive:
|
if not case_sensitive:
|
||||||
search_text = search_text.lower()
|
search_text = search_text.lower()
|
||||||
@@ -786,7 +786,7 @@ class BaseAction(ABC):
|
|||||||
try:
|
try:
|
||||||
# 自动获取聊天内容
|
# 自动获取聊天内容
|
||||||
chat_content = self._get_chat_content()
|
chat_content = self._get_chat_content()
|
||||||
|
|
||||||
# 如果没有提供 LLM 模型,创建一个默认的
|
# 如果没有提供 LLM 模型,创建一个默认的
|
||||||
if llm_judge_model is None:
|
if llm_judge_model is None:
|
||||||
from src.config.config import model_config
|
from src.config.config import model_config
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ class ActionInfo(ComponentInfo):
|
|||||||
) # 动作参数与描述,例如 {"param1": "描述1", "param2": "描述2"}
|
) # 动作参数与描述,例如 {"param1": "描述1", "param2": "描述2"}
|
||||||
action_require: list[str] = field(default_factory=list) # 动作需求说明
|
action_require: list[str] = field(default_factory=list) # 动作需求说明
|
||||||
associated_types: list[str] = field(default_factory=list) # 关联的消息类型
|
associated_types: list[str] = field(default_factory=list) # 关联的消息类型
|
||||||
|
|
||||||
# ==================================================================================
|
# ==================================================================================
|
||||||
# 激活类型相关字段(已废弃,建议使用 go_activate() 方法)
|
# 激活类型相关字段(已废弃,建议使用 go_activate() 方法)
|
||||||
# 保留这些字段是为了向后兼容,BaseAction.go_activate() 的默认实现会使用这些字段
|
# 保留这些字段是为了向后兼容,BaseAction.go_activate() 的默认实现会使用这些字段
|
||||||
@@ -155,7 +155,7 @@ class ActionInfo(ComponentInfo):
|
|||||||
llm_judge_prompt: str = "" # 已废弃,建议在 go_activate() 中使用 _llm_judge_activation()
|
llm_judge_prompt: str = "" # 已废弃,建议在 go_activate() 中使用 _llm_judge_activation()
|
||||||
activation_keywords: list[str] = field(default_factory=list) # 已废弃,建议在 go_activate() 中使用 _keyword_match()
|
activation_keywords: list[str] = field(default_factory=list) # 已废弃,建议在 go_activate() 中使用 _keyword_match()
|
||||||
keyword_case_sensitive: bool = False # 已废弃
|
keyword_case_sensitive: bool = False # 已废弃
|
||||||
|
|
||||||
# 模式和并行设置
|
# 模式和并行设置
|
||||||
mode_enable: ChatMode = ChatMode.ALL
|
mode_enable: ChatMode = ChatMode.ALL
|
||||||
parallel_action: bool = False
|
parallel_action: bool = False
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ class ChatterPlanFilter:
|
|||||||
|
|
||||||
schedule_block = ""
|
schedule_block = ""
|
||||||
# 优先检查是否被吵醒
|
# 优先检查是否被吵醒
|
||||||
from src.chat.message_manager.message_manager import message_manager
|
|
||||||
|
|
||||||
angry_prompt_addition = ""
|
angry_prompt_addition = ""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
from maim_message import UserInfo
|
from maim_message import UserInfo
|
||||||
|
|
||||||
|
from src.chat.message_manager.sleep_system.state_manager import SleepState, sleep_state_manager
|
||||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
@@ -13,7 +14,6 @@ from src.manager.async_task_manager import AsyncTask, async_task_manager
|
|||||||
from src.plugin_system import BaseEventHandler, EventType
|
from src.plugin_system import BaseEventHandler, EventType
|
||||||
from src.plugin_system.apis import chat_api, message_api, person_api
|
from src.plugin_system.apis import chat_api, message_api, person_api
|
||||||
from src.plugin_system.base.base_event import HandlerResult
|
from src.plugin_system.base.base_event import HandlerResult
|
||||||
from src.chat.message_manager.sleep_system.state_manager import SleepState, sleep_state_manager
|
|
||||||
|
|
||||||
from .proactive_thinker_executor import ProactiveThinkerExecutor
|
from .proactive_thinker_executor import ProactiveThinkerExecutor
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class UILogHandler(logging.Handler):
|
|||||||
# if not success:
|
# if not success:
|
||||||
# print(f"[UI日志适配器] 日志发送失败: {ui_level} - {formatted_msg[:50]}...")
|
# print(f"[UI日志适配器] 日志发送失败: {ui_level} - {formatted_msg[:50]}...")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# 静默失败,不影响主程序
|
# 静默失败,不影响主程序
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user