今天我们介绍 查询管道(Query Pipelines),LlamaIndex 中的新声明式 API,允许你 简洁地编排从简单到复杂的查询工作流程,以满足各种使用场景(如检索增强生成(RAG)、结构化数据提取等)。
这一切的核心就是我们的QueryPipeline
抽象。它可以接受许多 LlamaIndex 模块(大型语言模型、提示、查询引擎、检索器,甚至是 LLM)。它可以为这些模块创建一个计算图(例如顺序链或DAG)。它支持回调,并与我们的可观测性合作伙伴具有原生支持。
最终目标是让在您的数据上构建LLM工作流变得更为简单。请参考我们的介绍指南和文档页面了解更多详情。
一个示例的 QueryPipeline
配置用于高级 RAG 流水线
在过去的一年里,AI工程师们开发了定制化和复杂的编排流程,利用大型语言模型(LLMs,即大型语言模型)来解决各种不同的用例。随着时间的推移,一些常见的模式出现了。在高层次上,形成了查询用户数据的模式——这包括利用RAG(在狭义上指查询非结构化数据)的方法,以及使用text-to-SQL查询结构化数据的方法。其他围绕具体用例出现的模式包括结构化数据提取(例如,提示LLM输出JSON并解析它等等),提示链(如链式思考),和能够与外部服务交互的代理(结合提示链等等)。
在RAG中有大量的查询编排工作。 即使在RAG本身内部,构建一个高性能优化的RAG管道也可能需要大量的工作。从用户的查询开始,我们可能希望运行查询理解/转换(重写/路由)。我们还可能希望运行多阶段检索算法——例如,top-k搜索+重新排序。我们也可以使用提示和大语言模型以不同的方式来合成响应。这里有一篇介绍高级RAG 组件 的精彩博客。
出处:《高级RAG技术:图文综述》(RAG指“检索和生成”),伊万·伊林著,https://pub.towardsai.net/advanced-rag-techniques-an-illustrated-overview-04d193d8fec6
RAG变得更具模块化了: 开发者不再局限于单一的RAG方式,而是根据具体应用场景选择最适合的模块。这种观点也在高伟等人的《RAG综述》论文中有所体现。
这产生了如dsp,Rewrite-Retrieve-Read,或多次交错检索和生成这样的创新模式。
LlamaIndex 的先前情况
LlamaIndex 本身提供了数百个 RAG 指南和 16+ 种 Llama Pack 配方,让用户能够设置不同的 RAG 流程(构建高级 RAG 的速查表和一些食谱)(点击查看),并一直走在建立高级 RAG 模式的前沿,引领潮流。
我们也暴露了底层模块,例如LLMs、提示、嵌入模型、后处理,以及包括检索器和查询工具的易于子类化的核心组件,让用户可以自定义工作流。
但到目前为止,我们并没有明确的编排抽象概念。用户需要自己阅读每个模块的 API 文档,定义自己的工作流,将输出转换成适当的输入,以命令式的方式使用这些模块。
查询流程因此,我们的QueryPipeline提供了一个声明式的查询编排工具。你可以用它来构建顺序链和有向无环图(DAG),这些图可以达到各种复杂程度。
你可以用 LlamaIndex 模块来编写这些工作流,但使用 QueryPipeline 可以让你用更少的代码行更高效地实现。
它有以下好处:
- 用更少的代码/样板表达常见的查询工作流程:停止编写输出与输入之间的转换逻辑,以及为每个模块确定参数的确切类型!
- 更好的可读性:减少样板代码能提高可读性。
- 端到端可观测性:在整个管道中获得回调集成(即使对于任意嵌套的DAG),你再也不用担心处理我们的可观测性集成了。
- [未来功能]易于序列化:声明式接口让核心组件能够更容易地在其他系统中进行序列化和重新部署。
- [未来功能]缓存:此接口还使我们能够构建底层缓存层,从而允许输入重用。
通过 networkx
和 pyvis
将我们高级的 RAG 查询管道进行可视化展示
用法
#
查询管道(Query Pipeline)允许你用LlamaIndex模块基于DAG的查询流程。主要有两种用法:
- 作为顺序链(最简单/最简洁的)
- 作为完整的DAG形式(更富有表现力)
请查阅我们的使用指南以获取更多详情。
顺序链条有些简单的管道完全是线性的,即前一个模块的输出直接进入下一个模块的输入。
这里有几个例子:
- 提示词 → LLM → 输出解析器
- 检索模块 → 响应合成
下面是一个最简单的例子,将提示与LLM链接起来。只需用chain
参数初始化QueryPipeline
即可。
# 尝试链式生成基本提示
prompt_str = "请生成与{movie_name}相关的电影"
# PromptTemplate是提示模板类
prompt_tmpl = PromptTemplate(prompt_str)
llm = OpenAI(model='gpt-3.5-turbo') # OpenAI(model="gpt-3.5-turbo")保持英文,作为技术术语
# QueryPipeline是查询流水线类,chain参数定义了处理步骤
p = QueryPipeline(chain=[prompt_tmpl, llm], verbose=True)
设置高级RAG工作流的DAG配置
通常设置查询工作流需要使用底层函数来构建一个DAG。
例如,要构建一个“高级RAG”,可以包括查询重写、检索、重新排名和合成等步骤。
从 llama_index.postprocessor 导入 CohereRerank
从 llama_index.response_synthesizers 导入 TreeSummarize
从 llama_index 导入 ServiceContext
# 定义组件模块
prompt_str = "请根据以下主题{topic}生成一个关于Paul Graham生活的问题。"
prompt_tmpl = PromptTemplate(prompt_str)
llm = OpenAI(model="gpt-3.5-turbo")
retriever = index.as_retriever(similarity_top_k=3)
reranker = CohereRerank()
summarizer = TreeSummarize(
service_context=ServiceContext.from_defaults(llm=llm)
)
# 定义查询流程
p = QueryPipeline(verbose=True)
p.add_modules(
{
"llm": llm,
"prompt_tmpl": prompt_tmpl,
"retriever": retriever,
"summarizer": summarizer,
"reranker": reranker,
}
)
# 添加链接
p.add_link("prompt_tmpl", "llm")
p.add_link("llm", "retriever")
p.add_link("retriever", "reranker", dest_key="nodes")
p.add_link("llm", "reranker", dest_key="query_str")
p.add_link("reranker", "summarizer", dest_key="nodes")
p.add_link("llm", "summarizer", dest_key="query_str")
在这个代码块里,我们首先添加模块,然后定义这些模块之间的关系。注意,source_key
和 dest_key
是可选的,仅在第一个模块有多个输出或第二个模块有多个输入时才需要。
如果管道有一个“根”节点和一个输出端口,则使用 run
。如之前的例子所示,
output = p.run(topic="YC")
# output 的类型是 Response
# 这将返回一个 Response 类型的对象
type(output)
如果有多个根结点和 / 或多个输出节点,请使用 run_multi
output_dict = p.run_multi({"llm": {"topic": "YC"}})
print(output_dict)
创建自定义查询模块
继承 CustomQueryComponent
非常简单,你可以轻松地将它插入到 QueryPipeline 中。
查看我们的入门指南[此处插入链接],了解更多详情。
以下列出支持的模块:当前支持以下 LlamaIndex 模块在 QueryPipeline 中。记住,你可以定义自己的模块!
- 大型语言模型(LLM,包括完成任务和聊天)
- 提示模板(
PromptTemplate
) - 查询引擎(用于处理查询的引擎,
BaseQueryEngine
) - 查询转换(
BaseQueryTransform
) - 检索器(用于检索信息,
BaseRetriever
) - 输出解析器(用于解析输出内容,
BaseOutputParser
) - 后处理器/重组器(
BaseNodePostprocessor
) - 响应合成器(用于合成响应,
BaseSynthesizer
) - 其他QueryPipeline相关对象
- 自定义组件(可自定义的组件,
CustomQueryComponent
)
查看模块使用说明了解更多详情。
示例漫步务必查看一下我们的查询管道入门指南,以查看详情。我们在上面详细介绍了所有步骤,并提供了具体示例!
笔记本指南也会通过Arize Phoenix记录痕迹。你可以在Phoenix控制台中查看每个QueryPipeline的完整运行。我们提供的全面回调支持贯穿整个QueryComponent,让你能够轻松地与任何可观测性提供商集成。
相关研究使用声明性语法构建LLM驱动管道的想法并不新鲜。相关工作包括Haystack以及LangChain 表达式语言。其他相关工作还包括无代码/低代码环境中的管道,例如Langflow / Flowise。
我们在这里的主要目标如前所述:提供一个方便的开发者用户体验,以定义数据上的常见查询流程。这里还有很多可以优化和指导的地方呢!
FAQ查询管道(QueryPipeline)和摄入管道(IngestionPipeline)之间的有什么区别?
很好的问题,您问到了点子上。目前,IngestionPipeline 在数据摄入阶段工作,而 QueryPipeline 则在查询阶段工作。说起来,我们或许会为两者开发一些共享的抽象层!
结论和资源就这样!正如之前提到的,我们很快就会增加更多的资源和指南。在此同时,可以看看我们现在提供的指南:
共同学习,写下你的评论
评论加载中...
作者其他优质文章