Skip to content

工具集#

概念#

构建LlamaIndex中的智能体系统的核心在于拥有恰当的工具抽象层。定义一组工具类似于定义任何API接口,不同之处在于这些工具是供智能体而非人类使用的。我们允许用户定义工具(Tool)以及包含一系列底层函数的工具规范(ToolSpec)

当使用具备函数调用能力的智能体或大语言模型时,工具的选择(以及为该工具编写的参数)高度依赖于工具名称工具用途及参数的描述。花时间调整这些参数可以显著改变大语言模型调用这些工具的方式。

工具实现了非常通用的接口——只需定义__call__方法并返回一些基本元数据(名称、描述、函数模式)。

我们提供以下几种不同类型的工具:

  • FunctionTool:函数工具允许用户轻松将任何自定义函数转换为工具。它可以自动推断函数模式,也支持自定义各个细节。
  • QueryEngineTool:封装现有查询引擎的工具。注意:由于我们的智能体抽象继承自BaseQueryEngine,这些工具也可以封装其他智能体。
  • 社区贡献的ToolSpecs,围绕单一服务(如Gmail)定义一个或多个工具
  • 实用工具,用于封装其他工具以处理从工具返回的大量数据

函数工具#

函数工具是对现有函数(同步和异步均支持!)的简单封装。

from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.tools import FunctionTool


def get_weather(location: str) -> str:
    """Usfeful for getting the weather for a given location."""
    ...


tool = FunctionTool.from_defaults(
    get_weather,
    # async_fn=aget_weather,  # optional!
)

agent = ReActAgent(llm=llm, tools=tools)

为了更好的函数定义,您还可以利用Annotated类型来指定参数描述。

from typing import Annotated


def get_weather(
    location: Annotated[
        str, "A city name and state, formatted like '<name>, <state>'"
    ],
) -> str:
    """Useful for getting the weather for a given location."""
    ...


tool = FunctionTool.from_defaults(get_weather)

默认情况下,工具名称将是函数名称,文档字符串将作为工具描述。但您也可以覆盖这些设置。

tool = FunctionTool.from_defaults(get_weather, name="...", description="...")

查询引擎工具#

任何查询引擎都可以通过QueryEngineTool转换为工具:

from llama_index.core.tools import QueryEngineTool

tool = QueryEngineTool.from_defaults(
    query_engine, name="...", description="..."
)

工具规范#

我们还通过LlamaHub 🦙提供丰富的工具和工具规范集。

您可以将工具规范视为需要一起使用的工具包。通常这些规范涵盖单个接口/服务的有用工具,比如Gmail。

要与智能体一起使用,您可以安装特定的工具规范集成:

pip install llama-index-tools-google

然后使用它:

from llama_index.core.agent.workflow import FunctionAgent
from llama_index.tools.google import GmailToolSpec

tool_spec = GmailToolSpec()
agent = FunctionAgent(llm=llm, tools=tool_spec.to_tool_list())

完整社区贡献的工具规范列表请参见LlamaHub

实用工具#

通常情况下,直接查询API可能会返回大量数据,这些数据本身可能会溢出大语言模型的上下文窗口(或者至少不必要地增加您使用的令牌数量)。

为了解决这个问题,我们在LlamaHub Tools中提供了一组初始的"实用工具"——实用工具在概念上不与特定服务(如Gmail、Notion)绑定,而是可以增强现有工具的能力。在这个特定情况下,实用工具有助于抽象出从任何API请求返回的数据需要缓存/索引和查询的常见模式。

让我们来看看下面两个主要的实用工具。

按需加载工具#

此工具将任何现有的LlamaIndex数据加载器(BaseReader类)转换为智能体可以使用的工具。该工具可以使用触发数据加载器load_data所需的所有参数以及自然语言查询字符串进行调用。在执行期间,我们首先从数据加载器加载数据,为其建立索引(例如使用向量存储),然后"按需"查询它。这三个步骤都在一个工具调用中完成。

通常情况下,这比弄清楚如何自己加载和索引API数据更可取。虽然这可能允许数据可重用性,但用户通常只需要一个临时索引来抽象掉任何API调用的提示窗口限制。

下面给出一个使用示例:

pip install llama-index-readers-wikipedia
from llama_index.readers.wikipedia import WikipediaReader
from llama_index.core.tools.ondemand_loader_tool import OnDemandLoaderTool

tool = OnDemandLoaderTool.from_defaults(
    reader,
    name="Wikipedia Tool",
    description="A tool for loading data and querying articles from Wikipedia",
)

加载与搜索工具规范#

LoadAndSearchToolSpec接受任何现有工具作为输入。作为工具规范,它实现了to_tool_list,当调用该函数时,会返回两个工具:一个load工具和一个search工具。

load工具的执行将调用底层工具,并为输出建立索引(默认使用向量索引)。search工具的执行将接受查询字符串作为输入并调用底层索引。

这对于默认情况下会返回大量数据的任何API端点都很有帮助——例如我们的WikipediaToolSpec默认会返回整个维基百科页面,这很容易溢出大多数大语言模型的上下文窗口。

示例用法如下所示:

pip install llama-index-tools-wikipedia
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.tools.tool_spec.load_and_search import (
    LoadAndSearchToolSpec,
)
from llama_index.tools.wikipedia import WikipediaToolSpec


wiki_spec = WikipediaToolSpec()
# Get the search wikipedia tool
tool = wiki_spec.to_tool_list()[1]

# Create the Agent with load/search tools
agent = FunctionAgent(
    llm=llm, tools=LoadAndSearchToolSpec.from_defaults(tool).to_tool_list()
)

直接返回#

您会注意到工具类构造函数中的return_direct选项。如果设置为True,则智能体的响应会直接返回,而不会被智能体解释和重写。这有助于减少运行时间,或者设计/指定将结束智能体推理循环的工具。

例如,假设您指定了一个工具:

tool = QueryEngineTool.from_defaults(
    query_engine,
    name="<name>",
    description="<description>",
    return_direct=True,
)

agent = FunctionAgent(llm=llm, tools=[tool])

response = await agent.run("<question that invokes tool>")

在上面的例子中,查询引擎工具将被调用,该工具的响应将直接作为响应返回,执行循环将结束。

如果使用return_direct=False,则智能体会根据聊天历史记录重写响应,甚至可能进行另一个工具调用。

我们还提供了一个示例笔记本来展示return_direct的使用。

调试工具#

通常,调试发送到API的工具定义到底是什么会很有用。

您可以通过使用底层函数获取当前工具模式来很好地了解这一点,这在OpenAI和Anthropic等API中被利用。

schema = tool.metadata.get_parameters_dict()
print(schema)