todo:本节内容需要实战,加深理解

使用 QueryEngineTool 转换 query engine 为 tool。

LlamaIndex 有 4 类 tools:

  • FunctionTool :将任何 Python 函数转换为 Agents 可以使用的工具。它自动推断出函数的工作原理。

  • QueryEngineTool :一个允许 Agents 使用 queryEngine 的工具。由于 Agents 是基于 queryEngine 构建的,它们也可以将其他 Agents 作为工具使用。

  • Toolspecs :由社区创建的工具集,通常包含针对特定服务的工具,如 Gmail。

  • Utility Tools: 帮助处理 large amounts of data from other tools. 特指 OnDemandToolLoader & LoadAndSearchToolSpec

Functional Tool

给出工具的 name 和 description 尤其重要,因为它有助于 Agent 理解什么时候应该使用该工具。

from llama_index.core.tools import FunctionTool

def get_weather(location: str) -> str:
    """Useful for getting the weather for a given location."""
    print(f"Getting weather for {location}")
    return f"The weather in {location} is sunny"

tool = FunctionTool.from_defaults(
    get_weather,
    name="my_weather_tool",
    description="Useful for getting the weather for a given location.",
)
tool.call("Shanghai")

QueryEngine Tool

使用 QueryEngineTool 转换 QueryEngine 为 tool:

import chromadb

from llama_index.core import VectorStoreIndex
from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core.tools import QueryEngineTool
from llama_index.vector_stores.chroma import ChromaVectorStore

db = chromadb.PersistentClient(path="./alfred_chroma_db")
chroma_collection = db.get_or_create_collection("alfred")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)

embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
llm = HuggingFaceInferenceAPI(model_name="meta-llama/Llama-3.2-3B-Instruct")

# index 是 RAG 中的一个重要组件
index = VectorStoreIndex.from_vector_store(
    vector_store=vector_store, embed_model=embed_model
)
# 通过index 创建 query Engine
query_engine = index.as_query_engine(llm=llm)

# 使用 QueryEngineTool 转换 query engine 为 tool
tool = QueryEngineTool.from_defaults(
    query_engine=query_engine,
    name="some useful name",
    description="some useful description",
)
await tool.acall(
    "Responds about research on the impact of AI on the future of work and society?"
)

ToolSpecs

Tool spec 是一组相互协作的工具,像一个用于特定目的的专业工具箱

from llama_index.tools.google import GmailToolSpec

tool_spec = GmailToolSpec()
# 返回一个工具对象列表
tool_spec_list = tool_spec.to_tool_list() 
# 返回每个对象的 name 和描述
[print(tool.metadata.name, tool.metadata.description) for tool in tool_spec_list]

返回 一个列表,包含了所以与邮件发送相关的 tools (函数),输出如下:

load_data load_data() -> List[llama_index.core.schema.Document]
Load emails from the user's account.
search_messages search_messages(query: str, max_results: Optional[int] = None)

        Searches email messages given a query string and the maximum number
        of results requested by the user
           Returns: List of relevant message objects up to the maximum number of results.

        Args:
            query (str): The user's query
            max_results (Optional[int]): The maximum number of search results
            to return.

        
create_draft create_draft(to: Optional[List[str]] = None, subject: Optional[str] = None, message: Optional[str] = None) -> str

        Create and insert a draft email.
           Print the returned draft's message and id.
           Returns: Draft object, including draft id and message meta data.

        Args:
            to (Optional[str]): The email addresses to send the message to
            subject (Optional[str]): The subject for the event
            message (Optional[str]): The message for the event
...

这里显示了3个工具:load_data()search_messages()create_draft()

Utility tools

通常,直接查询 API 可能会返回大量数据,其中一些可能无关紧要,溢出 LLM 的上下文窗口,或无谓地增加用户使用 token 的数量。LlamaIndex 中的两个工具用于解决这个问题。

OnDemandToolLoader

它将数据加载器(BaseReader 类)转换为代理可以使用的工具,允许你的 Agent 按需加载、索引和查询数据。

  • 数据加载器转换: 它接收一个 LlamaIndex 数据加载器(例如,用于读取 PDF、网站、数据库等)。
  • 工具化: 将这个数据加载器包装成一个工具,这个工具可以被 Agent 调用。
  • 按需加载:按需 (On-Demand)指数据不是预先加载和索引的,而是在 Agent 需要时才进行加载和索引。
  • 加载、索引和查询: 工具在被调用时,会执行以下步骤:
    1. 加载数据: 使用数据加载器加载数据。
    2. 索引数据: 将加载的数据进行索引,通常使用向量存储(Vector Store)等方法,以便快速查询。
    3. 查询数据: 使用自然语言查询字符串来查询索引后的数据,并返回结果。

使用场景:

  • 大型数据集: 当你的数据集非常大,无法一次性加载到内存中时,可以使用 OnDemandToolLoader 按需加载数据。
  • 动态数据: 当你的数据需要频繁更新时,可以使用 OnDemandToolLoader 确保 Agent 始终访问最新的数据。
  • Agent 工具集成: 当你希望将数据访问能力集成到你的 Agent 中时,可以使用 OnDemandToolLoader 将数据加载器转换为一个工具。

实例:


# 1. 创建一个数据加载器 (例如,读取 PDF 文件)
data_loader = SimpleDirectoryReader(input_dir="./data")
# 2. 创建 OnDemandToolLoader
tool_loader = OnDemandToolLoader.from_loader(data_loader)
# 3. 获取工具
tool = tool_loader.as_tool()
# 4. Agent 可以调用这个工具来查询数据
# 假设 Agent 接收到查询 "What is the main topic of this document?"
response = tool.run("What is the main topic of this document?")

print(response)

LoadAndSearchToolSpec

它的作用是将一个现有的 Tool 转换为两个新的 Tool:一个用于加载数据并索引的 Tool,另一个用于搜索索引数据的 Tool。

工作原理:

  • Tool 包装: 它接收一个现有的 Tool 作为输入。 这个 Tool 可以是任何 LlamaIndex 支持的 Tool,例如用于读取文件、访问 API 等。

  • 生成两个 Tool: LoadAndSearchToolSpec 将原始 Tool 包装成两个新的 Tool:

    1. 加载 Tool (Loading Tool): 这个 Tool 的作用是调用原始 Tool,获取其输出结果,并将结果进行 Indexing (索引可以大大提高搜索效率,特别是对于大型数据集)。 默认情况下,它使用向量索引 (Vector Index) 来索引数据。
    2. 搜索 Tool (Search Tool): 这个 Tool 的作用是接收一个查询字符串作为输入,然后在加载 Tool 创建的索引中进行搜索,并返回结果。
  • to_tool_list 方法: LoadAndSearchToolSpec 实现了 to_tool_list 方法,该方法返回一个包含加载 Tool 和搜索 Tool 的列表。

KAQ:为什么偏偏是 Loading Tool 和 Search Tool,而不是其他功能的 tools

是因为这两个工具对应了 Agent 在多数应用场景中都需要执行的两个关键步骤:获取信息 & 利用信息。

  • 获取信息: Agent 需要从各种数据源获取信息,例如网页、文件、数据库、API 等。然后进行indexing处理。
  • 利用信息: Agent 需要利用获取到的信息来回答用户的问题、执行用户的指令或完成其他任务。