MaiBot/src/plugin_system/base/base_action.py

120 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from abc import ABC, abstractmethod
from typing import Tuple, Dict, Any, Optional
from src.common.logger_manager import get_logger
from src.plugin_system.apis.plugin_api import PluginAPI
from src.plugin_system.base.component_types import ActionActivationType, ChatMode, ActionInfo, ComponentType
logger = get_logger("base_action")
class BaseAction(ABC):
"""Action组件基类
Action是插件的一种组件类型用于处理聊天中的动作逻辑
子类可以通过类属性定义激活条件:
- focus_activation_type: 专注模式激活类型
- normal_activation_type: 普通模式激活类型
- activation_keywords: 激活关键词列表
- keyword_case_sensitive: 关键词是否区分大小写
- mode_enable: 启用的聊天模式
- parallel_action: 是否允许并行执行
- random_activation_probability: 随机激活概率
- llm_judge_prompt: LLM判断提示词
"""
# 默认激活设置(子类可以覆盖)
focus_activation_type: ActionActivationType = ActionActivationType.NEVER
normal_activation_type: ActionActivationType = ActionActivationType.NEVER
activation_keywords: list = []
keyword_case_sensitive: bool = False
mode_enable: ChatMode = ChatMode.ALL
parallel_action: bool = True
random_activation_probability: float = 0.0
llm_judge_prompt: str = ""
def __init__(self,
action_data: dict,
reasoning: str,
cycle_timers: dict,
thinking_id: str,
**kwargs):
"""初始化Action组件
Args:
action_data: 动作数据
reasoning: 执行该动作的理由
cycle_timers: 计时器字典
thinking_id: 思考ID
**kwargs: 其他参数(包含服务对象)
"""
self.action_data = action_data
self.reasoning = reasoning
self.cycle_timers = cycle_timers
self.thinking_id = thinking_id
# 创建API实例
self.api = PluginAPI(
chat_stream=kwargs.get("chat_stream"),
expressor=kwargs.get("expressor"),
replyer=kwargs.get("replyer"),
observations=kwargs.get("observations"),
log_prefix=kwargs.get("log_prefix", "")
)
self.log_prefix = kwargs.get("log_prefix", "")
logger.debug(f"{self.log_prefix} Action组件初始化完成")
async def send_reply(self, content: str) -> bool:
"""发送回复消息
Args:
content: 回复内容
Returns:
bool: 是否发送成功
"""
return await self.api.send_message("text", content)
@classmethod
def get_action_info(cls, name: str = None, description: str = None) -> 'ActionInfo':
"""从类属性生成ActionInfo
Args:
name: Action名称如果不提供则使用类名
description: Action描述如果不提供则使用类文档字符串
Returns:
ActionInfo: 生成的Action信息对象
"""
# 自动生成名称和描述
if name is None:
name = cls.__name__.lower().replace('action', '')
if description is None:
description = cls.__doc__ or f"{cls.__name__} Action组件"
description = description.strip().split('\n')[0] # 取第一行作为描述
return ActionInfo(
name=name,
component_type=ComponentType.ACTION,
description=description,
focus_activation_type=cls.focus_activation_type,
normal_activation_type=cls.normal_activation_type,
activation_keywords=cls.activation_keywords.copy() if cls.activation_keywords else [],
keyword_case_sensitive=cls.keyword_case_sensitive,
mode_enable=cls.mode_enable,
parallel_action=cls.parallel_action,
random_activation_probability=cls.random_activation_probability,
llm_judge_prompt=cls.llm_judge_prompt
)
@abstractmethod
async def execute(self) -> Tuple[bool, str]:
"""执行Action的抽象方法子类必须实现
Returns:
Tuple[bool, str]: (是否执行成功, 回复文本)
"""
pass