为了账号安全,请及时绑定邮箱和手机立即绑定

基于LlamaIndex工作流和Groq实现高级RAG系统的方法

简介

AI应用包括各种由不同组件执行的任务。为了简化AI工程师的工作,开源框架提供了用户友好的抽象,用于如数据加载器、大型语言模型(LLMs)、向量数据库和重排序器等核心组件,并涵盖了外部服务。这些框架正在探索最有效的方式来整合这些组件,重点是让开发者能够以最直观和高效的方式构建统一的AI系统。

在考虑的编排方式中包括链和管道流程,它们都基于有向无环图(DAG)模型。

今年年初(2024年),LlamaIndex 推出了我们的查询管线,这是一个声明式 API,旨在方便各种查询工作流的编排,适用于问题回答、结构化数据提取和自动化流程等应用程序。然而,在尝试通过集成循环来增强其功能,以支持更复杂的查询工作流时,我们遇到了一些挑战。这促使我们重新考虑有向无环图模型在代理环境中的适用性,并在我们的框架内探索替代方案,以适应更复杂的场景。

这导致了对工作流的探索过程。工作流是一种新的代理实现方式。它采用事件驱动架构。

基于图的框架的局限性是什么。

基于图或DAG的方法,如LangGraph(以及我们之前的查询管道方案),需要做大量的幕后工作来确定这些。所有这些逻辑处理了大量的特殊情况。这在我们日益复杂的查询管道代码中变得越来越明显。

有向无环图(DAGs)的背景下,无环特性意味着没有循环,这在日益自主的人工智能应用中可能具有限制性。开发人员需要能够实现自我修正机制来应对组件表现不佳的问题。即使不引入循环,查询管道也面临着许多挑战:

  • 调试难题:识别问题变得繁琐。
  • 执行过程不透明:组件的执行流程不够透明。
  • 编排变得过于复杂:编排器变得过于复杂,需要管理许多边界情况。
  • 可读性问题:复杂的管线难以读懂。

当循环被加入到查询管道时,这些问题变得更加突出。遇到了显著的痛点,比如:

  • 复杂的逻辑: 核心的编排逻辑,比如 if-else 和 while 循环,杂乱地散布在图的边,使得代码冗长。
  • 处理边界情况: 处理可选和默认值变得复杂,因为不清楚上游节点是否会传递这些参数。
  • 自然流程的中断: 定义包含循环的图对开发基于代理系统的开发者来说感觉很不自然。需要明确指定“代理”节点的输入和输出边,导致与其他节点之间的通信变得冗长。

为了解决上述问题,LlamaIndex 提出了一种新的设计范式转变,称为 Workflows(工作流),这是一种事件驱动的架构。

什么是工作流程?

这是一种通过事件来触发步骤,从而控制应用程序执行流程的方法。应用程序被分解为多个步骤,每个步骤在相应的事件触发时执行。

步骤其实就是Python中的函数。比如,它们可以是简单的单行代码,也可以是多行的复杂代码。

事件实际上是指任何我们可以注意到、观察到或记录下来的变化或情况。

通过结合步骤与事件,我们可以创建任意复杂的工作流程,封装逻辑性,从而使应用程序更容易维护和理解。

总之,工作流(以及事件驱动的编程方式)提供了更强大的解决方案。代码内部更加简单,因为现在完全由用户来决定接下来运行哪些步骤,如何进行调试,这大大减少了这些问题。如我们之前的查询管道等其他方式相比,这种做法大大减少了“黑盒子”问题。

LlamaIndex 工作流相比 LangGraph 有什么优势?

LlamaIndex工作流程提供了一些独特的特性和功能,使其与LangGraph区别开来,

  1. 数据连接器: 从各种原生来源(如API、PDF和SQL数据库)导入数据的工具。
  2. 数据索引: 将数据结构化为易于大型语言模型(LLM)消费的高效中间表示形式。
  3. 引擎: 不同类型的引擎用于通过自然语言访问数据:
  • 例如,查询引擎:主要用于回答问题的界面,比如RAG(检索和生成)管道。
  • 例如,聊天引擎:用于多轮对话的聊天界面。

4. 代理:由LLM增强的知识型工作者,包括简单的助手函数和API集成。ReActAgent实现定义了一组工具,这些工具可以是Python函数或LlamaIndex查询引擎中的任意一种,以对数据进行自动化推理和处理

