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))

总结

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

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

相关推荐
装不满的克莱因瓶12 分钟前
【SpringAI Alibaba】ReactAgent结构化输出OutputType与OutputSchema实战
java·人工智能·ai·springai·springaialibaba
楚山之石22 分钟前
【Radiology】影像组学的标准化与可重复性:IBSI 卷积滤波器共识及其未能覆盖的环节
人工智能·学习·机器学习·mri
东姬AI28 分钟前
挖出948个内核漏洞、自动写补丁:GPT-6 Cyber把AI推进“实战岗“,内容行业还卡在哪一关?
人工智能·网络安全·openai·gpt-6
用户29914221968035 分钟前
GitHub 热榜项目:日榜(2026-11-10)
人工智能·开源·github
用户29914221968041 分钟前
AI 日报(2026年11月10日)
人工智能
QXWZ_IA1 小时前
定位数据怎么推给 IoT 平台?消息协议选型与接入准备
网络·人工智能·物联网·安全
java_logo1 小时前
Docker 部署 ReMe:轻松搭建 AI Agent 记忆管理平台
人工智能·docker·容器·ai agent·轩辕镜像·reme·agentscope-ai
硅谷秋水1 小时前
从VLM规划器到机器人智能体:面向依赖历史信息的操控任务自演化框架
人工智能·机器学习·语言模型·机器人
西安小哥1 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
Vex2une1 小时前
AI 渲染正在重写游戏美术的账本:提效、外包与新的门槛
人工智能·aigc·游戏美术·神经渲染·dlss 5·ai 渲染·游戏开发门槛