在 LlamaIndex 的 ReActAgent 中,tool
和 tool_retriever
都是重要组件,但它们在代理的工作流程中服务于不同的目的:
工具是代理可以执行的实际函数或操作。每个工具:
工具检索器是一个帮助代理根据当前上下文或查询找到合适工具的组件。它:
功能:
在工作流程中的角色:
实现方式:
当 ReActAgent 处理查询时:
这种分离允许代理更高效地运行,尤其是当有许多潜在工具可用时。工具检索器防止代理在每次查询时都必须考虑每一个可能的工具。
基于搜索结果,我将详细介绍如何在 LlamaIndex 中创建工具检索器(Tool Retriever)。工具检索器是一个重要组件,可以帮助代理根据当前查询选择最合适的工具。
首先,需要创建基本的索引和检索器,这些将作为工具检索器的基础组件:
在 LlamaIndex 中,可以从各种索引(如 SummaryIndex、VectorIndex 或 KeywordIndex)创建检索器。例如:
# 创建基础索引
summary_index = SummaryIndex(nodes, storage_context=storage_context)
vector_index = VectorStoreIndex(nodes, storage_context=storage_context)
keyword_index = SimpleKeywordTableIndex(nodes, storage_context=storage_context)
# 从索引创建检索器
list_retriever = summary_index.as_retriever()
vector_retriever = vector_index.as_retriever()
keyword_retriever = keyword_index.as_retriever()
接下来,将这些检索器转换为检索工具(RetrieverTool),这样它们就可以被工具检索器使用:
from llama_index.core.tools import RetrieverTool
list_tool = RetrieverTool.from_defaults(
retriever=list_retriever,
description=(
"用于检索文档的所有上下文,适合需要完整背景信息的查询"
),
)
vector_tool = RetrieverTool.from_defaults(
retriever=vector_retriever,
description=(
"用于检索文档中的特定上下文,适合具体问题"
),
)
keyword_tool = RetrieverTool.from_defaults(
retriever=keyword_retriever,
description=(
"使用查询中提到的实体来检索文档中的特定上下文"
),
)
这里的描述非常重要,因为工具检索器将基于这些描述来选择合适的工具。
选择器决定使用哪些检索工具。LlamaIndex 提供了几种选择器:
from llama_index.core.selectors import PydanticSingleSelector, PydanticMultiSelector
from llama_index.llms.openai import OpenAI
# 初始化LLM
llm = OpenAI(model="gpt-4")
# 创建单选择器(只选择一个工具)
single_selector = PydanticSingleSelector.from_defaults(llm=llm)
# 或者创建多选择器(可以选择多个工具)
multi_selector = PydanticMultiSelector.from_defaults(llm=llm)
最后,使用选择器和检索工具创建工具检索器:
from llama_index.core.retrievers import RouterRetriever
# 创建只选择一个工具的检索器
single_retriever = RouterRetriever(
selector=PydanticSingleSelector.from_defaults(llm=llm),
retriever_tools=[list_tool, vector_tool, keyword_tool],
)
# 或者创建可以选择多个工具的检索器
multi_retriever = RouterRetriever(
selector=PydanticMultiSelector.from_defaults(llm=llm),
retriever_tools=[list_tool, vector_tool, keyword_tool],
)
如果需要更高级的功能,还可以创建自定义检索器,例如混合搜索检索器:
from llama_index.core import QueryBundle
from llama_index.core.schema import NodeWithScore
from llama_index.core.retrievers import BaseRetriever
from typing import List
class CustomRetriever(BaseRetriever):
"""自定义混合检索器,可以结合向量检索和关键词检索"""
def __init__(
self,
vector_retriever,
keyword_retriever,
mode: str = "AND" # 可以设置为 "AND" 或 "OR"
) -> None:
self._vector_retriever = vector_retriever
self._keyword_retriever = keyword_retriever
if mode not in ("AND", "OR"):
raise ValueError("无效的模式,必须是 AND 或 OR")
self._mode = mode
super().__init__()
def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
"""根据查询检索节点"""
# 获取两种检索器的结果
vector_nodes = self._vector_retriever.retrieve(query_bundle)
keyword_nodes = self._keyword_retriever.retrieve(query_bundle)
# 获取节点ID
vector_ids = {n.node.node_id for n in vector_nodes}
keyword_ids = {n.node.node_id for n in keyword_nodes}
# 合并结果
combined_dict = {n.node.node_id: n for n in vector_nodes}
combined_dict.update({n.node.node_id: n for n in keyword_nodes})
# 根据模式选择结果
if self._mode == "AND":
# 两种检索器都检索到的节点
retrieve_ids = vector_ids.intersection(keyword_ids)
else: # OR模式
# 任一检索器检索到的节点
retrieve_ids = vector_ids.union(keyword_ids)
return [combined_dict[rid] for rid in retrieve_ids]
还可以创建递归检索器,它能够递归地检索和查询节点:
from llama_index.core.retrievers import RecursiveRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core import get_response_synthesizer
# 创建递归检索器
recursive_retriever = RecursiveRetriever(
"vector", # 指定根检索器的ID
retriever_dict={"vector": vector_retriever}, # 映射 ID 到检索器
query_engine_dict=query_engine_mapping, # 映射 ID 到查询引擎
verbose=True,
)
# 创建响应合成器
response_synthesizer = get_response_synthesizer(response_mode="compact")
# 创建查询引擎
query_engine = RetrieverQueryEngine.from_args(
recursive_retriever,
response_synthesizer=response_synthesizer
)
创建完工具检索器后,可以直接使用它来检索节点:
# 使用检索器检索节点
nodes = retriever.retrieve("你的查询")
# 异步方式
nodes = await retriever.aretrieve("你的查询")
# 查看结果
for node in nodes:
print(node.node.text)
工具检索器会根据查询自动选择最合适的检索工具,然后使用该工具检索相关节点。对于多选择器,它可能会选择多个工具并合并结果。
创建工具检索器的关键步骤是:
这种方法使代理能够智能地选择最合适的检索工具,从而提高检索效率和准确性。