5. 可观察性/评估: 用于应用程序严格实验、评估和监控的集成.

6.LlamaCloud:LlamaCloud提供全方位的数据解析、摄取、索引和检索服务,其中包括领先的文档解析解决方案LlamaParse.

7. 社区与生态系统: 活跃的社区,比如用于自定义数据连接器的LlamaHub和用于快速启动项目的create-llama。

  1. 集成灵活性:既支持入门级又支持自定义构建。用户可以使用llama-index快速入门,或者使用llama-index-core从LlamaHub添加特定集成,LlamaHub提供了超过300个集成包以上。

9. 高级检索和查询界面: 提供一个高级界面,用于输入大型语言模型 (LLM) 的提示,并检索上下文和增强知识的输出结果.

10. 初学者和高级用户易用性: 初学者可以使用高级API,只需几行代码即可导入并查询数据,而高级用户则可以使用底层API来自定义和扩展模块的功能。

11. 代理组件:能够自动对您的数据进行推理的核心模块,这些核心模块本质上就像代理一样。例如,SubQuestionQueryEngine 可用于多文档分析、查询转换、路由和LLM重新排序.

12. 原生的OpenAIAgent: 包含一个基于OpenAI API实现的OpenAIAgent,允许快速开发代理功能.

13. 与其他框架的集成: 可以在其他代理框架中作为工具使用,如LangChain和ChatGPT,提供紧密集成并带来额外功能。

这些功能使LlamaIndex成为一个全面的框架,基于大规模语言模型构建增强上下文的生成式AI应用。

设计工作流,

我们将使用LlamaIndex工作流在这里实现一个高级的RAG系统。

  1. 对数据创建索引
  2. 使用该索引和查询来检索相关文本片段
  3. 根据原始查询对检索到的文本片段进行重新排序
  4. 合成最终回复

高级RAG(检索增强生成)工作流程

为实现所使用的技术堆栈

代码实现部分

先安装所需的依赖

    pip install -qU llama-index   # 安装快速更新的 llama-index 包
    pip install -qU llama-index-llms-groq   # 安装快速更新的 llama-index-llms-groq 包
    pip install -qU llama-index-embeddings-huggingface   # 安装快速更新的 llama-index-embeddings-huggingface 包
    pip install -qU llama-index-utils-workflow   # 确保你安装了最新的 llama-index-utils-workflow 包
    pip install python-dotenv   # 安装 python-dotenv 包
    pip install pyvis   # 安装 pyvis 包

2. 创建一个.env文件存放API密钥

GROQ_API_KEY = 你的 API 密钥(你的)

3.: 配置 Groq_API_Key.

导入 os
# 从 dotenv 模块导入 load_dotenv 函数
load_dotenv()  # 从 .env 文件加载环境变量。
os.getenv("GROQ_API_KEY")

4. 导入所需的依赖

    from llama_index.core import VectorStoreIndex  
    from llama_index.core.schema import NodeWithScore  
    from llama_index.core.response_synthesizers import CompactAndRefine  
    from llama_index.core import SimpleDirectoryReader  
    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,  
        Event  
    )  
    from llama_index.core.workflow.utils import get_steps_from_class, get_steps_from_instance  
    from llama_index.llms.groq import Groq  
    from llama_index.embeddings.huggingface import HuggingFaceEmbedding

5., 设置工作流中的事件。

为了处理这些步骤,我们需要定义一些事件。

  1. 传递给重排器的获取节点的事件
  2. 传递给合成器的排序节点的事件

    其他步骤会用到内置的StartEventStopEvent事件。

    class RetrieverEvent(Event):  
        """检索的结果"""  
        nodes: list[NodeWithScore]  # NodeWithScore  

    class RerankEvent(Event):  
        """重排检索节点的结果"""  
        nodes: list[NodeWithScore]  # NodeWithScore

