深入了解同一创建者 LangChain 和 LangGraph 的两个库:它们的关键构建块、它们如何处理其功能的核心部分,以及为您的用例在它们之间做出决定
语言模型为用户如何与 AI 系统交互以及这些系统如何通过自然语言相互通信开启了可能性。
在本文中,我们将探讨用于构建代理 AI 应用程序的两个最流行的框架——LangChain 和 LangGraph。在本文结束时,您应该对关键构建块、每个框架在处理其核心功能方面有何不同,并能够形成一个受过教育的观点,了解哪个框架最适合您的问题。
由于将生成式 AI 广泛纳入解决方案的做法相对较新,因此开源参与者正在积极竞争开发“最佳”代理框架和编排工具。这意味着,尽管每个参与者都带来了独特的方法,但他们几乎一直在推出新功能。阅读这篇文章时,请记住,今天是正确的,明天可能就不是了!
注意:我原本打算对 AutoGen、LangChain 和 LangGraph 进行比较。但是,AutoGen 已经宣布推出 AutoGen 0.4,这是对框架从基础开始的完全重新设计。请留意 AutoGen 0.4 发布时的另一篇文章!
LangChain 和 LangGraph 的基本组件
通过了解每个框架的不同基本元素,您将对它们在下一节中如何处理某些核心功能的主要差异有更丰富的了解。下面的描述并不是每个框架的所有组件的详尽列表,而是作为理解它们一般方法差异的有力基础。
LangChain
使用 LangChain 有两种方法:作为预定义命令的连续链或使用 LangChain Agent。每种方法处理工具和编排的方式都不同。链遵循预定义的线性工作流程,而Agent充当协调器,可以做出更动态(非线性)的决策。
- Chain:一系列步骤,可以包括对 llm、代理、工具、外部数据源、过程代码等的调用。链可以分支,这意味着根据 逻辑条件将单个链拆分为多个路径。
- Agent或语言模型:语言模型能够以自然语言生成响应。但是 Agent 使用语言模型和附加功能来推理、调用工具,并在出现任何故障时重复调用工具的过程。
- Tools:基于代码的函数,可以在链中调用或由代理调用以与外部系统交互。
- Prompts:这可能包括指示模型如何完成任务以及可用工具的系统提示、从外部数据源注入的信息(为模型提供更多上下文)以及模型要完成的用户提示或任务。
LangGraph
LangGraph 从不同的角度处理 AI 工作流。顾名思义,它像图表一样编排工作流。由于它在处理 AI 代理、过程代码和其他工具之间的不同流方面具有灵活性,因此它更适合线性链方法、分支链或简单Agent系统无法满足用例需求的用例。与 LangChain 相比,LangGraph 旨在处理更复杂的条件逻辑和反馈循环。
- Graph:一种组织工作流的灵活方式,可以包括对 llm、工具、外部数据源、程序代码等的调用。LangGraph 也支持循环图;这意味着您可以创建循环和反馈机制,以便可以多次重新访问节点。
- Nodes:表示工作流程中的步骤,例如 LLM 查询、API 调用或工具执行。
- Edges and Conditional Edges:边通过将一个节点的输出作为输入连接到下一个节点来定义信息流。条件边定义在满足特定条件时从一个节点到另一个节点的信息流。开发人员可以自定义定义这些条件。
- State:State 是信息流经图形时应用程序的当前状态。它是一个开发人员定义的可变 TypedDict 对象,其中包含当前执行图形的所有相关信息。当信息流经图形时,LangGraph 会自动处理每个节点的状态更新。
- Agent或语言模型:图形中的语言模型仅负责生成对输入的文本响应。代理功能利用语言模型,但使图形具有多个节点,表示代理的不同组件(例如推理、工具选择和工具执行)。代理可以决定在图形中采用哪个路径,更新图形的状态,并执行更多任务,而不仅仅是文本生成。
每个框架处理核心功能的方式之间的差异
LangGraph 和 LangChain 在某些功能上存在重叠,但它们从不同的角度处理问题。LangChain 通过使用链或不同的 AI 代理模式专注于线性工作流。而 LangGraph 专注于创建更灵活、更精细、基于流程的工作流程,其中可以包括 AI 代理、工具调用、程序代码等。
一般来说,LangChain 需要的学习曲线比 LangGraph 少。有更多的抽象和预定义配置,使 LangChain 更容易在简单的用例中实现。LangGraph 允许对工作流的设计进行更多自定义控制,这意味着它不那么抽象,开发人员需要学习更多才能有效地使用框架。
工具调用:
LangChain
在 LangChain 中,有两种方法可以调用工具,具体取决于您是使用链对一系列步骤进行排序,还是仅使用其Agent功能而不在链中明确定义。在链中,工具作为预定义的步骤包含在链中,这意味着它们不一定由代理调用,因为已经预先确定它们将在链中调用。但是,当您有一个未在链中定义的Agent时,Agent可以自主决定调用什么工具以及何时根据它所拥有的工具列表调用。
链的流示例:
- 创建表示工具的函数并使其与链兼容
- 将工具整合到链条中
- 执行链
Agent的流示例:
- 工具已定义
- 该工具已添加到代理
- 代理会收到查询并决定是否以及何时使用搜索工具。如果需要,代理可以多次使用该工具。
LangGraph
在 LangGraph 中,工具通常表示为图形上的一个节点。如果图形包含代理,则代理将根据其推理能力确定要调用的工具。根据代理的工具决策,图形导航到 “tool node” 以处理工具的执行。条件逻辑可以包含在从代理到工具节点的边缘中,以添加确定是否执行工具的附加逻辑。如果需要,这为开发人员提供了另一层控制。如果图中没有代理,那么就像在 LanchChain 的链中一样,该工具可以基于条件逻辑包含在工作流中。
使用 anAgent 的 Graph 的 Flow 示例:
- 工具已定义
- 该工具已绑定到Agent
- Agent决定是否需要工具,如果需要,则决定使用哪种工具
- LangGraph 框架检测到需要工具调用,并导航到图形中的工具节点以执行工具调用
- 捕获工具输出并将其添加到图形的状态中
- 使用更新的状态再次调用代理,以允许它决定下一步做什么
没有Agent的图表的 Flow 示例:
- 工具已定义
- 该工具将作为节点添加到图表中
- 条件边可用于确定何时使用某个工具节点并控制图形的流程
- 该工具可以配置为更新图形的状态
对话历史记录和内存
LangChain
Langchain 提供了用于处理对话历史和内存的内置抽象。有一些选项可以用于要传递给 llm其中包括完整的会话对话历史记录、汇总版本或自定义定义的内存。开发人员还可以创建自定义长期记忆系统,他们可以将记忆存储在外部数据库中,以便在相关时检索。
LangGraph
在 LangGraph 中,state 通过跟踪每个时间点定义的变量来处理内存。状态可以包括对话历史记录、计划步骤、语言模型上一个响应的输出等内容。它可以从一个节点传递到下一个节点,以便每个节点都可以访问系统的当前状态。但是,跨会话的长期持久内存不作为框架的直接功能提供。为了实现这一点,开发人员可以包含负责将内存和其他变量存储在外部数据库中以供以后检索的节点。
开箱即用的 RAG 功能
LangChain
LangChain 可以处理复杂的检索和生成工作流程,并拥有一套更成熟的工具来帮助开发人员将 RAG 集成到他们的应用程序中。例如,LangChain 通过直接使用 langchain.document_loaders、langchain.embeddings 和 langchain.vectorstores 提供开箱即用的文档加载、文本解析、嵌入创建、矢量存储和检索功能。
LangGraph
在 LangGraph 中,RAG 需要作为图结构的一部分从头开始开发。例如,可能有单独的节点用于文档解析、嵌入和检索,这些节点将通过正常或条件边缘连接。每个节点的状态将用于在 RAG 管道中的步骤之间传递信息。
并行性
LangChain
LangChain 提供了使用 RunnableParallel 类并行运行多个链或代理的机会。对于更高级的并行处理和异步工具调用,开发人员必须使用 python 库(如 ayncio)自定义实现这些功能。
LangGraph
LangGraph 支持节点的并行执行,只要没有任何依赖关系(例如一个语言模型的响应输出作为下一个节点的输入)。这意味着它可以支持在图表中同时运行的多个代理,只要它们不是依赖节点。与 LangChain 一样,LangGraph 可以使用 RunnableParallel 类并行运行多个图形。LangGraph 还支持使用 ayncio 等 python 库进行并行工具调用。
重试逻辑和错误处理
LangChain
在 LangChain 中,错误处理由开发人员明确定义,可以通过将重试逻辑引入链本身或在工具调用失败时在Agent中完成。
LangGraph
在 LangGraph 中,你实际上可以通过将 workflow 设为自己的节点来将错误处理嵌入到你的工作流中。当某些任务失败时,您可以指向另一个节点或让同一节点重试。最好的部分是,只有失败的特定节点会重试,而不是整个工作流。这意味着图形可以从故障点恢复,而不必从头开始。如果您的使用案例需要许多步骤和工具调用,这可能是重要的。
总结
你可以不使用 LangGraph,不使用 LangChain,或者同时使用两者!通过将 AutoGen 代理设为图中自己的节点,也完全可以探索将 LangGraph 基于图的编排与其他 Agentic AI 框架(如 MSFT 的 AutoGen)结合使用。可以肯定地说,有很多选择——而且可能会让人感到不知所措。
那么,经过所有这些研究,我应该什么时候使用呢?虽然没有硬性规定,但以下是我个人的选择:
仅在以下情况下使用 LangChain:
您需要快速构建原型或开发 AI 工作流,这些工作流涉及遵循预定义线性模式的顺序任务(例如文档检索、文本生成或摘要)。或者,您希望利用可以动态做出决策的 AI 代理模式,但不需要对复杂的工作流程进行精细控制。
仅在以下情况下使用 LangGraph:
您的使用案例需要多个组件动态交互的非线性工作流,例如依赖于条件、需要复杂分支逻辑、错误处理或并行性的工作流。你愿意为那些没有像 LangChain 那样为你抽象的组件构建自定义实现。
在以下情况下同时使用 LangChain 和 LanGraph:
您喜欢 LangChain 预先构建的提取组件,例如开箱即用的 RAG 功能、内存功能等,但也希望使用 LangGraph 的非线性编排来管理复杂的任务流。同时使用这两个框架可以成为从每个框架中提取最佳能力的强大工具。最终,你是选择 LangChain、LangGraph 还是两者的组合,取决于你项目的具体需求。