Agent工具使用

工具使用能力是Agent突破LLM固有局限的关键。通过工具,Agent可以获取实时信息、 执行计算、操作文件、调用外部服务,极大地扩展了Agent的能力边界。 本文将深入探讨工具定义、选择策略和执行机制。

预计阅读时间:55分钟·难度:中级

工具使用概述

为什么需要工具

大语言模型虽然具备强大的语言理解和生成能力,但存在固有局限:

  • 知识截止:训练数据有时间截止点,无法获取最新信息
  • 计算能力弱:复杂计算容易出错,不适合精确数学运算
  • 无外部交互:无法直接访问网络、文件系统、数据库等
  • 幻觉问题:可能生成不准确或虚构的信息
  • 无执行能力:只能生成文本,无法执行实际操作

工具使用(Tool Use)正是解决这些局限的关键机制。通过工具,Agent可以:

工具带来的能力扩展

  • 获取实时数据(天气、新闻、股价等)
  • 执行精确计算和数据处理
  • 访问和操作文件系统
  • 调用外部API和服务
  • 执行代码和脚本
  • 与数据库交互
  • 发送邮件、消息等通知
  • 控制物理设备(通过API)

工具带来的能力

能力类别示例工具应用场景
信息获取搜索引擎、知识库查询实时新闻、事实核查
数据处理计算器、数据分析财务计算、统计分析
文件操作文件读写、格式转换文档处理、代码编辑
外部服务API调用、数据库操作业务系统集成
代码执行Python执行器、Shell自动化脚本、数据处理

工具定义

定义规范

工具定义需要遵循特定规范,使LLM能够理解工具的功能和正确使用方法。 主流LLM平台(OpenAI、Claude等)都采用类似的定义格式。

OpenAI Function Calling 格式

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "获取指定城市的当前天气信息。当用户询问天气相关问题时使用此工具。",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "城市名称,如'北京'、'上海'"
        },
        "unit": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"],
          "description": "温度单位,默认摄氏度",
          "default": "celsius"
        }
      },
      "required": ["city"]
    }
  }
}

Claude Tool Use 格式

{
  "name": "get_weather",
  "description": "获取指定城市的当前天气信息",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "城市名称"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"],
        "description": "温度单位"
      }
    },
    "required": ["city"]
  }
}

参数设计

参数设计原则

  • 必要的设为必填:执行工具必须的参数设为required
  • 提供默认值:可选参数提供合理的默认值
  • 使用枚举限制:限定取值范围的参数使用enum
  • 描述要清晰:每个参数都需要清晰的description
  • 避免过度复杂:参数结构尽量简单,避免深层嵌套
  • 考虑验证需求:设计时考虑参数验证的便利性

复杂参数示例

{
  "name": "search_products",
  "description": "搜索商品信息",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "搜索关键词"
      },
      "filters": {
        "type": "object",
        "description": "筛选条件",
        "properties": {
          "price_range": {
            "type": "object",
            "properties": {
              "min": { "type": "number", "description": "最低价格" },
              "max": { "type": "number", "description": "最高价格" }
            }
          },
          "category": {
            "type": "string",
            "description": "商品分类"
          },
          "brand": {
            "type": "string",
            "description": "品牌名称"
          }
        }
      },
      "sort_by": {
        "type": "string",
        "enum": ["price_asc", "price_desc", "rating", "sales"],
        "description": "排序方式"
      },
      "limit": {
        "type": "integer",
        "description": "返回结果数量",
        "default": 10,
        "minimum": 1,
        "maximum": 100
      }
    },
    "required": ["query"]
  }
}

工具类型

搜索类工具

搜索工具是Agent最常用的工具类型之一,用于获取实时信息和知识。

常见搜索工具

  • 网络搜索:Google/Bing搜索API、DuckDuckGo
  • 知识库搜索:向量数据库检索、全文搜索
  • 文档搜索:PDF解析、网页内容提取
  • 数据库查询:SQL生成与执行

计算类工具

计算工具用于执行数学计算、数据处理等需要精确性的任务。

计算工具类型

  • 基础计算器:四则运算、数学函数
  • 代码执行器:Python解释器、沙箱环境
  • 数据分析:统计分析、可视化
  • 单位转换:货币、度量衡、时区

文件类工具

文件操作工具示例

# 文件读取工具
{
  "name": "read_file",
  "description": "读取文件内容",
  "parameters": {
    "type": "object",
    "properties": {
      "path": { "type": "string", "description": "文件路径" },
      "encoding": { "type": "string", "default": "utf-8" }
    },
    "required": ["path"]
  }
}

# 文件写入工具
{
  "name": "write_file",
  "description": "写入内容到文件",
  "parameters": {
    "type": "object",
    "properties": {
      "path": { "type": "string", "description": "文件路径" },
      "content": { "type": "string", "description": "文件内容" },
      "mode": { 
        "type": "string", 
        "enum": ["write", "append"],
        "default": "write"
      }
    },
    "required": ["path", "content"]
  }
}

API类工具