6. 设置工作流程

    class RAGWorkflow(Workflow):  
        @step  
        async def ingest(self, ctx: Context, ev: StartEvent) -> StopEvent | None:  
            """文档的入口点,由带有 `dirname` 属性的 StartEvent 触发。"""  
            dirname = ev.get("dirname")  
            if not dirname:  
                return None  

            documents = SimpleDirectoryReader(dirname).load_data()  
            index = VectorStoreIndex.from_documents(  
                documents=documents,  
                embed_model=HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5"),  
            )  
            return StopEvent(result=index)  

        @step  
        async def retrieve(  
            self, ctx: Context, ev: StartEvent  
        ) -> RetrieverEvent | None:  
            """RAG 的入口点,由带有 `query` 属性的 StartEvent 触发。"""  
            query = ev.get("query")  
            index = ev.get("index")  

            if not query:  
                return None  

            print(f"使用 {query} 查询数据库。")  

            # 将查询保存到全局上下文中  
            await ctx.set("query", query)  

            # 从全局上下文中获取索引信息  
            if index is None:  
                print("索引为空,加载一些文档后再进行查询!")  
                return None  

            retriever = index.as_retriever(similarity_top_k=2)  
            nodes = await retriever.aretrieve(query)  
            print(f"检索到了 {len(nodes)} 个节点。")  
            return RetrieverEvent(nodes=nodes)  

        @step  
        async def rerank(self, ctx: Context, ev: RetrieverEvent) -> RerankEvent:  
            # 重新排序节点的过程  
            ranker = LLMRerank(  
                choice_batch_size=5, top_n=3,   
                llm=Groq(model="llama-3.1-70b-versatile")  
            )  
            print(await ctx.get("query", default=None), flush=True)  
            new_nodes = ranker.postprocess_nodes(  
                ev.nodes, query_str=await ctx.get("query", default=None)  
            )  
            print(f"重新排序节点为 {len(new_nodes)}")  
            print(new_nodes)  
            return RerankEvent(nodes=new_nodes)  

        @step  
        async def synthesize(self, ctx: Context, ev: RerankEvent) -> StopEvent:  
            """使用重新排序的节点生成流式响应。"""  
            llm = Groq(model="llama-3.1-70b-versatile")  
            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)
  1. 检查步骤是否正确执行
    # 检查是否有 __step_config 属性,因为这里的重点是检查属性本身,而不是特定的步骤。
    workflow = RAGWorkflow()
    steps = get_steps_from_class(RAGWorkflow)
    if not steps:
        steps = get_steps_from_instance(workflow)
    print(f"步骤:{steps}")
    for step_name, step_func in steps.items():
        step_config = getattr(step_func, "__step_config", None)
        print(f"配置信息:{step_config}")
        if step_config is None:
            print(f"步骤 {step_name} 缺少 __step_config 属性")

回复

    步骤定义:{'_done': <function 步骤完成 at 0x000001BD6E5F3880>, 'ingest': <function 数据摄入 at 0x000001BD07DEAB60>, 'rerank': <function 重新排序 at 0x000001BD07DEA160>, 'retrieve': <function 检索 at 0x000001BD07DEA5C0>, 'synthesize': <function 合成 at 0x000001BD07DEA0C0>}  
    配置:接受事件=[<class 'llama_index.core.workflow.events.StopEvent'>] 事件名称='ev' 返回类型=[<class 'NoneType'>] 上下文参数='ctx' 工作线程数=1 请求服务=[]  
    配置:接受事件=[<class 'llama_index.core.workflow.events.StartEvent'>] 事件名称='ev' 返回类型=[<class 'llama_index.core.workflow.events.StopEvent'>] 上下文参数='ctx' 工作线程数=1 请求服务=[]  
    配置:接受事件=[<class '__main__.RetrieverEvent'>] 事件名称='ev' 返回类型=[<class '__main__.RerankEvent'>] 上下文参数='ctx' 工作线程数=1 请求服务=[]  
    配置:接受事件=[<class 'llama_index.core.workflow.events.StartEvent'>] 事件名称='ev' 返回类型=[<class '__main__.RetrieverEvent'>] 上下文参数='ctx' 工作线程数=1 请求服务=[]  
    配置:接受事件=[<class '__main__.RerankEvent'>] 事件名称='ev' 返回类型=[<class 'llama_index.core.workflow.events.StopEvent'>] 上下文参数='ctx' 工作线程数=1 请求服务=[]

