深入解析LlamaIndex Workflows:构建复杂RAG与智能体工作流的新利器【上篇】

面对多样的LLM应用需求,不管是主流如LangChain这样的基础开发框架,还是以云服务提供的低代码开发平台,都试图在提供基础组件抽象的基础上,提供更便捷的组装与编排这些组件的方式,以帮助构建更高级的AI工作流应用。比如年初发布的LangChain新版本中就引入了LangGraph,以帮助构建Graph表示的AI工作流。

最近,另一家主流LLM框架LlamaIndex推出了一项新beta特性:Workflows提供了一种与LangGraph不同、事件驱动的框架,以编排复杂的RAG或Agent应用工作流,支持灵活的分支、并行与循环等处理。

我们将分成两篇来给大家深入解析与介绍LlamaIndex Workflows:

  • Workflows的思想、概念与简单演示

  • 基于Workflows构建多分支与循环的复杂LLM应用

回顾:为什么需要Workflows

以两种主流LLM应用开发框架LangChain与LlamaIndex来看,它们都提供了大量的基础组件封装,将常见的RAG或Agent应用开发中常用到的流程环节进行了抽象,简化了开发并避免锁定到特定的底层设施(如大模型、向量库)。利用它们提供的API可以在极短的时间内开发出大模型应用,比如在LlamaIndex中,几行代码可以快速完成一个RAG原型:

......  
documents = SimpleDirectoryReader("../data").load_data()  
index = VectorStoreIndex.from_documents(documents)  
query_engine = index.as_query_engine()  
response = query_engine.query('你的问题')  
print(response)

但这里的问题是:**当面对复杂的业务与优化需求时,不断出现更多的RAG工作模块与算法(重写、路由、排序、图索引等),如何用最佳的方法来组合与协调这些组件,实现更复杂的工作流程?
**

在框架的早期,可以总结成两种主要方式:

  • **提供更高层的组件与API的封装。**比如简单的向量检索器是VectorIndexRetriever,但现在需要增加路由功能,就封装一个带有路由的RouterRetriever;简单的查询引擎是QueryEngine,但现在需要增加重排功能,就增加一个可以传入Reranker模块的参数。

  • 提供链式或DAG(单向无环图)结构的可编排方法。最具代表性的是LangChain框架中的Chain(链)与LCEL(LangChain表达语言)特性;以及LlamaIndex在年初推出的Query Pipeline(查询管道)声明式API特性。它们都在一定程度上提供了编排能力。

LlamaIndex的Query Pipeline提供了一定的编排能力

尽管如此,这种受限的工作流编排仍然面临较大的局限性:

* **高层的组件或API封装缺乏足够的灵活性。**体现在:

  • 随着需求的复杂化,需要封装更多的高层组件,框架变得更臃肿。

  • 高层组件的内部过于“黑盒”。比如很难对LangChain或LlamaIndex的ReActAgent组件构建的智能体的执行过程做更精细化的控制。

* **链式或DAG结构的流程无法支持循环,限制了使用场景。**但在如今的很多AI工作流中,比如智能体的反思(Relfection)以及一些新的RAG范式(如C-RAG等)都需要循环的支持。

* 不够简洁与直观,也难以调试。

基于这样一些原因,提供一种更强大的工作流定义与编排的支持,也成为了开发框架的发力重点,典型的就是之前介绍过的LangGraph以及本篇将一窥究竟的LlamaIndex Workflows

LlamaIndex Workflows初探

LlamaIndex Workflows是LlamaIndex近期推出(仍然是测试版)的用来替代之前Query Pipeline(查询管道)的新特性。与LangGraph不同的是,其没有采用类似LangCraph基于图结构的流程编排模式,而是采用了一种事件驱动的工作流编排方式:

工作流中的每个环节被作为step(步骤,代表一个处理动作),每个step可以选择接收(类似订阅)一种或多种event(事件)做处理,并同样可以发送一种或多种event给其他step。通过这种方式,把多个step自然的连接起来形成完整的Workflow。

在这种架构中,工作流的运行不是由框架来根据预先的定义(比如Graph)来调度任务组件执行,而是由组件自身决定:你想接收什么event,做什么处理,并发出什么event。如果组件B接受了A发出的某种event,那么B就会在A发出event后触发执行。

看一个这种方式定义的模拟复杂工作流:

图中涉及到LlamaIndex Workflows中的一些关键概念:

  • Workflow(工作流)

工作流代表一个复杂的RAG、Agent或者任意复合形式的LLM应用的端到端流程。创建完工作流后,调用run方法,并输入任务即可启动。

Workflow类似LangGraph中的Graph。

  • Step(步骤)

步骤代表工作流中的单个任务,你可以自由的定义步骤内容。每个步骤接收输入事件(订阅),并返回输出事件。当输入事件发生时,这个步骤就会自动执行。步骤使用Python函数定义。

Step类似LangGraph中的Node。

  • Event(事件)

事件是一个步骤的输入输出,也是工作流各个步骤之间的数据载体。当事件发生时,“订阅”该事件的步骤就会执行,同时从事件中取出必要数据。事件是一个Pydantic类型对象,可以自由定义结构。注意两个特殊事件:

  • StartEvent与StopEvent是两个系统事件,代表工作流开始与结束。

  • StartEvent由框架派发,接收StartEvent的步骤代表工作流的开始。

  • StopEvent由框架接收,发送StopEvent的步骤代表没有后续步骤。

