10 KiB
10 KiB
📋 开发标准规范
🎯 概述
本文档定义了MaiBot插件开发的标准规范,包括Action组件、Command组件和Tool组件的开发规范,确保代码质量、可维护性和性能。
🧩 组件开发规范
Tool组件开发
工具基本要求:
- 继承
BaseTool基类 - 定义唯一的工具名称
- 提供清晰的功能描述
- 使用JSONSchema定义参数
- 实现
execute异步方法 - 使用
register_tool()注册
工具开发模板:
from src.tools.tool_can_use.base_tool import BaseTool, register_tool
class MyTool(BaseTool):
"""工具类文档字符串"""
name = "my_tool"
description = "详细的工具功能描述,告诉LLM这个工具的用途"
parameters = {
"type": "object",
"properties": {
"param": {
"type": "string",
"description": "参数详细描述"
}
},
"required": ["param"]
}
async def execute(self, function_args, message_txt=""):
"""执行工具逻辑
Args:
function_args: 工具调用参数
message_txt: 原始消息文本
Returns:
dict: 包含name和content字段的结果
"""
# 实现工具功能逻辑
result = "处理结果"
return {
"name": self.name,
"content": result
}
# 注册工具
register_tool(MyTool)
工具命名规范:
- 使用描述性的英文名称
- 采用下划线命名法(snake_case)
- 体现工具的核心功能
- 避免过于简短或复杂的名称
示例:
# ✅ 好的命名
name = "weather_query" # 天气查询
name = "knowledge_search" # 知识搜索
name = "stock_price_check" # 股价检查
# ❌ 避免的命名
name = "tool1" # 无意义
name = "wq" # 过于简短
name = "weather_and_news" # 功能复杂
Action组件开发
Action必需字段检查表:
激活控制字段:
- ✅
activation_type:激活类型(KEYWORD/LLM_JUDGE/RANDOM/ALWAYS/NEVER) - ✅
activation_config:激活配置参数
基本信息字段:
- ✅
name:Action唯一标识名称 - ✅
description:功能描述 - ✅
usage_tip:使用提示
功能定义字段:
- ✅
func:执行函数 - ✅
llm_function_tips:LLM调用提示
Action开发模板:
from src.plugin_system.base_actions import BaseAction
class MyAction(BaseAction):
"""Action类文档字符串"""
# 激活控制
activation_type = "KEYWORD" # 或 LLM_JUDGE/RANDOM/ALWAYS/NEVER
activation_config = {
"keywords": ["关键词1", "关键词2"],
"priority": 1
}
# 基本信息
name = "my_action"
description = "Action功能描述"
usage_tip = "使用场景和方法提示"
# 功能定义
func = "执行函数名"
llm_function_tips = "告诉LLM何时以及如何使用这个Action"
async def 执行函数名(self, message_txt, sender_name, chat_stream):
"""Action执行逻辑"""
# 实现Action功能
await chat_stream.send_message("执行结果")
激活类型使用规范:
KEYWORD:适用于有明确关键词的功能,性能最优LLM_JUDGE:适用于需要智能判断的复杂场景RANDOM:适用于随机触发的功能ALWAYS:适用于总是可用的基础功能NEVER:适用于临时禁用的功能
Command组件开发
Command开发模板:
from src.plugin_system.base_commands import BaseCommand
class MyCommand(BaseCommand):
"""Command类文档字符串"""
# 命令基本信息
command_name = "my_command"
description = "命令功能描述"
usage = "/my_command <参数> - 命令使用说明"
# 匹配模式
pattern = r"^/my_command\s+(.*)"
async def execute(self, match, message_txt, sender_name, chat_stream):
"""Command执行逻辑"""
params = match.group(1) if match.group(1) else ""
# 实现命令功能
await chat_stream.send_message(f"命令执行结果: {params}")
📝 代码结构标准
文件组织结构
plugins/my_plugin/
├── __init__.py # 插件入口
├── plugin.py # 插件主文件
├── config.toml # 插件配置
├── actions/ # Action组件目录
│ ├── __init__.py
│ └── my_action.py
├── commands/ # Command组件目录
│ ├── __init__.py
│ └── my_command.py
├── utils/ # 工具函数目录
│ ├── __init__.py
│ └── helpers.py
└── README.md # 插件说明文档
插件主文件模板
"""
插件名称:My Plugin
插件描述:插件功能描述
作者:作者名称
版本:1.0.0
"""
from src.plugin_system.plugin_interface import PluginInterface
from .actions.my_action import MyAction
from .commands.my_command import MyCommand
class MyPlugin(PluginInterface):
"""插件主类"""
def get_action_info(self):
"""获取Action信息"""
return [MyAction()]
def get_command_info(self):
"""获取Command信息"""
return [MyCommand()]
# 插件实例
plugin_instance = MyPlugin()
🔧 命名规范
类命名
- Action类:使用
Action后缀,如GreetingAction - Command类:使用
Command后缀,如HelpCommand - Tool类:使用
Tool后缀,如WeatherTool - 插件类:使用
Plugin后缀,如ExamplePlugin
变量命名
- 使用小写字母和下划线(snake_case)
- 布尔变量使用
is_、has_、can_前缀 - 常量使用全大写字母
函数命名
- 使用小写字母和下划线(snake_case)
- 异步函数不需要特殊前缀
- 私有方法使用单下划线前缀
📊 性能优化规范
Action激活类型选择
- 首选KEYWORD:明确知道触发关键词时
- 谨慎使用LLM_JUDGE:仅在必须智能判断时使用
- 合理设置优先级:避免过多高优先级Action
异步编程规范
- 所有I/O操作必须使用异步
- 避免在异步函数中使用阻塞操作
- 合理使用
asyncio.gather()并发执行
资源管理
- 及时关闭文件、网络连接等资源
- 使用上下文管理器(
async with) - 避免内存泄漏
🚨 错误处理规范
异常处理模板
async def my_function(self, message_txt, sender_name, chat_stream):
"""函数文档字符串"""
try:
# 核心逻辑
result = await some_operation()
# 成功处理
await chat_stream.send_message(f"操作成功: {result}")
except ValueError as e:
# 具体异常处理
await chat_stream.send_message(f"参数错误: {str(e)}")
except Exception as e:
# 通用异常处理
await chat_stream.send_message(f"操作失败: {str(e)}")
# 记录错误日志
logger.error(f"Function my_function failed: {str(e)}")
错误信息规范
- 使用用户友好的错误提示
- 避免暴露系统内部信息
- 提供解决建议或替代方案
- 记录详细的错误日志
🧪 测试标准
单元测试模板
import unittest
import asyncio
from unittest.mock import Mock, AsyncMock
from plugins.my_plugin.actions.my_action import MyAction
class TestMyAction(unittest.TestCase):
"""MyAction测试类"""
def setUp(self):
"""测试前准备"""
self.action = MyAction()
self.mock_chat_stream = AsyncMock()
def test_action_properties(self):
"""测试Action属性"""
self.assertEqual(self.action.name, "my_action")
self.assertIsNotNone(self.action.description)
self.assertIsNotNone(self.action.activation_type)
async def test_action_execution(self):
"""测试Action执行"""
await self.action.执行函数名("测试消息", "测试用户", self.mock_chat_stream)
# 验证消息发送
self.mock_chat_stream.send_message.assert_called()
def test_action_execution_sync(self):
"""同步测试包装器"""
asyncio.run(self.test_action_execution())
if __name__ == '__main__':
unittest.main()
测试覆盖率要求
- 核心功能必须有测试覆盖
- 异常处理路径需要测试
- 边界条件需要验证
📚 文档规范
代码文档
- 所有类和函数必须有文档字符串
- 使用Google风格的docstring
- 包含参数说明和返回值说明
README文档模板
# 插件名称
## 📖 插件描述
简要描述插件的功能和用途
## ✨ 功能特性
- 功能1:功能描述
- 功能2:功能描述
## 🚀 快速开始
### 安装配置
1. 步骤1
2. 步骤2
### 使用方法
具体的使用说明和示例
## 📝 配置说明
配置文件的详细说明
## 🔧 开发信息
- 作者:作者名称
- 版本:版本号
- 许可证:许可证类型
🔍 代码审查清单
基础检查
- 代码符合命名规范
- 类和函数有完整文档字符串
- 异常处理覆盖完整
- 没有硬编码的配置信息
Action组件检查
- 包含所有必需字段
- 激活类型选择合理
- LLM函数提示清晰
- 执行函数实现正确
Command组件检查
- 正则表达式模式正确
- 参数提取和验证完整
- 使用说明准确
Tool组件检查
- 继承BaseTool基类
- 参数定义遵循JSONSchema
- 返回值格式正确
- 工具已正确注册
性能检查
- 避免不必要的LLM_JUDGE激活
- 异步操作使用正确
- 资源管理合理
安全检查
- 输入参数验证
- SQL注入防护
- 敏感信息保护
🎯 最佳实践总结
设计原则
- 单一职责:每个组件专注单一功能
- 松耦合:减少组件间依赖
- 高内聚:相关功能聚合在一起
- 可扩展:易于添加新功能
性能优化
- 合理选择激活类型:优先使用KEYWORD
- 避免阻塞操作:使用异步编程
- 缓存重复计算:提高响应速度
- 资源池化:复用连接和对象
用户体验
- 友好的错误提示:帮助用户理解问题
- 清晰的使用说明:降低学习成本
- 一致的交互方式:统一的命令格式
- 及时的反馈:让用户知道操作状态
🎉 遵循这些标准可以确保插件的质量、性能和用户体验!