8. 调用工作流并将其可视化

    import nest_asyncio  
    nest_asyncio.apply()  

    # 可视化  
    from llama_index.utils.workflow import draw_all_possible_flows, draw_most_recent_execution  

    # 绘制流程  
    draw_all_possible_flows(RAGWorkflow, filename="multi_step_workflow.html")  

    # 画出最近的执行流程  
    w = RAGWorkflow()  

    # 加载文档  
    index = await w.run(dirname="Data")  
    result = await w.run(query="什么是纤维肌痛?", index=index)  
    async for chunk in result.async_response_gen():  
        print(chunk, end="", flush=True)  
    draw_most_recent_execution(w, filename="rag_flow_recent.html")

回复

查询数据库:纤维肌痛是什么?
检索到2个节点。
纤维肌痛是什么?
将节点重新排序为2
[NodeWithScore(node=TextNode(id_='abde4b4c-b787-4003-acf5-2f5bd05d867c', embedding=None, metadata={'page_label': '137', 'file_name': 'fibromyalgia.pdf', 'file_path': 'c:\\Users\\PLNAYAK\\Documents\\workflow\\Data\\fibromyalgia.pdf', 'file_type': 'application/pdf', 'file_size': 632664, 'creation_date': '2024-09-09', 'last_modified_date': '2024-09-09'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='7b100860-f0b3-445b-b5d6-21f021d8c3c0', node_type=<ObjectType.DOCUMENT: '4'>, metadata={'page_label': '137', 'file_name': 'fibromyalgia.pdf', 'file_path': 'c:\\Users\\PLNAYAK\\Documents\\workflow\\Data\\fibromyalgia.pdf', 'file_type': 'application/pdf', 'file_size': 632664, 'creation_date': '2024-09-09', 'last_modified_date': '2024-09-09'}, hash='65d90d8fae093e6a574c784e808701ce0596d595e3e6136f7f0b4a70be8d2b57'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='7edbd742-55e9-4559-9e9f-55d8688c6e62', node_type=<ObjectType.TEXT: '1'>, metadata={}, hash='08366d434882c9ea475468bcff6e0fe183d4192c93617ec3cf3700cf03fd5a65')}, text='2023年2月 ◆ 第107卷,第2期  www.aafp.org/afp 《美国家庭医学杂志》137纤维肌痛的特点是弥漫性肌肉骨骼疼痛、疲劳、睡眠不佳和其他躯体症状。1全球约有10%到15%的成年人患有慢性弥漫性疼痛,其中许多人可能患有纤维肌痛。\n2,3 约2%的美国人患有纤维肌痛,尽管患病率因人群和诊断标准的不同而有所差异。\n3,4 纤维肌痛可以影响儿童和成人,在世界各地和各种文化中都有发现。女性的诊断频率高于男性;一项苏格兰调查发现,女性的诊断频率比男性高两倍到十四倍不等,取决于使用的标准。\n3,4 过去十年诊断标准的变化,包括特定触痛点的消除,导致更多患有慢性疼痛的患者符合纤维肌痛的诊断标准。\n3-5\n病理生理学\n纤维肌痛可能是由中枢疼痛信号处理紊乱引起的,导致高敏和痛觉过敏,这与慢性疼痛状况如肠易激综合症、间质性膀胱炎、慢性盆腔疼痛和慢性下背痛相似。\n6,7 功能性脑成像表明,这种异常处理可能归因于兴奋性和抑制性神经递质之间的不平衡,特别是在岛叶。\n8 建议的病因包括下丘脑-垂体-肾上腺轴和自主神经系统功能障碍、弥漫性炎症、小胶质细胞激活、小纤维神经病以及感染如EB病毒、莱姆病和病毒性肝炎。\n9 双胞胎研究表明,遗传因素也可能是影响因素之一。10纤维肌痛:诊断和管理\nBradford T. Winslow,医学博士,科罗拉多大学医学院,科罗拉多州奥罗拉;瑞典家庭医学住院医师,科罗拉多州恩格尔伍德\nCarmen Vandal,医学博士,和Laurel Dang,医学博士,瑞典家庭医学住院医师,科罗拉多州恩格尔伍德\n CME 本文的临床内容符合AAFP的CME标准。如需CME测验,请参阅第127页。\n作者披露:无相关财务利益。\n患者信息:本文作者撰写的关于该主题的手册可在该文章的在线版本中找到。\n纤维肌痛是一种慢性中枢性疼痛综合症,特点是疼痛刺激处理紊乱。纤维肌痛在女性中诊断频率较高,全球范围内均有发现,影响2%的美国人。纤维肌痛患者表现出弥漫性慢性疼痛、睡眠不佳、疲劳、认知功能障碍和情绪紊乱。可能伴随的功能性躯体综合症、精神障碍和风湿病等共病状况也可能存在。对于有弥漫性慢性疼痛的患者,可通过纤维肌痛快速筛查工具进行筛查。可使用美国风湿病学会标准或Analgesic、Anesthetic和Addiction临床试验转化创新机会和网络-美国疼痛学会疼痛分类标准来诊断纤维肌痛。建立诊断并进行教育可以安抚患者,减少不必要的检测。多学科方法结合非药物疗法和药物来缓解症状最为有效。患者教育、锻炼和认知行为疗法可改善疼痛和功能。度洛西汀、米纳普兰、普瑞巴林和阿米替林可能是治疗纤维肌痛的有效药物。而非甾体抗炎药和阿片类药物对纤维肌痛没有显示出益处,且存在显著局限性。\n(Am Fam Physician\n. 2023; 107(2): 137-144. 版权 © 2023 American Academy of Family Physicians.)\n插图由Jonathan Dimes绘制\n从《美国家庭医学杂志》网站www.aafp.org/afp下载。版权 © 2023 American Academy of Family Physicians。仅供个人非商业使用。所有其他权利保留。如需版权问题或请求授权,请联系copyrights@aafp.org。下载自美国家庭医师网站www.aafp.org/afp。版权 © 2023 American Academy of Family Physicians。', mimetype='text/plain', start_char_idx=0, end_char_idx=4397, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n'), score=10.0), NodeWithScore(node=TextNode(id_='0a680a09-1f8d-409e-bbdc-b562b4879f6f', embedding=None, metadata={'page_label': '138', 'file_name': 'fibromyalgia.pdf', 'file_path': 'c:\\Users\\PLNAYAK\\Documents\\workflow\\Data\\fibromyalgia.pdf', 'file_type': 'application/pdf', 'file_size': 632664, 'creation_date': '2024-09-09', 'last_modified_date': '2024-09-09'}, excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'], relationships={<NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='f2591e71-4fd5-48ef-8c08-ab465fdabf88', node_type=<ObjectType.DOCUMENT: '4'>, metadata={'page_label': '138', 'file_name': 'fibromyalgia.pdf', 'file_path': 'c:\\Users\\PLNAYAK\\Documents\\workflow\\Data\\fibromyalgia.pdf', 'file_type': 'application/pdf', 'file_size': 632664, 'creation_date': '2024-09-09', 'last_modified_date': '2024-09-09'}, hash='e0f0653ead2af78ad773abacd139db824a7e40216476d9aa63077b83a7370686')}, text='138 《美国家庭医学杂志》www.aafp.org/afp  第107卷,第2期  ◆ 2023年2月\n纤维肌痛\n临床表现\n慢性弥漫性疼痛是大多数纤维肌痛患者的首要症状。患者还可能经历肌肉僵硬和触痛。纤维肌痛患者的体格检查通常发现弥漫性触痛,而没有其他异常发现。如果有关节肿胀、炎症或畸形,应考虑其他或额外的诊断。\n5\n疲劳和睡眠障碍也很常见。5,11 睡眠障碍包括难以入睡、保持睡眠或在睡眠后感觉未得到充分恢复。5,6,12 认知症状如注意力不集中、健忘或思维改变也很常见。患者将这种认知障碍称为“fibrofog”,描述为精神变慢,影响日常活动。\n13\n同时存在其他疼痛性疾病并不排除纤维肌痛的诊断。纤维肌痛快速筛查工具可以用于筛查有弥漫性慢性疼痛的患者,帮助区分纤维肌痛和其他状况(表1)。\n14 该工具可SORT: 关键实践建议\n临床建议 证据评级 评论\n对于患有弥漫性疼痛、疲劳和睡眠障碍至少三个月的患者,应考虑纤维肌痛的诊断。\n5,11 纤维肌痛的诊断可以使用AAPT 2019诊断标准或美国风湿病学会2011/2016标准\n纤维肌痛患者应采用多学科治疗方法,包括教育、锻炼和非药物和药物选项。\n27,28C 共识指南和系统评价\n认知行为疗法可以在短期内改善纤维肌痛患者的疼痛和残疾。\n32,34,35A 系统评价显示改善效果\n阿米替林、环苯扎林、度洛西汀(Cymbalta)、米纳普兰(Savella)和普瑞巴林(Lyrica)在纤维肌痛疼痛治疗上有效。\n43,46-48,50,52,54A 系统评价显示这些药物有效\nAAPT = Analgesic、Anesthetic和Addiction临床试验转化创新机会和网络-美国疼痛学会疼痛分类。\nA = 一致、高质量的患者导向证据;B = 不一致或低质量的患者导向证据;C = 共识、疾病导向证据、常规实践、专家意见或个案系列。有关SORT证据评级系统的更多信息,请访问 https://www.aafp.org/afpsort。\n表1\n纤维肌痛快速筛查工具(FiRST)\n是\n我全身都有疼痛。\n我的疼痛伴随着持续而非常不愉快的持续疲劳。\n我的疼痛感觉像是烧灼、电击或抽筋。\n我的疼痛伴随着其他身体上的异常感觉,如针刺、刺痛或麻木。\n我的疼痛伴随着其他健康问题,如消化问题、泌尿问题、头痛或不安腿综合症。\n我的疼痛对我的生活产生了重大影响,特别是在我的睡眠和我的注意力方面,使我整体感觉迟钝。\n总计*\n*—每个“是”答案得1分。总分5分或以上提示纤维肌痛。\n改编自 Perrot S, Bouhassira D, Fermanian J; CEDR (Cercle d’Étude de la Douleur en Rhumatologie)。纤维肌痛快速筛查工具(FiRST)的开发和验证。Pain。2010;150(2):255。\n下载自ClinicalKey.es Elsevier于2023年3月24日,供National Library of Health and Social Security Boletin-BINASSS (bolet-binas@binasss.sa.cr) 使用。版权 ©2023 Elsevier Inc.保留所有权利。', mimetype='text/plain', start_char_idx=0, end_char_idx=3975, text_template='{metadata_str}\n\n{content}', metadata_template='{key}: {value}', metadata_seperator='\n'), score=8.0)]  
纤维肌痛是一种慢性中央性疼痛综合症,特点是疼痛刺激处理紊乱。它表现为弥漫性肌肉骨骼疼痛、疲劳、睡眠不佳和其他躯体症状。