API工具用于调用外部服务和系统,是Agent与外部世界交互的主要方式。

API工具分类

  • REST API:HTTP请求,支持GET/POST/PUT/DELETE
  • GraphQL:灵活的查询语言,按需获取数据
  • SDK封装:将第三方SDK封装为工具
  • 数据库API:ORM操作、原生SQL

工具选择策略

选择流程

Agent选择工具的过程是一个推理决策过程,通常包括以下步骤:

工具选择流程

1. 分析任务需求
   ↓
2. 匹配工具描述
   - 遍历可用工具列表
   - 将任务需求与工具description匹配
   ↓
3. 选择最合适的工具
   - 可能有多个候选工具
   - 根据上下文选择最佳匹配
   ↓
4. 构造参数
   - 从上下文中提取参数值
   - 验证参数类型和约束
   ↓
5. 执行工具调用
   ↓
6. 解析返回结果

选择优化

提高工具选择准确性的方法

  • 优化工具描述:清晰描述工具的用途和使用场景
  • 工具分类:按功能分类,减少选择范围
  • 示例驱动:提供工具使用的示例
  • 上下文增强:在提示中提供更多上下文信息
  • 反馈学习:记录选择错误,持续优化

工具执行机制

执行流程

完整执行流程

# Agent工具执行循环

while not task_complete:
    # 1. LLM分析当前状态,决定下一步行动
    response = llm.generate(
        messages=conversation_history,
        tools=available_tools
    )
    
    # 2. 检查是否需要调用工具
    if response.tool_calls:
        for tool_call in response.tool_calls:
            # 3. 验证工具和参数
            tool = get_tool(tool_call.name)
            validated_params = validate(
                tool_call.arguments,
                tool.parameters_schema
            )
            
            # 4. 执行工具
            try:
                result = tool.execute(validated_params)
            except ToolExecutionError as e:
                result = {"error": str(e)}
            
            # 5. 将结果添加到对话历史
            conversation_history.append({
                "role": "tool",
                "name": tool_call.name,
                "content": serialize(result)
            })
    else:
        # 没有工具调用,返回最终答案
        return response.content

错误处理

常见错误类型

  • 参数错误:缺少必填参数、类型不匹配、值超出范围
  • 执行错误:网络超时、服务不可用、权限不足
  • 结果错误:返回格式异常、数据为空、结果不符合预期
  • 超时错误:执行时间超过限制

错误处理策略

def execute_with_retry(tool, params, max_retries=3):
    """带重试的工具执行"""
    for attempt in range(max_retries):
        try:
            # 参数验证
            validated = validate_params(params, tool.schema)
            
            # 执行工具
            result = tool.execute(validated)
            
            # 结果验证
            if validate_result(result):
                return {"success": True, "data": result}
            else:
                return {"success": False, "error": "Invalid result"}
                
        except ValidationError as e:
            return {"success": False, "error": f"参数错误: {e}"}
            
        except TimeoutError:
            if attempt < max_retries - 1:
                continue  # 重试
            return {"success": False, "error": "执行超时"}
            
        except Exception as e:
            return {"success": False, "error": str(e)}

安全考虑

输入验证

严格验证所有工具输入,防止注入攻击。 特别是文件路径、SQL语句、Shell命令等高风险参数。

权限控制

为工具设置最小必要权限。限制可访问的文件、目录、API端点。

敏感信息保护

不在工具调用日志中记录敏感信息。 对API密钥、密码等进行脱敏处理。

执行隔离

代码执行应在沙箱环境中进行,限制系统资源和网络访问。

代码示例

LangChain工具定义示例

from langchain.tools import tool
from pydantic import BaseModel, Field

# 使用Pydantic定义参数模型
class SearchInput(BaseModel):
    query: str = Field(description="搜索关键词")
    num_results: int = Field(default=5, description="返回结果数量")

# 使用装饰器定义工具
@tool("search_web", args_schema=SearchInput)
def search_web(query: str, num_results: int = 5) -> str:
    """
    搜索互联网获取最新信息。
    当需要查询实时数据、新闻、具体事实时使用此工具。
    """
    # 实际搜索逻辑
    results = perform_search(query, num_results)
    return format_results(results)

# 使用工具
from langchain.agents import create_openai_functions_agent
from langchain_openai import ChatOpenAI

tools = [search_web]
llm = ChatOpenAI(model="gpt-4-turbo")
agent = create_openai_functions_agent(llm, tools)

最佳实践

1. 提供清晰的工具描述

工具描述应该明确说明功能、使用场景和限制, 帮助LLM正确选择和使用工具。

2. 设计合理的参数结构

参数应该直观易懂,避免过度复杂。 提供合理的默认值和清晰的描述。

3. 实现完善的错误处理

对所有可能的错误情况进行处理, 返回有意义的错误信息,帮助Agent调整策略。

4. 控制工具数量

避免一次提供过多工具。工具过多会增加选择难度, 建议按场景分组提供,或使用工具选择机制。

5. 记录和分析工具使用

记录工具调用日志,分析使用模式, 持续优化工具定义和选择策略。

----