# ⚡ Action组件详解

## 📖 什么是Action

Action是给麦麦在回复之外提供额外功能的智能组件，**由麦麦的决策系统自主选择是否使用**，具有随机性和拟人化的调用特点。Action不是直接响应用户命令，而是让麦麦根据聊天情境智能地选择合适的动作，使其行为更加自然和真实。

### 🎯 Action的特点

- 🧠 **智能激活**：麦麦根据多种条件智能判断是否使用
- 🎲 **随机性**：增加行为的不可预测性，更接近真人交流
- 🤖 **拟人化**：让麦麦的回应更自然、更有个性
- 🔄 **情境感知**：基于聊天上下文做出合适的反应

## 🎯 两层决策机制

Action采用**两层决策机制**来优化性能和决策质量：

### 第一层：激活控制（Activation Control）

**激活决定麦麦是否"知道"这个Action的存在**，即这个Action是否进入决策候选池。**不被激活的Action麦麦永远不会选择**。

> 🎯 **设计目的**：在加载许多插件的时候降低LLM决策压力，避免让麦麦在过多的选项中纠结。

#### 激活类型说明

| 激活类型      | 说明                                        | 使用场景                 |
| ------------- | ------------------------------------------- | ------------------------ |
| `NEVER`     | 从不激活，Action对麦麦不可见                | 临时禁用某个Action       |
| `ALWAYS`    | 永远激活，Action总是在麦麦的候选池中        | 核心功能，如回复、不回复 |
| `LLM_JUDGE` | 通过LLM智能判断当前情境是否需要激活此Action | 需要智能判断的复杂场景   |
| `RANDOM`    | 基于随机概率决定是否激活                    | 增加行为随机性的功能     |
| `KEYWORD`   | 当检测到特定关键词时激活                    | 明确触发条件的功能       |

#### 聊天模式控制

| 模式                | 说明                     |
| ------------------- | ------------------------ |
| `ChatMode.FOCUS`  | 仅在专注聊天模式下可激活 |
| `ChatMode.NORMAL` | 仅在普通聊天模式下可激活 |
| `ChatMode.ALL`    | 所有模式下都可激活       |

### 第二层：使用决策（Usage Decision）

**在Action被激活后，使用条件决定麦麦什么时候会"选择"使用这个Action**。

这一层由以下因素综合决定：

- `action_require`：使用场景描述，帮助LLM判断何时选择
- `action_parameters`：所需参数，影响Action的可执行性
- 当前聊天上下文和麦麦的决策逻辑

### 🎬 决策流程示例

假设有一个"发送表情"Action：

```python
class EmojiAction(BaseAction):
    # 第一层：激活控制
    focus_activation_type = ActionActivationType.RANDOM  # 专注模式下随机激活
    normal_activation_type = ActionActivationType.KEYWORD  # 普通模式下关键词激活
    activation_keywords = ["表情", "emoji", "😊"]
  
    # 第二层：使用决策
    action_require = [
        "表达情绪时可以选择使用",
        "增加聊天趣味性",
        "不要连续发送多个表情"
    ]
```

**决策流程**：

1. **第一层激活判断**：

   - 普通模式：只有当用户消息包含"表情"、"emoji"或"😊"时，麦麦才"知道"可以使用这个Action
   - 专注模式：随机激活，有概率让麦麦"看到"这个Action
2. **第二层使用决策**：

   - 即使Action被激活，麦麦还会根据 `action_require`中的条件判断是否真正选择使用
   - 例如：如果刚刚已经发过表情，根据"不要连续发送多个表情"的要求，麦麦可能不会选择这个Action

## 📋 Action必须项清单

每个Action类都**必须**包含以下属性：

### 1. 激活控制必须项

```python
# 专注模式下的激活类型
focus_activation_type = ActionActivationType.LLM_JUDGE

# 普通模式下的激活类型
normal_activation_type = ActionActivationType.KEYWORD

# 启用的聊天模式
mode_enable = ChatMode.ALL

# 是否允许与其他Action并行执行
parallel_action = False
```

### 2. 基本信息必须项

```python
# Action的唯一标识名称
action_name = "my_action"

# Action的功能描述
action_description = "描述这个Action的具体功能和用途"
```

### 3. 功能定义必须项