可视化工作流程

工作流程观察
  • 我们有两个入口点,即接受 StartEvent 的步骤
  • 各步骤自己决定何时运行
  • 工作流上下文用来保存用户的查询信息
  • 节点被传递,最终返回一个流式响应
RAGWorkflow :
  • 工作流由StartEvent触发。
  • StartEvent触发ingest步骤,将文档索引化、切分并加载到向量存储中。
  • ingest步骤返回生成的索引,此步骤由StopEvent关闭,从而结束该步骤。
  • StartEvent然后触发检索步骤,输入包括查询和索引。
  • 检索步骤触发RetrieverEvent,返回与查询匹配的节点。
  • RetrieverEvent触发重排序步骤,输入为匹配的节点。
  • 重排序步骤按节点与查询的相关性重新排序匹配的节点,并触发RerankEvent
  • RerankEvent然后触发合成步骤,根据重新排序的节点生成最终响应。

当前的流程可视化展示

关于工作流执行的几点看法:

</TRANSLATION>

以下是我根据观察的一些详细见解和建议。

1. Python 3.11.0 的兼容性

观察: 流程和可视化在Python 3.11.0中工作正确.

推荐: Python 3.11.0 支持使用 | 运算符进行类型注释,这简化了类型提示。如果可能,建议使用 Python 3.11.0 或更高版本进行开发,以利用这些功能并避免兼容性问题的困扰。

