better:优化文档

This commit is contained in:
SengokuCola
2025-06-15 23:30:53 +08:00
parent 517f0c29e1
commit 2879b5dba0
14 changed files with 3680 additions and 1048 deletions

495
docs/plugins/tool-system.md Normal file
View File

@@ -0,0 +1,495 @@
# 🔧 工具系统详解
## 📖 什么是工具系统
工具系统是MaiBot的信息获取能力扩展组件**专门用于在Focus模式下扩宽麦麦能够获得的信息量**。如果说Action组件功能五花八门可以拓展麦麦能做的事情那么Tool就是在某个过程中拓宽了麦麦能够获得的信息量。
### 🎯 工具系统的特点
- 🔍 **信息获取增强**:扩展麦麦获取外部信息的能力
- 🎯 **Focus模式专用**:仅在专注聊天模式下工作,必须开启工具处理器
- 📊 **数据丰富**:帮助麦麦获得更多背景信息和实时数据
- 🔌 **插件式架构**:支持独立开发和注册新工具
-**自动发现**:工具会被系统自动识别和注册
### 🆚 Tool vs Action vs Command 区别
| 特征 | Action | Command | Tool |
|-----|-------|---------|------|
| **主要用途** | 扩展麦麦行为能力 | 响应用户指令 | 扩展麦麦信息获取 |
| **适用模式** | 所有模式 | 所有模式 | 仅Focus模式 |
| **触发方式** | 麦麦智能决策 | 用户主动触发 | LLM根据需要调用 |
| **目标** | 让麦麦做更多事情 | 提供具体功能 | 让麦麦知道更多信息 |
| **使用场景** | 增强交互体验 | 功能服务 | 信息查询和分析 |
## 🏗️ 工具基本结构
### 必要组件
每个工具必须继承 `BaseTool` 基类并实现以下属性和方法:
```python
from src.tools.tool_can_use.base_tool import BaseTool, register_tool
class MyTool(BaseTool):
# 工具名称,必须唯一
name = "my_tool"
# 工具描述告诉LLM这个工具的用途
description = "这个工具用于获取特定类型的信息"
# 参数定义遵循JSONSchema格式
parameters = {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "查询参数"
},
"limit": {
"type": "integer",
"description": "结果数量限制"
}
},
"required": ["query"]
}
async def execute(self, function_args, message_txt=""):
"""执行工具逻辑"""
# 实现工具功能
result = f"查询结果: {function_args.get('query')}"
return {
"name": self.name,
"content": result
}
# 注册工具
register_tool(MyTool)
```
### 属性说明
| 属性 | 类型 | 说明 |
|-----|------|------|
| `name` | str | 工具的唯一标识名称 |
| `description` | str | 工具功能描述帮助LLM理解用途 |
| `parameters` | dict | JSONSchema格式的参数定义 |
### 方法说明
| 方法 | 参数 | 返回值 | 说明 |
|-----|------|--------|------|
| `execute` | `function_args`, `message_txt` | `dict` | 执行工具核心逻辑 |
## 🔄 自动注册机制
工具系统采用自动发现和注册机制:
1. **文件扫描**:系统自动遍历 `tool_can_use` 目录中的所有Python文件
2. **类识别**:寻找继承自 `BaseTool` 的工具类
3. **自动注册**:调用 `register_tool()` 的工具会被注册到系统中
4. **即用即加载**:工具在需要时被实例化和调用
### 注册流程
```python
# 1. 创建工具类
class WeatherTool(BaseTool):
name = "weather_query"
description = "查询指定城市的天气信息"
# ...
# 2. 注册工具(在文件末尾)
register_tool(WeatherTool)
# 3. 系统自动发现(无需手动操作)
# discover_tools() 函数会自动完成注册
```
## 🎨 完整工具示例
### 天气查询工具
```python
from src.tools.tool_can_use.base_tool import BaseTool, register_tool
import aiohttp
import json
class WeatherTool(BaseTool):
"""天气查询工具 - 获取指定城市的实时天气信息"""
name = "weather_query"
description = "查询指定城市的实时天气信息,包括温度、湿度、天气状况等"
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
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)
```
### 知识查询工具
```python
from src.tools.tool_can_use.base_tool import BaseTool, register_tool
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等
# 示例返回数据
return [
{
"title": f"{query}的定义",
"summary": f"关于{query}的详细解释...",
"source": "Wikipedia"
}
]
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)
```
## 📊 工具开发步骤
### 1. 创建工具文件
`src/tools/tool_can_use/` 目录下创建新的Python文件
```bash
# 例如创建 my_new_tool.py
touch src/tools/tool_can_use/my_new_tool.py
```
### 2. 实现工具类
```python
from src.tools.tool_can_use.base_tool import BaseTool, register_tool
class MyNewTool(BaseTool):
name = "my_new_tool"
description = "新工具的功能描述"
parameters = {
"type": "object",
"properties": {
# 定义参数
},
"required": []
}
async def execute(self, function_args, message_txt=""):
# 实现工具逻辑
return {
"name": self.name,
"content": "执行结果"
}
register_tool(MyNewTool)
```
### 3. 测试工具
创建测试文件验证工具功能:
```python
import asyncio
from my_new_tool import MyNewTool
async def test_tool():
tool = MyNewTool()
result = await tool.execute({"param": "value"})
print(result)
asyncio.run(test_tool())
```
### 4. 系统集成
工具创建完成后,系统会自动发现和注册,无需额外配置。
## ⚙️ 工具处理器配置
### 启用工具处理器
工具系统仅在Focus模式下工作需要确保工具处理器已启用
```python
# 在Focus模式配置中
focus_config = {
"enable_tool_processor": True, # 必须启用
"tool_timeout": 30, # 工具执行超时时间(秒)
"max_tools_per_message": 3 # 单次消息最大工具调用数
}
```
### 工具使用流程
1. **用户发送消息**在Focus模式下发送需要信息查询的消息
2. **LLM判断需求**:麦麦分析消息,判断是否需要使用工具获取信息
3. **选择工具**:根据需求选择合适的工具
4. **调用工具**:执行工具获取信息
5. **整合回复**:将工具获取的信息整合到回复中
### 使用示例
```python
# 用户消息示例
"今天北京的天气怎么样?"
# 系统处理流程:
# 1. 麦麦识别这是天气查询需求
# 2. 调用 weather_query 工具
# 3. 获取北京天气信息
# 4. 整合信息生成回复
# 最终回复:
"根据最新天气数据北京今天晴天温度22°C湿度45%,适合外出活动。"
```
## 🚨 注意事项和限制
### 当前限制
1. **模式限制**仅在Focus模式下可用
2. **独立开发**:需要单独编写,暂未完全融入插件系统
3. **适用范围**:主要适用于信息获取场景
4. **配置要求**:必须开启工具处理器
### 未来改进
工具系统在之后可能会面临以下修改:
1. **插件系统融合**:更好地集成到插件系统中
2. **模式扩展**:可能扩展到其他聊天模式
3. **配置简化**:简化配置和部署流程
4. **性能优化**:提升工具调用效率
### 开发建议
1. **功能专一**:每个工具专注单一功能
2. **参数明确**:清晰定义工具参数和用途
3. **错误处理**:完善的异常处理和错误反馈
4. **性能考虑**:避免长时间阻塞操作
5. **信息准确**:确保获取信息的准确性和时效性
## 🎯 最佳实践
### 1. 工具命名规范
```python
# ✅ 好的命名
name = "weather_query" # 清晰表达功能
name = "knowledge_search" # 描述性强
name = "stock_price_check" # 功能明确
# ❌ 避免的命名
name = "tool1" # 无意义
name = "wq" # 过于简短
name = "weather_and_news" # 功能过于复杂
```
### 2. 描述规范
```python
# ✅ 好的描述
description = "查询指定城市的实时天气信息,包括温度、湿度、天气状况"
# ❌ 避免的描述
description = "天气" # 过于简单
description = "获取信息" # 不够具体
```
### 3. 参数设计
```python
# ✅ 合理的参数设计
parameters = {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如:北京、上海"
},
"unit": {
"type": "string",
"description": "温度单位celsius(摄氏度) 或 fahrenheit(华氏度)",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["city"]
}
# ❌ 避免的参数设计
parameters = {
"type": "object",
"properties": {
"data": {
"type": "string",
"description": "数据" # 描述不清晰
}
}
}
```
### 4. 结果格式化
```python
# ✅ 良好的结果格式
def _format_result(self, data):
return f"""
🔍 查询结果
━━━━━━━━━━━━
📊 数据: {data['value']}
📅 时间: {data['timestamp']}
📝 说明: {data['description']}
━━━━━━━━━━━━
""".strip()
# ❌ 避免的结果格式
def _format_result(self, data):
return str(data) # 直接返回原始数据
```
---
🎉 **工具系统为麦麦提供了强大的信息获取能力!合理使用工具可以让麦麦变得更加智能和博学。**