```python
# Action参数定义 - 告诉LLM执行时需要什么参数
action_parameters = {
    "param1": "参数1的说明",
    "param2": "参数2的说明"
}

# Action使用场景描述 - 帮助LLM判断何时"选择"使用
action_require = [
    "使用场景描述1",
    "使用场景描述2"
]

# 关联的消息类型 - 说明Action能处理什么类型的内容
associated_types = ["text", "emoji", "image"]
```

### 4. 新API导入必须项

使用新插件系统时，必须导入所需的API模块：

```python
# 导入新API模块
from src.plugin_system.apis import generator_api, send_api, emoji_api

# 如果需要使用其他API
from src.plugin_system.apis import llm_api, database_api, message_api
```

### 5. 动作记录必须项

每个 Action 在执行完成后，**必须**使用 `store_action_info` 记录动作信息：

```python
async def execute(self) -> Tuple[bool, str]:
    # ... 执行动作的代码 ...
  
    if success:
        # 存储动作信息 - 使用新API格式
        await self.store_action_info(
            action_build_into_prompt=True,  # 让麦麦知道这个动作
            action_prompt_display=f"执行了xxx动作，参数：{param}",  # 动作描述
            action_done=True,  # 动作是否完成
        )
        return True, "动作执行成功"
```

> ⚠️ **重要提示**：新API格式中不再需要手动传递 `thinking_id` 等参数，BaseAction会自动处理。

## 🚀 新API使用指南

### 📨 消息发送API

新的消息发送API更加简洁，自动处理群聊/私聊逻辑：

```python
class MessageAction(BaseAction):
    async def execute(self) -> Tuple[bool, str]:
        # 发送文本消息 - 自动判断群聊/私聊
        await self.send_text("Hello World!")
      
        # 发送表情包
        emoji_base64 = await emoji_api.get_by_description("开心")
        if emoji_base64:
            await self.send_emoji(emoji_base64)
      
        # 发送图片
        await self.send_image(image_base64)
      
        # 发送自定义类型消息
        await self.send_custom("video", video_data, typing=True)
      
        return True, "消息发送完成"
```

### 🤖 智能生成API (replyer_1)

使用replyer_1生成个性化内容：

```python
class SmartReplyAction(BaseAction):
    async def execute(self) -> Tuple[bool, str]:
        # 构建生成参数
        reply_data = {
            "text": "请生成一个友好的回复",
            "style": "casual",
            "topic": "日常聊天",
            "replyer_name": "replyer_1"  # 指定使用replyer_1
        }
      
        # 使用generator_api生成回复
        success, reply_set = await generator_api.generate_reply(
            chat_stream=self.chat_stream,
            action_data=reply_data,
            platform=self.platform,
            chat_id=self.chat_id,
            is_group=self.is_group
        )
      
        if success and reply_set:
            # 提取并发送文本回复
            for reply_type, reply_content in reply_set:
                if reply_type == "text":
                    await self.send_text(reply_content)
                elif reply_type == "emoji":
                    await self.send_emoji(reply_content)
          
            # 记录动作
            await self.store_action_info(
                action_build_into_prompt=True,
                action_prompt_display=f"使用replyer_1生成了智能回复",
                action_done=True
            )
          
            return True, "智能回复生成成功"
        else:
            return False, "回复生成失败"
```

### ⚙️ 配置访问API

使用便捷的配置访问方法：

```python
class ConfigurableAction(BaseAction):
    async def execute(self) -> Tuple[bool, str]:
        # 获取插件配置 - 支持嵌套键访问
        enable_feature = self.get_config("features.enable_smart_mode", False)
        max_length = self.get_config("limits.max_text_length", 200)
        style = self.get_config("behavior.response_style", "friendly")
      
        if enable_feature:
            # 启用高级功能
            pass
      
        return True, "配置获取成功"
```

### 📊 数据库API

使用新的数据库API存储和查询数据：

```python
class DataAction(BaseAction):
    async def execute(self) -> Tuple[bool, str]:
        # 使用database_api
        from src.plugin_system.apis import database_api
      
        # 存储数据
        await database_api.store_action_info(
            chat_stream=self.chat_stream,
            action_name=self.action_name,
            action_data=self.action_data,
            # ... 其他参数
        )
      
        return True, "数据存储完成"
```