2. Python 3.9.12 兼容性

观察:在Python 3.9.12里,| 操作符无法使用,你得去修改utils.py里的num_of_events

推荐如下:

类型提示: 在Python 3.9版本中,使用typing模块里的Union,而不是用|操作符进行类型注解。

修复验证: 直接在utils.py中修改num_of_events是一个临时解决方案,但不是理想的方案。相反,确保每个步骤函数恰好有一个使用Event类型注解的参数以通过验证检查。

3. 数据可视化在Google Colab

观察:即使设置了 notebook=True 参数,Google Colab 中的可视化功能也无法正常运行.

推荐:

确保正确安装所有必需的库:确保所有必需的库都已安装在Colab里。

    !pip install pyvis llama-index-core llama-index-llms-openai llama-index-embeddings-openai llama-index-readers-file llama-index-utils-workflow  

    # 渲染HTML的检查:使用以下方法在Colab中渲染HTML内容:  

    from pyvis.network import Network  
    from IPython.core.display import display, HTML  

    def draw_all_possible_flows(  
        workflow: Workflow,  
        filename: str = "workflow_all_flows.html",  
        notebook: bool = True,  # 将notebook设为True  
    ) -> None:  

        net = Network(directed=True, height="750px", width="100%")  

        # 添加停止事件的节点和边  
        net.add_node(  
            StopEvent.__name__,  
            label=StopEvent.__name__,  
            color="#FFA07A",  
            shape="ellipse",  
        )  
        net.add_node("_done", label="_done", color="#ADD8E6", shape="box")  
        net.add_edge(StopEvent.__name__, "_done")  

        # 添加从所有步骤的节点  
        steps = get_steps_from_class(workflow)  
        if not steps:  
            # 如果类中没有定义步骤,则尝试从实例中获取  
            steps = get_steps_from_instance(workflow)  

        step_config: Optional[StepConfig] = None  
        for step_name, step_func in steps.items():  
            step_config = getattr(step_func, "__step_config", None)  
            if step_config is None:  
                continue  

            net.add_node(  
                step_name, label=step_name, color="#ADD8E6", shape="box"  
            )  # 步骤节点用浅蓝色  

            for event_type in step_config.accepted_events:  
                net.add_node(  
                    event_type.__name__,  
                    label=event_type.__name__,  
                    color="#90EE90" if event_type != StartEvent else "#E27AFF",  
                    shape="ellipse",  
                )  # 事件节点用浅绿色  

        # 添加所有步骤的边  
        for step_name, step_func in steps.items():  
            step_config = getattr(step_func, "__step_config", None)  

            if step_config is None:  
                continue  

            for return_type in step_config.return_types:  
                if return_type != type(None):  
                    net.add_edge(step_name, return_type.__name__)  

            for event_type in step_config.accepted_events:  
                net.add_edge(event_type.__name__, step_name)  

        if notebook:  
            net.show(filename, notebook=True)  
            with open(filename, "r") as file:  
                display(HTML(file.read()))  
        else:  
            net.show(filename)  

    # 在Google Colab中的示例用法  
    draw_all_possible_flows(  
        RAGWorkflow, filename="multi_step_workflow.html", notebook=True  
    )

