Files
Mofox-Core/docs/plugins/examples/complete-examples.md
2025-06-15 23:30:53 +08:00

13 KiB
Raw Blame History

📚 完整示例

📖 概述

这里收集了各种类型的完整插件示例展示了MaiBot插件系统的最佳实践和高级用法。每个示例都包含完整的代码、配置和说明。

🎯 示例列表

🌟 基础示例

🔧 实用示例

🛠️ 工具系统示例

🚀 高级示例


Hello World插件

最基础的入门插件展示Action和Command的基本用法。

功能说明

  • HelloAction: 响应问候语,展示关键词激活
  • TimeCommand: 查询当前时间,展示命令处理

完整代码

plugins/hello_world_plugin/plugin.py:

from typing import List, Tuple, Type
from src.plugin_system import (
    BasePlugin, register_plugin, BaseAction, BaseCommand,
    ComponentInfo, ActionActivationType, ChatMode
)

class HelloAction(BaseAction):
    """问候Action"""

    # ===== 激活控制必须项 =====
    focus_activation_type = ActionActivationType.KEYWORD
    normal_activation_type = ActionActivationType.KEYWORD
    mode_enable = ChatMode.ALL
    parallel_action = False

    # ===== 基本信息必须项 =====
    action_name = "hello_greeting"
    action_description = "向用户发送友好的问候消息"

    # 关键词配置
    activation_keywords = ["你好", "hello", "hi"]
    keyword_case_sensitive = False

    # ===== 功能定义必须项 =====
    action_parameters = {
        "greeting_style": "问候风格casual(随意) 或 formal(正式)"
    }

    action_require = [
        "用户发送问候语时使用",
        "营造友好的聊天氛围"
    ]

    associated_types = ["text", "emoji"]

    async def execute(self) -> Tuple[bool, str]:
        style = self.action_data.get("greeting_style", "casual")
        
        if style == "formal":
            message = "您好!很高兴为您服务!"
            emoji = "🙏"
        else:
            message = "嗨!很开心见到你!"
            emoji = "😊"
        
        await self.send_text(message)
        await self.send_type("emoji", emoji)
        
        return True, f"发送了{style}风格的问候"

class TimeCommand(BaseCommand):
    """时间查询Command"""

    command_pattern = r"^/time$"
    command_help = "查询当前时间"
    command_examples = ["/time"]
    intercept_message = True

    async def execute(self) -> Tuple[bool, str]:
        import datetime
        
        now = datetime.datetime.now()
        time_str = now.strftime("%Y-%m-%d %H:%M:%S")
        
        await self.send_text(f"⏰ 当前时间:{time_str}")
        
        return True, f"显示了当前时间: {time_str}"

@register_plugin
class HelloWorldPlugin(BasePlugin):
    """Hello World插件"""

    plugin_name = "hello_world_plugin"
    plugin_description = "Hello World演示插件"
    plugin_version = "1.0.0"
    plugin_author = "MaiBot Team"
    enable_plugin = True

    def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]:
        return [
            (HelloAction.get_action_info(), HelloAction),
            (TimeCommand.get_command_info(
                name="time_query", 
                description="查询当前系统时间"
            ), TimeCommand),
        ]

配置文件

plugins/hello_world_plugin/config.toml:

[plugin]
name = "hello_world_plugin"
version = "1.0.0"
enabled = true

[greeting]
default_style = "casual"
enable_emoji = true

[time]
timezone = "Asia/Shanghai"
format = "%Y-%m-%d %H:%M:%S"

天气查询工具

展示如何创建Focus模式下的信息获取工具专门用于扩展麦麦的信息获取能力。

功能说明

  • Focus模式专用:仅在专注聊天模式下工作
  • 自动调用LLM根据用户查询自动判断是否使用
  • 信息增强:为麦麦提供实时天气数据
  • 必须启用工具处理器

完整代码

src/tools/tool_can_use/weather_tool.py:

from src.tools.tool_can_use.base_tool import BaseTool, register_tool
import aiohttp
import json

class WeatherTool(BaseTool):
    """天气查询工具 - 获取指定城市的实时天气信息"""
    
    # 工具名称,必须唯一
    name = "weather_query"
    
    # 工具描述告诉LLM这个工具的用途
    description = "查询指定城市的实时天气信息,包括温度、湿度、天气状况等"
    
    # 参数定义遵循JSONSchema格式
    parameters = {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "要查询天气的城市名称,如:北京、上海、纽约"
            },
            "country": {
                "type": "string",
                "description": "国家代码CN、US可选参数"
            }
        },
        "required": ["city"]
    }
    
    async def execute(self, function_args, message_txt=""):
        """执行天气查询"""
        try:
            city = function_args.get("city")
            country = function_args.get("country", "")
            
            # 构建查询参数
            location = f"{city},{country}" if country else city
            
            # 调用天气API
            weather_data = await self._fetch_weather(location)
            
            # 格式化结果
            result = self._format_weather_data(weather_data)
            
            return {
                "name": self.name,
                "content": result
            }
            
        except Exception as e:
            return {
                "name": self.name,
                "content": f"天气查询失败: {str(e)}"
            }
    
    async def _fetch_weather(self, location: str) -> dict:
        """获取天气数据"""
        # 这里是示例实际需要接入真实的天气API
        # 例如OpenWeatherMap、和风天气等
        api_url = f"http://api.weather.com/v1/current?q={location}"
        
        async with aiohttp.ClientSession() as session:
            async with session.get(api_url) as response:
                return await response.json()
    
    def _format_weather_data(self, data: dict) -> str:
        """格式化天气数据"""
        if not data:
            return "暂无天气数据"
        
        # 提取关键信息
        city = data.get("location", {}).get("name", "未知城市")
        temp = data.get("current", {}).get("temp_c", "未知")
        condition = data.get("current", {}).get("condition", {}).get("text", "未知")
        humidity = data.get("current", {}).get("humidity", "未知")
        
        # 格式化输出
        return f"""
🌤️ {city} 实时天气
━━━━━━━━━━━━━━━━━━
🌡️ 温度: {temp}°C
☁️ 天气: {condition}
💧 湿度: {humidity}%
━━━━━━━━━━━━━━━━━━
        """.strip()

