Querying
概念解释
Querying(查询):在加载数据、构建索引并存储索引之后,查询是LLM应用中最重要的一部分。简单来说,查询就是向LLM发送一个提示(prompt),可以是提问并获得答案,请求摘要,或更复杂的指令。
QueryEngine(查询引擎):查询引擎是执行查询的基础。它负责从索引中检索相关文档,对检索到的节点进行后处理,并将查询、相关数据和提示组合发送给LLM以返回响应。
查询的基本步骤
查询过程包括三个主要阶段:
- Retrieval(检索):从索引中找到并返回与查询最相关的文档。最常见的检索类型是“top-k 语义检索”,但还有许多其他检索策略。
- Postprocessing(后处理):对检索到的节点进行可选的重新排序、转换或过滤。例如,要求节点具有特定的元数据(如关键词)。
- Response synthesis(响应合成):将查询、最相关的数据和提示组合并发送给LLM,以返回最终的响应。
获取查询引擎
最简单的方法是让索引为你创建一个查询引擎:
query_engine = index.as_query_engine()
response = query_engine.query(
"Write an email to the user given their background information."
)
print(response)
自定义查询阶段
LlamaIndex 提供了一个低层次的组合API,让你可以对查询过程进行细粒度控制。
示例代码:
from llama_index.core import VectorStoreIndex, get_response_synthesizer
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.postprocessor import SimilarityPostprocessor
# 构建索引
index = VectorStoreIndex.from_documents(documents)
# 配置检索器
retriever = VectorIndexRetriever(
index=index,
similarity_top_k=10,
)
# 配置响应合成器
response_synthesizer = get_response_synthesizer()
# 组装查询引擎
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=response_synthesizer,
node_postprocessors=[SimilarityPostprocessor(similarity_cutoff=0.7)],
)
# 查询
response = query_engine.query("What did the author do growing up?")
print(response)
在这个示例中,我们自定义了检索器以使用不同的 top_k
值,并添加了一个后处理步骤,要求检索到的节点达到最小相似度分数才能被包含。
配置检索器
retriever = VectorIndexRetriever(
index=index,
similarity_top_k=10,
)
有关检索器的更多信息,请参阅检索器模块指南。
配置节点后处理器
我们支持高级的节点过滤和增强,可以进一步提高检索到的节点对象的相关性。例如:
- KeywordNodePostprocessor:通过
required_keywords
和exclude_keywords
过滤节点。 - SimilarityPostprocessor:通过设置相似度分数阈值过滤节点(仅支持基于嵌入的检索器)。
- PrevNextNodePostprocessor:基于节点关系增强检索到的节点对象,添加额外的相关上下文。
完整的节点后处理器列表请参阅节点后处理器参考。
示例代码:
node_postprocessors = [
KeywordNodePostprocessor(
required_keywords=["Combinator"], exclude_keywords=["Italy"]
)
]
query_engine = RetrieverQueryEngine.from_args(
retriever, node_postprocessors=node_postprocessors
)
response = query_engine.query("What did the author do growing up?")
配置响应合成
在检索器获取相关节点后,BaseSynthesizer 将信息组合以合成最终响应。
可以通过以下方式配置:
query_engine = RetrieverQueryEngine.from_args(
retriever, response_mode=response_mode
)
目前支持以下选项:
- default:通过依次处理每个检索到的节点“创建并细化”答案。每个节点都会进行单独的LLM调用。适用于更详细的答案。
- compact:在每次LLM调用中“压缩”提示,尽可能多地填充节点文本块。如果块太多,无法填充到一个提示中,则通过多个提示“创建并细化”答案。
- tree_summarize:给定一组节点对象和查询,递归构建树并返回根节点作为响应。适用于摘要目的。
- no_text:仅运行检索器以获取将发送给LLM的节点,而不实际发送它们。可以通过检查
response.source_nodes
来检查。 - accumulate:给定一组节点对象和查询,将查询应用于每个节点文本块,并将响应累积到一个数组中。返回所有响应的串联字符串。适用于需要对每个文本块单独运行相同查询的情况。
结构化输出
你可能希望确保输出是结构化的。请参阅查询引擎 + Pydantic 输出,了解如何从查询引擎类中提取Pydantic对象。
还可以查看整个结构化输出指南。
创建自己的查询管道
如果希望设计复杂的查询流程,可以在许多不同的模块之间组合自己的查询管道,从提示/LLM/输出解析器到检索器、响应合成器以及自定义组件。
请参阅查询管道模块指南了解更多详细信息。
总结
通过本课程,我们详细讲解了Querying的概念及其在LlamaIndex中的应用。我们介绍了查询的基本步骤、如何获取和自定义查询引擎、配置检索器和节点后处理器、响应合成以及结构化输出。这些内容将帮助学生更好地理解和应用LlamaIndex中的查询功能。