Event是LlamaIndex中连接Step的机制,作用类似LangGraph中的Edge(边),但机制完全不同。

  • Context(上下文

Context是一个用来在整个工作流内自动流转的上下文状态对象,放入Context中的数据可以被所有步骤接收和读取到,可以理解为全局变量。

Context类似LangGraph中的State(状态),但LlamaIndex中各Step的数据交换更多通过event传递,而不是Context。

最后总结:LlamaIndex Workflows是通过一种事件驱动、自我管理的任务组件(step)来组装与编排复杂工作流的方式。此外还具有可视化(生成流程图)、可单步调试、可复用工作流等特性。

Hello,Workflows!

现在我们用LlamaIndex的Workflows来实现一个最简单的带Rerank重排功能的RAG工作流。其工作流程图如下:

这个简单的Workflow反映了一个经典RAG流程的两个工作阶段,索引(indexing)与生成(generate)阶段。这里把两个阶段做成不同的分支,是为了便于一次索引后做多次生成,也体现了Workflows的一个特征:一个Workflow的入口step可以有多个,只要这个step接收StartEvent事件。

看下这个Workflow的简单实现代码:

from llama_index.core.workflow import Event  
from llama_index.core.schema import NodeWithScore  
  
#定义两个事件  
class RetrieverEvent(Event):  
    nodes: list[NodeWithScore]  
  
class RerankEvent(Event):  
    nodes: list[NodeWithScore]  
  
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex  
from llama_index.core.response_synthesizers import CompactAndRefine  
from llama_index.core.postprocessor.llm_rerank import LLMRerank  
from llama_index.core.workflow import (  
    Context,  
    Workflow,  
    StartEvent,  
    StopEvent,  
    step,  
)  
  
from llama_index.llms.openai import OpenAI  
from llama_index.embeddings.openai import OpenAIEmbedding  
  
#workflow定义  
class RAGWorkflow(Workflow):  
    @step  
    async def indexing(self, ctx: Context, ev: StartEvent) -> StopEvent | None:  
        #不带query参数,表示索引阶段  
        if not ev.get("query"):  
            documents = SimpleDirectoryReader(input_files=['../../data/sales_tips1.txt']).load_data()  
            index = VectorStoreIndex.from_documents(documents=documents)  
            print("Indexing complete")  
            return StopEvent(result=index)  
        else:  
            return None  
  
    @step  
    async def retrieve(  
        self, ctx: Context, ev: StartEvent) -> RetrieverEvent | None:  
        #带query参数,表示生成阶段  
        if not ev.get("query"):  
            return None  
          
        query = ev.get("query")  
        index = ev.get("index")  
  
        await ctx.set("query", query)  
        retriever = index.as_retriever(similarity_top_k=2)  
        nodes = await retriever.aretrieve(query)  
        return RetrieverEvent(nodes=nodes)  
  
    @step  
    async def rerank(self, ctx: Context, ev: RetrieverEvent) -> RerankEvent:  
        ranker = LLMRerank(  
            choice_batch_size=5, top_n=3, llm=OpenAI(model="gpt-4o-mini")  
        )  
        new_nodes = ranker.postprocess_nodes(  
            ev.nodes, query_str=await ctx.get("query", default=None)  
        )  
        return RerankEvent(nodes=new_nodes)  
  
    @step  
    async def generate(self, ctx: Context, ev: RerankEvent) -> StopEvent:   
        llm = OpenAI(model="gpt-4o-mini")  
        summarizer = CompactAndRefine(llm=llm, streaming=True, verbose=True)  
        query = await ctx.get("query", default=None)  
  
        response = await summarizer.asynthesize(query, nodes=ev.nodes)  
        return StopEvent(result=response)  
      
w = RAGWorkflow()

代码非常清晰易懂:其中四个函数定义了四个step,各个step之间通过输入的event与返回的event进行连接,并驱动整个工作流的自动运行。这里也能体现Workflows与LangGraph的最大区别:LangGraph通过定义图中的edge来体现流程节点之间的关系;而Workflows则是通过step之间的event传递来体现。

你可以通过如下代码运行工作流并测试:

w = RAGWorkflow()  
  
#索引阶段  
index = await w.run()  
  
#生成阶段,需要带入问题和创建好的索引  
result = await w.run(query="你的问题", index=index)  
async for chunk in result.async_response_gen():  
    print(chunk, end="", flush=True

此外,Workflows提供了工具对定义的Workflow进行可视化,使用如下代码:

from llama_index.utils.workflow import draw_all_possible_flows  
draw_all_possible_flows(  
    RAGWorkflow, filename="RAG.html"  
)

可以生成可视化的工作流程图:

如果你使用过LlamaIndex,可能会觉得这里的代码似乎更复杂化了,这并不意外:Workflows(以及LangChain的LangGraph)显然都是为了更复杂与更灵活化的LLM应用场景而设计,而非简单应用。

下一篇我们将分析如何使用Workflows实现一个复杂的Agent工作流。

在这里插入图片描述

大模型&AI产品经理如何学习

求大家的点赞和收藏,我花2万买的大模型学习资料免费共享给你们,来看看有哪些东西。

1.学习路线图

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己整理的大模型视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。

在这里插入图片描述

在这里插入图片描述

(都打包成一块的了,不能一一展开,总共300多集)

因篇幅有限,仅展示部分资料,需要点击下方图片前往获取

3.技术文档和电子书

这里主要整理了大模型相关PDF书籍、行业报告、文档,有几百本,都是目前行业最新的。
在这里插入图片描述

4.LLM面试题和面经合集

这里主要整理了行业目前最新的大模型面试题和各种大厂offer面经合集。
在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。
在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值