Skip to content
LlamaIndex 文档版本 跟随上游 源快照 1a40720c 更新于 2026-10-15

数据已加载、索引已建好、索引也存下来备用了,现在可以进入 LLM 应用最关键的一环:查询。

最简单的情形下,查询就是向 LLM 发一次提示词调用:可以是有问有答,可以是请求摘要,也可以是复杂得多的指令。

更复杂的查询会涉及反复/链式的提示词 + LLM 调用,甚至在多个组件之间走一轮推理循环。

入门

一切查询的基础是 QueryEngine。获得 QueryEngine 最省事的办法是让索引替你创建一个,就像这样:

query_engine = index.as_query_engine()
response = query_engine.query(
    "Write an email to the user given their background information."
)
print(response)

查询的阶段

不过,查询并不像看上去那么直白,它由三个各不相同的阶段组成:

  • 检索(Retrieval):从你的 Index 中找到并返回与查询最相关的文档。如前文索引所讨论的,最常见的检索方式是“top-k”语义检索,但检索策略远不止这一种。
  • 后处理(Postprocessing):对检索到的 Node 可选地做重排、变换或过滤,例如要求它们带有特定的元数据(如关键词)。
  • 响应合成(Response synthesis):把查询、最相关的数据和提示词组合起来交给 LLM,由它给出回答。

提示

关于如何给文档附加元数据以及给节点附加元数据,可以查看对应说明。

定制查询的各个阶段

LlamaIndex 提供了一套低层组合 API,让你对查询拥有细粒度的控制。

这个例子里,我们把检索器的 top_k 改成另一个数值,并加一道后处理:只有达到最低相似度分数的节点才会被保留。这样一来,有相关结果时你会拿到很多数据,而没有任何相关内容时可能一条都拿不到。

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

# build index
index = VectorStoreIndex.from_documents(documents)

# configure retriever
retriever = VectorIndexRetriever(
    index=index,
    similarity_top_k=10,
)

# configure response synthesizer
response_synthesizer = get_response_synthesizer()

# assemble query engine
query_engine = RetrieverQueryEngine(
    retriever=retriever,
    response_synthesizer=response_synthesizer,
    node_postprocessors=[SimilarityPostprocessor(similarity_cutoff=0.7)],
)

# query
response = query_engine.query("What did the author do growing up?")
print(response)

你也可以通过实现相应的接口,加入自己的检索、响应合成以及整体的查询逻辑。

已实现的组件清单与支持的配置项,请看我们的参考文档。

下面逐个步骤细说怎么定制:

配置检索器

retriever = VectorIndexRetriever(
    index=index,
    similarity_top_k=10,
)

检索器的种类非常多,可以在我们的检索器模块指南里逐一了解。

配置节点后处理器

我们支持进阶的 Node 过滤与增强,可以进一步提升检索到的 Node 对象的相关性。这有助于减少 LLM 调用的次数与耗时(也就是成本),或者提升回答质量。

例如:

  • KeywordNodePostprocessor:按 required_keywords 与 exclude_keywords 过滤节点。
  • SimilarityPostprocessor:通过设定相似度分数阈值来过滤节点(因此仅适用于基于嵌入的检索器)
  • PrevNextNodePostprocessor:依据 Node 之间的关联关系,为检索到的 Node 补充额外的相关上下文。

节点后处理器的完整清单记录在节点后处理器参考里。

按需要配置节点后处理器:

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:依次遍历每个检索到的 Node,以“先生成再修正”的方式作答;每个 Node 都会单独调用一次 LLM。适合更详细的回答。
  • compact:在每次 LLM 调用时“压缩”提示词,把尽可能多的 Node 文本块塞进提示词长度上限之内。如果块太多塞不进一个提示词,就用多个提示词走“先生成再修正”。
  • tree_summarize:给定一组 Node 对象和查询,递归构造一棵树,并把根节点作为最终回答。适合做摘要。
  • no_text:只运行检索器,取回本来要发给 LLM 的节点,但并不真的发送。之后可以通过 response.source_nodes 查看。响应对象的更多细节见第 5 节。
  • accumulate:给定一组 Node 对象和查询,把该查询分别应用到每个 Node 文本块上,并把回答累积到一个数组里。返回所有回答拼接后的字符串。适合需要把同一个查询逐块分别执行的情形。

结构化输出

你可能希望输出是结构化的。如何从查询引擎类中抽取一个 Pydantic 对象,见我们的 Query Engines + Pydantic 输出。

也别忘了看我们完整的结构化输出指南。

创建你自己的查询工作流

想要设计复杂的查询流程,可以在众多模块之间自由组合出自己的查询工作流——从提示词/LLM/输出解析器,到检索器、响应合成器,再到你自己的自定义组件。

更多细节见我们的工作流指南。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。