## 🔧 激活类型详解

### KEYWORD激活

当检测到特定关键词时激活Action：

```python
class GreetingAction(BaseAction):
    focus_activation_type = ActionActivationType.KEYWORD
    normal_activation_type = ActionActivationType.KEYWORD
  
    # 关键词配置
    activation_keywords = ["你好", "hello", "hi", "嗨"]
    keyword_case_sensitive = False  # 不区分大小写
  
    async def execute(self) -> Tuple[bool, str]:
        # 可选：使用replyer_1生成个性化问候
        if self.get_config("greeting.use_smart_reply", False):
            greeting_data = {
                "text": "生成一个友好的问候语",
                "replyer_name": "replyer_1"
            }
          
            success, reply_set = await generator_api.generate_reply(
                chat_stream=self.chat_stream,
                action_data=greeting_data
            )
          
            if success:
                for reply_type, content in reply_set:
                    if reply_type == "text":
                        await self.send_text(content)
                        break
                return True, "发送智能问候"
      
        # 传统问候方式
        await self.send_text("你好！很高兴见到你！")
        return True, "发送问候"
```

### LLM_JUDGE激活

通过LLM智能判断是否激活：

```python
class HelpAction(BaseAction):
    focus_activation_type = ActionActivationType.LLM_JUDGE
    normal_activation_type = ActionActivationType.LLM_JUDGE
  
    # LLM判断提示词
    llm_judge_prompt = """
    判定是否需要使用帮助动作的条件：
    1. 用户表达了困惑或需要帮助
    2. 用户提出了问题但没有得到满意答案
    3. 对话中出现了技术术语或复杂概念
  
    请回答"是"或"否"。
    """
  
    async def execute(self) -> Tuple[bool, str]:
        # 使用replyer_1生成帮助内容
        help_data = {
            "text": "用户需要帮助，请提供适当的帮助信息",
            "help_type": self.action_data.get("help_type", "general"),
            "replyer_name": "replyer_1"
        }
      
        success, reply_set = await generator_api.generate_reply(
            chat_stream=self.chat_stream,
            action_data=help_data
        )
      
        if success:
            for reply_type, content in reply_set:
                if reply_type == "text":
                    await self.send_text(content)
            return True, "提供了帮助"
        else:
            await self.send_text("我来帮助你！有什么问题吗？")
            return True, "提供了默认帮助"
```

### RANDOM激活

基于随机概率激活：

```python
class SurpriseAction(BaseAction):
    focus_activation_type = ActionActivationType.RANDOM
    normal_activation_type = ActionActivationType.RANDOM
  
    # 随机激活概率
    random_activation_probability = 0.1  # 10%概率激活
  
    async def execute(self) -> Tuple[bool, str]:
        import random
      
        surprises = ["🎉", "✨", "🌟", "💝", "🎈"]
        selected = random.choice(surprises)
      
        await self.send_emoji(selected)
        return True, f"发送了惊喜表情: {selected}"
```

## 💡 完整示例

### 智能聊天Action