# 注册工具(重要!必须调用)
register_tool(WeatherTool)

使用说明

  1. 部署位置:将文件放在 src/tools/tool_can_use/ 目录下
  2. 模式要求仅在Focus模式下可用
  3. 配置要求:必须开启工具处理器 enable_tool_processor = True
  4. 自动调用:用户发送"今天北京天气怎么样?"时,麦麦会自动调用此工具

知识搜索工具

展示如何创建知识查询工具,为麦麦提供百科知识和专业信息。

功能说明

  • 知识增强:扩展麦麦的知识获取能力
  • 分类搜索:支持科学、历史、技术等分类
  • 多语言支持:支持中英文结果
  • 智能调用LLM自动判断何时需要知识查询

完整代码

src/tools/tool_can_use/knowledge_search_tool.py:

from src.tools.tool_can_use.base_tool import BaseTool, register_tool
import aiohttp
import json

class KnowledgeSearchTool(BaseTool):
    """知识搜索工具 - 查询百科知识和专业信息"""
    
    name = "knowledge_search"
    description = "搜索百科知识、专业术语解释、历史事件等信息"
    
    parameters = {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "要搜索的知识关键词或问题"
            },
            "category": {
                "type": "string",
                "description": "知识分类science(科学)、history(历史)、technology(技术)、general(通用)等",
                "enum": ["science", "history", "technology", "general"]
            },
            "language": {
                "type": "string",
                "description": "结果语言zh(中文)、en(英文)",
                "enum": ["zh", "en"]
            }
        },
        "required": ["query"]
    }
    
    async def execute(self, function_args, message_txt=""):
        """执行知识搜索"""
        try:
            query = function_args.get("query")
            category = function_args.get("category", "general")
            language = function_args.get("language", "zh")
            
            # 执行搜索逻辑
            search_results = await self._search_knowledge(query, category, language)
            
            # 格式化结果
            result = self._format_search_results(query, search_results)
            
            return {
                "name": self.name,
                "content": result
            }
            
        except Exception as e:
            return {
                "name": self.name,
                "content": f"知识搜索失败: {str(e)}"
            }
    
    async def _search_knowledge(self, query: str, category: str, language: str) -> list:
        """执行知识搜索"""
        # 这里实现实际的搜索逻辑
        # 可以对接维基百科API、百度百科API等
        
        # 示例API调用
        if language == "zh":
            api_url = f"https://zh.wikipedia.org/api/rest_v1/page/summary/{query}"
        else:
            api_url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{query}"
        
        async with aiohttp.ClientSession() as session:
            async with session.get(api_url) as response:
                if response.status == 200:
                    data = await response.json()
                    return [
                        {
                            "title": data.get("title", "无标题"),
                            "summary": data.get("extract", "无摘要"),
                            "source": "Wikipedia"
                        }
                    ]
                else:
                    return []
    
    def _format_search_results(self, query: str, results: list) -> str:
        """格式化搜索结果"""
        if not results:
            return f"未找到关于 '{query}' 的相关信息"
        
        formatted_text = f"📚 关于 '{query}' 的搜索结果:\n\n"
        
        for i, result in enumerate(results[:3], 1):  # 限制显示前3条
            title = result.get("title", "无标题")
            summary = result.get("summary", "无摘要")
            source = result.get("source", "未知来源")
            
            formatted_text += f"{i}. **{title}**\n"
            formatted_text += f"   {summary}\n"
            formatted_text += f"   📖 来源: {source}\n\n"
        
        return formatted_text.strip()

# 注册工具
register_tool(KnowledgeSearchTool)

配置示例

Focus模式配置文件示例

# 在Focus模式配置中
focus_config = {
    "enable_tool_processor": True,  # 必须启用工具处理器
    "tool_timeout": 30,             # 工具执行超时时间(秒)
    "max_tools_per_message": 3      # 单次消息最大工具调用数
}

使用流程

  1. 用户查询用户在Focus模式下发送"什么是量子计算?"
  2. LLM判断:麦麦识别这是知识查询需求
  3. 工具调用:自动调用 knowledge_search 工具
  4. 信息获取:工具查询相关知识信息
  5. 整合回复:麦麦将获取的信息整合到回复中

工具系统特点

  • 🎯 专用性仅在Focus模式下工作专注信息获取
  • 🔍 智能性LLM自动判断何时需要使用工具
  • 📊 丰富性:为麦麦提供外部数据和实时信息
  • 高效性:系统自动发现和注册工具
  • 🔧 独立性:目前需要单独编写,未来将更好融入插件系统

🎉 这些示例展示了MaiBot插件系统的强大功能根据你的需求选择合适的示例作为起点。