Agents Course documentation

什么是工具?

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

什么是工具?

Unit 1 planning

AI 智能体的关键能力在于执行行动。正如前文所述,这通过工具的使用实现。

本节将学习工具的定义、有效设计方法,以及如何通过系统消息将其集成到智能体中。

通过为智能体配备合适的工具——并清晰描述这些工具的工作原理——可显著提升 AI 的能力边界。让我们深入探讨!

AI 工具的定义

工具是赋予 LLM 的函数,该函数应实现明确的目标

以下是 AI 智能体中常用的工具示例:

工具类型 描述
网络搜索 允许智能体从互联网获取最新信息
图像生成 根据文本描述生成图像
信息检索 从外部源检索信息
API 接口 与外部 API 交互(GitHub、YouTube、Spotify 等)

以上仅为示例,实际可为任何用例创建工具!

优秀工具应能补充 LLM 的核心能力

例如,若需执行算术运算,为 LLM 提供计算器工具将比依赖模型原生能力获得更好结果。

此外,LLM 基于训练数据预测提示的补全,意味着其内部知识仅包含训练截止前的信息。因此,若智能体需要最新数据,必须通过工具获取。

例如,若直接询问 LLM(无搜索工具)今日天气,LLM 可能会产生随机幻觉。

Weather
  • 合格工具应包含:
    • 函数功能的文本描述
    • 可调用对象(执行操作的实体)
    • 带类型声明的参数
    • (可选)带类型声明的输出

工具如何运作?

正如前文所述,LLM 只能接收文本输入并生成文本输出。它们无法自行调用工具。当我们谈及为智能体提供工具时,实质是教导 LLM 认识工具的存在,并要求模型在需要时生成调用工具的文本。例如,若我们提供从互联网获取某地天气的工具,当询问 LLM 巴黎天气时,LLM 将识别该问题适合使用我们教授的”天气”工具,并生成代码形式的文本来调用该工具。智能体负责解析 LLM 的输出,识别工具调用需求,并执行工具调用。工具的输出将返回给 LLM,由其生成最终用户响应。

工具调用的输出是对话中的另一种消息类型。工具调用步骤通常对用户不可见:智能体检索对话、调用工具、获取输出、将其作为新消息添加,并将更新后的对话再次发送给 LLM。从用户视角看,仿佛 LLM 直接使用了工具,但实际执行的是我们的应用代码(智能体)。

后续课程将深入探讨该流程。

如何为 LLM 提供工具?

完整答案可能看似复杂,但核心是通过系统提示(system prompt)向模型文本化描述可用工具:

System prompt for tools

为确保有效性,必须精准描述:

  1. 工具功能
  2. 预期输入格式

因此工具描述通常采用结构化表达方式(如编程语言或 JSON)。虽非强制,但任何精确、连贯的格式均可。

若觉抽象,我们通过具体示例理解。

我们将实现简化的计算器工具,仅执行两整数相乘。Python 实现如下:

def calculator(a: int, b: int) -> int:
    """Multiply two integers."""
    return a * b

因此我们的工具名为calculator,其功能是将两个整数相乘,需要以下输入:

  • aint):整数
  • bint):整数

工具输出为另一个整数,描述如下:

  • int):ab的乘积

所有这些细节都至关重要。让我们将这些信息整合成 LLM 可理解的工具描述文本:

工具名称: calculator,描述:将两个整数相乘。参数:a: int, b: int,输出:int

重要提示: 此文本描述是我们希望 LLM 了解的工具体系

当我们将上述字符串作为输入的一部分传递给 LLM 时,模型将识别其为工具,并知晓需要传递的输入参数及预期输出。

若需提供更多工具,必须保持格式一致性。此过程可能较为脆弱,容易遗漏某些细节。

是否有更好的方法?

自动化工具描述生成

我们的工具采用 Python 实现,其代码已包含所需全部信息:

  • 功能描述性名称:calculator
  • 详细说明(通过函数文档字符串实现):将两个整数相乘
  • 输入参数及类型:函数明确要求两个int类型参数
  • 输出类型

这正是人们使用编程语言的原因:表达力强、简洁且精确。

虽然可以将 Python 源代码作为工具规范提供给 LLM,但具体实现方式并不重要。关键在于工具名称、功能描述、输入参数和输出类型。

我们将利用 Python 的自省特性,通过源代码自动构建工具描述。只需确保工具实现满足:

  1. 使用类型注解(Type Hints)
  2. 编写文档字符串(Docstrings)
  3. 采用合理的函数命名

完成这些之后,我们只需使用一个 Python 装饰器来指示calculator函数是一个工具:

@tool
def calculator(a: int, b: int) -> int:
    """Multiply two integers."""
    return a * b

print(calculator.to_string())