```python
from src.plugin_system.apis import generator_api, emoji_api

class IntelligentChatAction(BaseAction):
    """智能聊天Action - 展示新API的完整用法"""
  
    # 激活设置
    focus_activation_type = ActionActivationType.ALWAYS
    normal_activation_type = ActionActivationType.LLM_JUDGE
    mode_enable = ChatMode.ALL
    parallel_action = False
  
    # 基本信息
    action_name = "intelligent_chat"
    action_description = "使用replyer_1进行智能聊天回复，支持表情包和个性化回复"
  
    # LLM判断提示词
    llm_judge_prompt = """
    判断是否需要进行智能聊天回复：
    1. 用户提出了有趣的话题
    2. 需要更加个性化的回复
    3. 适合发送表情包的情况
  
    请回答"是"或"否"。
    """
  
    # 功能定义
    action_parameters = {
        "topic": "聊天话题",
        "mood": "当前氛围（happy/sad/excited/calm）",
        "include_emoji": "是否包含表情包（true/false）"
    }
  
    action_require = [
        "需要更个性化回复时使用",
        "聊天氛围适合发送表情时使用",
        "避免在正式场合使用"
    ]
  
    associated_types = ["text", "emoji"]
  
    async def execute(self) -> Tuple[bool, str]:
        # 获取参数
        topic = self.action_data.get("topic", "日常聊天")
        mood = self.action_data.get("mood", "happy")
        include_emoji = self.action_data.get("include_emoji", "true") == "true"
      
        # 构建智能回复数据
        chat_data = {
            "text": f"请针对{topic}话题进行回复，当前氛围是{mood}",
            "topic": topic,
            "mood": mood,
            "style": "conversational",
            "replyer_name": "replyer_1"  # 使用replyer_1
        }
      
        # 生成智能回复
        success, reply_set = await generator_api.generate_reply(
            chat_stream=self.chat_stream,
            action_data=chat_data,
            platform=self.platform,
            chat_id=self.chat_id,
            is_group=self.is_group
        )
      
        reply_sent = False
      
        if success and reply_set:
            # 发送生成的回复
            for reply_type, content in reply_set:
                if reply_type == "text":
                    await self.send_text(content)
                    reply_sent = True
                elif reply_type == "emoji":
                    await self.send_emoji(content)
      
        # 如果配置允许且生成失败，发送表情包
        if include_emoji and not reply_sent:
            emoji_result = await emoji_api.get_by_description(mood)
            if emoji_result:
                emoji_base64, emoji_desc, matched_emotion = emoji_result
                await self.send_emoji(emoji_base64)
                reply_sent = True
      
        # 记录动作执行
        if reply_sent:
            await self.store_action_info(
                action_build_into_prompt=True,
                action_prompt_display=f"进行了智能聊天回复，话题：{topic}，氛围：{mood}",
                action_done=True
            )
            return True, f"完成智能聊天回复：{topic}"
        else:
            return False, "智能回复生成失败"
```

## 🛠️ 调试技巧

### 开发调试Action

```python
class DebugAction(BaseAction):
    """调试Action - 展示如何调试新API"""
  
    focus_activation_type = ActionActivationType.KEYWORD
    normal_activation_type = ActionActivationType.KEYWORD
    activation_keywords = ["debug", "调试"]
    mode_enable = ChatMode.ALL
    parallel_action = True
  
    action_name = "debug_helper"
    action_description = "调试助手，显示当前状态信息"
  
    action_parameters = {}
    action_require = ["需要调试信息时使用"]
    associated_types = ["text"]
  
    async def execute(self) -> Tuple[bool, str]:
        # 收集调试信息
        debug_info = {
            "聊天类型": "群聊" if self.is_group else "私聊",
            "平台": self.platform,
            "目标ID": self.target_id,
            "用户ID": self.user_id,
            "用户昵称": self.user_nickname,
            "动作数据": self.action_data,
        }
      
        if self.is_group:
            debug_info.update({
                "群ID": self.group_id,
                "群名": self.group_name,
            })
      
        # 格式化调试信息
        info_lines = ["🔍 调试信息:"]
        for key, value in debug_info.items():
            info_lines.append(f"  • {key}: {value}")
      
        debug_text = "\n".join(info_lines)
      
        # 发送调试信息
        await self.send_text(debug_text)
      
        # 测试配置获取
        test_config = self.get_config("debug.verbose", True)
        if test_config:
            await self.send_text(f"配置测试: debug.verbose = {test_config}")
      
        return True, "调试信息已发送"
```

## 📚 最佳实践

1. **总是导入所需的API模块**：

   ```python
   from src.plugin_system.apis import generator_api, send_api, emoji_api
   ```
2. **在生成内容时指定replyer_1**：

   ```python
   action_data = {
       "text": "生成内容的请求",
       "replyer_name": "replyer_1"
   }
   ```
3. **使用便捷发送方法**：

   ```python
   await self.send_text("文本")  # 自动处理群聊/私聊
   await self.send_emoji(emoji_base64)
   ```
4. **合理使用配置**：

   ```python
   enable_feature = self.get_config("section.key", default_value)
   ```
5. **总是记录动作信息**：

   ```python
   await self.store_action_info(
       action_build_into_prompt=True,
       action_prompt_display="动作描述",
       action_done=True
   )
   ```

通过使用新的API格式，Action的开发变得更加简洁和强大！
