1. 引言
想象你在組裝一個超級智慧管家機器人(Agent)。這個機器人需要各種工具才能幫你完成任務 - 就像哆啦A夢的百寶袋一樣。本文將教你如何打造這些強大的工具,讓你的 AI 管家更加得心應手。
2. 兩種核心工具設計模式
2.1 同步工具:即問即答模式
想象你在使用一臺自助咖啡機:
- 投幣按下"美式咖啡"按鈕
- 等待幾秒鐘
- 咖啡直接流出來,拿走就能喝
這就是典型的同步工具模式。Agent 呼叫工具後會等待直接得到結果,整個過程快速且簡單。
class WeatherTool(BaseTool):
"""天氣查詢工具 - 同步模式"""
async def execute(self, city: str) -> dict:
# 就像按下咖啡機按鈕一樣簡單直接
weather_data = await self.weather_api.get_current(city)
return {
"status": "success",
"data": {
"temperature": weather_data.temp,
"humidity": weather_data.humidity,
"description": weather_data.desc
}
}
適用場景:
- 快速查詢:天氣、匯率、簡單計算
- 簡單操作:傳送訊息、開關控制
- 實時反饋:驗證碼校驗、餘額查詢
2.2 非同步工具:任務追蹤模式
設想你在使用外賣 APP 點餐:
- 下單後,APP 給你一個訂單號
- 你可以隨時開啟 APP 檢視訂單狀態
- 送達時,APP 推送通知告訴你
這就是非同步工具的工作方式。適合那些需要較長時間處理的任務。
class DocumentAnalysisTool(BaseTool):
"""文件分析工具 - 非同步模式"""
async def start_task(self, file_path: str) -> str:
# 類似下外賣訂單,先返回一個任務ID
task_id = str(uuid.uuid4())
await self.task_queue.put({
"task_id": task_id,
"file_path": file_path,
"status": "processing"
})
return task_id
async def get_status(self, task_id: str) -> dict:
# 像檢視外賣訂單狀態一樣
task = await self.task_store.get(task_id)
return {
"task_id": task_id,
"status": task["status"],
"progress": task.get("progress", 0),
"result": task.get("result", None)
}
適用場景:
- 耗時操作:大檔案處理、資料分析
- 多步驟任務:影片渲染、報表生成
- 需要進度追蹤:模型訓練、批次處理
3. 工具介面標準化:制定通用規範
就像所有電器都遵循統一的插座標準一樣,我們的工具介面也需要標準化。這樣可以確保所有工具都能完美配合 Agent 使用。
3.1 工具描述規範
想象你在寫產品說明書,需要清晰地告訴使用者:
- 這個工具是做什麼用的
- 需要提供什麼引數
- 會返回什麼結果
from pydantic import BaseModel, Field
class ToolSchema(BaseModel):
"""工具說明書模板"""
name: str = Field(..., description="工具名稱")
description: str = Field(..., description="工具用途說明")
parameters: dict = Field(..., description="需要的引數")
required: List[str] = Field(default_factory=list, description="必填引數")
class Config:
schema_extra = {
"example": {
"name": "天氣查詢",
"description": "查詢指定城市的天氣資訊",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名稱"
}
}
},
"required": ["city"]
}
}
3.2 統一的工具基類
就像所有電器都需要有開關和電源介面一樣,所有工具都需要遵循基本規範:
class BaseTool(ABC):
"""所有工具的基礎模板"""
@abstractmethod
def get_schema(self) -> ToolSchema:
"""工具說明書"""
pass
def validate_input(self, params: Dict) -> Dict:
"""引數檢查,就像電器的保險絲"""
return ToolSchema(**params).dict()
@abstractmethod
async def execute(self, **kwargs) -> Dict:
"""實際執行功能"""
pass
4. 錯誤處理:讓工具更可靠
就像家用電器需要防水、防震、防過載一樣,工具也需要完善的保護機制。
4.1 錯誤分類和處理
想象你在處理快遞:
- 地址寫錯了 → 引數錯誤
- 系統維護中 → 服務暫時不可用
- 快遞員太忙了 → 需要限流重試
class ToolError(Exception):
"""工具錯誤基類"""
def __init__(self, message: str, error_code: str, retry_after: Optional[int] = None):
self.message = message
self.error_code = error_code
self.retry_after = retry_after
@error_handler
async def execute(self, **kwargs):
try:
# 執行具體操作
result = await self._do_work(**kwargs)
return {"status": "success", "data": result}
except ValidationError:
# 引數錯誤,就像地址寫錯了
return {"status": "error", "code": "INVALID_PARAMS"}
except RateLimitError as e:
# 需要限流,就像快遞員太忙
return {
"status": "error",
"code": "RATE_LIMIT",
"retry_after": e.retry_after
}
4.2 重試機制
就像遇到快遞派送失敗會自動安排第二次派送:
class RetryableTool(BaseTool):
@retry(
stop=stop_after_attempt(3), # 最多重試3次
wait=wait_exponential(multiplier=1, min=4, max=10) # 等待時間遞增
)
async def execute_with_retry(self, **kwargs):
return await self.execute(**kwargs)
5. 效能最佳化:讓工具更高效
5.1 快取機制
就像便利店會把熱門商品放在顯眼的位置:
class CachedSearchTool(BaseTool):
def __init__(self):
self.cache = {} # 簡單的記憶體快取
self.cache_ttl = 3600 # 快取1小時
async def execute(self, query: str):
# 先檢查"貨架"上有沒有
cache_key = f"search:{query}"
if cache_key in self.cache:
return self.cache[cache_key]
# 沒有才去"倉庫"拿
result = await self._do_search(query)
self.cache[cache_key] = result
return result
5.2 併發控制
就像醫院的掛號系統,控制同時服務的人數:
class RateLimiter:
def __init__(self, max_concurrent: int = 5):
self._semaphore = Semaphore(max_concurrent) # 最多同時處理5個請求
@asynccontextmanager
async def acquire(self):
async with self._semaphore:
yield
class ApiTool(BaseTool):
def __init__(self):
self.rate_limiter = RateLimiter(max_concurrent=5)
async def execute(self, **kwargs):
async with self.rate_limiter.acquire():
return await self._call_api(**kwargs)
6. 測試和文件:保證工具可靠性
6.1 單元測試
就像新產品上市前需要質檢:
class TestWeatherTool:
@pytest.mark.asyncio
async def test_normal_weather(self):
"""測試正常天氣查詢"""
tool = WeatherTool()
result = await tool.execute(city="北京")
assert result["status"] == "success"
assert "temperature" in result["data"]
@pytest.mark.asyncio
async def test_invalid_city(self):
"""測試無效城市名"""
tool = WeatherTool()
result = await tool.execute(city="不存在的城市")
assert result["status"] == "error"
6.2 文件規範
就像產品說明書要詳細清晰:
class WeatherTool(BaseTool):
"""
天氣查詢工具
功能:查詢指定城市的實時天氣資訊
使用示例:
```python
tool = WeatherTool()
result = await tool.execute(city="北京")
print(f"溫度: {result['data']['temperature']}°C")
```
注意事項:
1. 城市名必須是有效的中國城市名稱
2. 每分鐘最多查詢 10 次
"""
7. 總結
開發好的 Agent 工具就像打造稱手的工具箱:
- 工具分類要合理 - 同步/非同步各有用途
- 介面要標準 - 便於統一管理
- 要有保護機制 - 處理各種異常情況
- 追求高效 - 該快取快取,該限流限流
- 重視質量 - 測試充分,文件清晰
記住:好的工具能讓 Agent 事半功倍,糟糕的工具會讓 Agent 處處受限。