Agent开发第2步:定义工具抽象 (Tools)

在第1步中,我们通过 Model Adapter 赋予了 Agent "思考"和"交流"的能力。然而,纯粹的语言模型只能基于训练数据回答问题,无法获取实时信息或操作外部系统。为了让 Agent 真正变得强大,我们需要为它装上"手和脚"------这就是**工具(Tools)**的作用。

1. 什么是工具抽象?

大语言模型通常支持 Function Calling(函数调用)机制。这意味着模型可以决定何时调用某个特定函数,并要求我们(客户端)执行该函数并将结果返回给它。

为了让 Agent 能够动态加载、管理和执行不同的函数,我们需要定义一套标准的工具抽象(Tool Interface)。每个工具都应该包含:

  1. 工具名称 (Name)
  2. 工具描述 (Description):告诉 LLM 这个工具是干什么的。
  3. 参数 Schema (Parameters):告诉 LLM 调用该工具需要提供哪些参数。
  4. 执行逻辑 (Run/Execute):实际运行的 Python 代码。

2. 工具调用工作流

3. Python 代码实现

我们先定义一个基础的工具类 BaseTool,然后实现具体的工具,例如一个查询天气的工具和一个计算器工具。

定义基础抽象类

python 复制代码
from abc import ABC, abstractmethod
from typing import Dict, Any, Type
from pydantic import BaseModel, Field

class BaseTool(ABC):
    name: str
    description: str
    args_schema: Type[BaseModel]

    @abstractmethod
    def run(self, **kwargs) -> str:
        """执行工具的核心逻辑"""
        pass
    
    def get_function_declaration(self) -> Dict[str, Any]:
        """将工具转换为 LLM 认识的 JSON Schema 格式"""
        return {
            "type": "function",
            "function": {
                "name": self.name,
                "description": self.description,
                "parameters": self.args_schema.model_json_schema()
            }
        }

实现具体工具:天气查询与计算器

python 复制代码
class WeatherArgs(BaseModel):
    location: str = Field(..., description="城市名称,例如:北京, 上海")

class WeatherTool(BaseTool):
    name = "get_weather"
    description = "获取指定城市的当前天气情况"
    args_schema = WeatherArgs

    def run(self, location: str) -> str:
        # 这里可以接入真实的第三方天气 API
        # 为了演示,我们返回 mock 数据
        mock_weather = {
            "北京": "晴朗,25度",
            "上海": "小雨,22度"
        }
        return mock_weather.get(location, f"无法获取 {location} 的天气信息")


class CalculatorArgs(BaseModel):
    expression: str = Field(..., description="数学表达式,例如:2 + 2 * 3")

class CalculatorTool(BaseTool):
    name = "calculator"
    description = "计算数学表达式的结果"
    args_schema = CalculatorArgs

    def run(self, expression: str) -> str:
        try:
            # 警告:实际生产环境中请使用安全的 eval 替代方案
            result = eval(expression)
            return str(result)
        except Exception as e:
            return f"计算错误: {str(e)}"

工具注册与管理

我们需要一个统一的地方来管理这些工具,并在 LLM 请求调用时找到对应的工具实例。

python 复制代码
class ToolRegistry:
    def __init__(self):
        self._tools: Dict[str, BaseTool] = {}

    def register(self, tool: BaseTool):
        self._tools[tool.name] = tool

    def get_all_declarations(self) -> list:
        """获取所有工具的声明,传给 LLM"""
        return [tool.get_function_declaration() for tool in self._tools.values()]

    def execute_tool(self, name: str, kwargs: dict) -> str:
        """根据 LLM 的指令执行对应工具"""
        if name not in self._tools:
            return f"Error: Tool {name} not found."
        
        tool = self._tools[name]
        try:
            # 使用 Pydantic 验证参数
            validated_args = tool.args_schema(**kwargs)
            # 执行工具
            return tool.run(**validated_args.model_dump())
        except Exception as e:
            return f"Tool Execution Error: {str(e)}"

# 初始化注册表并注册工具
registry = ToolRegistry()
registry.register(WeatherTool())
registry.register(CalculatorTool())

# 打印生成的 JSON Schema 给 LLM 看
import json
print(json.dumps(registry.get_all_declarations(), indent=2, ensure_ascii=False))

总结

通过抽象出 BaseToolToolRegistry,我们极大地方便了后续工具的扩展。开发者只需要继承基础类并定义参数 Schema,即可快速将新的能力接入到 Agent 中。

有了大脑(Model Adapter)和手脚(Tools),下一步就是将它们结合起来,让 Agent 自主地进行"思考、调用工具、观察结果、回答"的循环------这就是我们在下一篇要实现的 Agent Loop

相关推荐
桃西西呀1 小时前
换个会话就失忆?拆开 Agent 记忆的 4 层与 4 个流派,附9个坑的自检清单
人工智能·llm·ai编程
桃西西呀1 小时前
风控模型说自己 80% 准,却漏掉了 76% 该拦的人:一次把模型评估讲透
人工智能·机器学习·llm
山铃1 小时前
Agent开发第4步:定义 RunEvent
人工智能
鲜于言悠9051 小时前
2026 AI Agent完整学习路线:6个阶段,从入门到可接商业项目
人工智能
Blockchina1 小时前
从一个 AI 助手到一支 AI 团队:用 Grok Bot 搭建自媒体内容流水线
人工智能
用户2215602767751 小时前
Dify 1.11.4 配置 LLM 深度思考:获取 reasoning_content 并支持前端渲染
人工智能
乱世刀疤1 小时前
WorkBuddy防踩坑指南
人工智能·workbuddy
开开心心就好2 小时前
PDF图片去水印软件,支持批量处理页面
前端·javascript·人工智能·智能手机·pdf·语音识别
深兰科技2 小时前
深兰科技亮相2026全球独角兽大会,获评“2026环卫机器人品类领袖企业”
人工智能·科技·jupyter·vim·腾讯会议·深兰科技·全球独角兽大会