工具集#
概念#
构建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)