总结

  • Python 3.11.0:与 | 操作符和工作流可视化兼容良好。
  • Python 3.9.12:使用 Union 进行类型注解,并确保正确注解事件参数,以避免修改 utils.py。
  • Google Colab:确保所有依赖项已安装,并使用提供的方法来渲染 HTML 内容。

通过遵循这些建议,你就可以在不同的环境和Python版本间达到一致的功能。

最后说一下

随着人工智能应用变得越来越复杂和具有代理功能,传统有向无环图(DAGs)的局限性变得越来越突出。无法包含循环限制了开发人员实施自我修正机制的能力,这对于保持稳健和适应性强的人工智能系统至关重要。

向前发展,探索能够适应现代AI应用动态性和迭代性的替代框架体系至关重要。通过优先考虑直观的设计和高效的编排,我们能帮助开发者创建更加强大和适应性强的AI系统,这些系统能够从错误中学习并在日益复杂的环境中蓬勃发展。

在这里,我们利用LlamaIndex Workflow实现了一个案例。我们还需要做更多的实验来充分了解它的潜力,并且让它在实现和理解复杂架构时更加简单易懂。

参考链接:
LlamaIndex 工作流 beta 版本:一种创建复杂 AI 应用程序的新方式——LlamaIndex 是一个简单且灵活的数据框架,可以将自定义数据源与大型语言模型 (LLMs) 相连接。www.llamaindex.ai](https://www.llamaindex.ai/blog/introducing-workflows-beta-a-new-way-to-create-complex-ai-applications-with-llamaindex?source=post_page-----bd6047299fa5--------------------------------)
体验全球最快的推断:GroqCloud console.groq.com

注:我在此声明,上述实验均为本人所做,实施时参考了网上的相关资料。

点击这里与我联系

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消