注意函数定义前的@tool装饰器。

通过我们即将看到的实现,可以利用装饰器提供的to_string()方法从源代码自动提取以下文本:

工具名称: calculator,描述:将两个整数相乘。参数:a: int, b: int,输出:int

正如所见,这与我们之前手动编写的内容完全一致!

通用工具类实现

我们创建通用Tool类,可在需要时重复使用:

说明: 此示例实现为虚构代码,但高度模拟了主流工具库的实际实现方式。

class Tool:
    """
    A class representing a reusable piece of code (Tool).
    
    Attributes:
        name (str): Name of the tool.
        description (str): A textual description of what the tool does.
        func (callable): The function this tool wraps.
        arguments (list): A list of argument.
        outputs (str or list): The return type(s) of the wrapped function.
    """
    def __init__(self, 
                 name: str, 
                 description: str, 
                 func: callable, 
                 arguments: list,
                 outputs: str):
        self.name = name
        self.description = description
        self.func = func
        self.arguments = arguments
        self.outputs = outputs

    def to_string(self) -> str:
        """
        Return a string representation of the tool, 
        including its name, description, arguments, and outputs.
        """
        args_str = ", ".join([
            f"{arg_name}: {arg_type}" for arg_name, arg_type in self.arguments
        ])
        
        return (
            f"Tool Name: {self.name},"
            f" Description: {self.description},"
            f" Arguments: {args_str},"
            f" Outputs: {self.outputs}"
        )

    def __call__(self, *args, **kwargs):
        """
        Invoke the underlying function (callable) with provided arguments.
        """
        return self.func(*args, **kwargs)

虽然看似复杂,但逐步解析即可理解其工作机制。我们定义的Tool类包含以下核心要素:

  • namestr):工具名称
  • descriptionstr):工具功能简述
  • functioncallable):工具执行的函数
  • argumentslist):预期输入参数列表
  • outputsstrlist):工具预期输出
  • __call__():调用工具实例时执行函数
  • to_string():将工具属性转换为文本描述

可通过如下代码创建工具实例:

calculator_tool = Tool(
    "calculator",                   # name
    "Multiply two integers.",       # description
    calculator,                     # function to call
    [("a", "int"), ("b", "int")],   # inputs (names and types)
    "int",                          # output
)

但我们可以利用 Python 的inspect模块自动提取这些信息!这正是@tool装饰器的实现原理。

若感兴趣,可展开以下内容查看装饰器具体实现:

decorator code
def tool(func):
    """
    A decorator that creates a Tool instance from the given function.
    """
    # Get the function signature
    signature = inspect.signature(func)
    
    # Extract (param_name, param_annotation) pairs for inputs
    arguments = []
    for param in signature.parameters.values():
        annotation_name = (
            param.annotation.__name__ 
            if hasattr(param.annotation, '__name__') 
            else str(param.annotation)
        )
        arguments.append((param.name, annotation_name))
    
    # Determine the return annotation
    return_annotation = signature.return_annotation
    if return_annotation is inspect._empty:
        outputs = "No return annotation"
    else:
        outputs = (
            return_annotation.__name__ 
            if hasattr(return_annotation, '__name__') 
            else str(return_annotation)
        )
    
    # Use the function's docstring as the description (default if None)
    description = func.__doc__ or "No description provided."
    
    # The function name becomes the Tool name
    name = func.__name__
    
    # Return a new Tool instance
    return Tool(
        name=name, 
        description=description, 
        func=func, 
        arguments=arguments, 
        outputs=outputs
    )

简而言之,在应用此装饰器后,我们可以按如下方式实现工具:

@tool
def calculator(a: int, b: int) -> int:
    """Multiply two integers."""
    return a * b

print(calculator.to_string())

我们可以使用Tool类的to_string方法自动生成适合LLM使用的工具描述文本:

工具名称: calculator,描述:将两个整数相乘。参数:a: int, b: int,输出:int

该描述将被注入系统提示。以本节初始示例为例,替换tools_description后的系统提示如下:

System prompt for tools

Actions章节,我们将深入探讨智能体如何调用刚创建的这个工具。


工具在增强AI智能体能力方面至关重要。

总结本节要点:

  • 工具定义:通过提供清晰的文本描述、输入参数、输出结果及可调用函数

  • 工具本质:赋予LLM额外能力的函数(如执行计算或访问外部数据)

  • 工具必要性:帮助智能体突破静态模型训练的局限,处理实时任务并执行专业操作

现在进入【智能体工作流】(agent-steps-and-structure)章节,您将看到智能体如何观察、思考与行动。这整合了当前所学全部内容,为创建功能完备的 AI 智能体奠定基础。

但在此之前,让我们先完成另一个简短测验!

< > Update on GitHub