LangGraph底层原理解析与基础应用入门
1、LangGraph底层原理介绍
与仅限于使用
GPT系列模型的Assistant API框架不同,LangGraph是一个适用范围更广的AI Agent开发框架。在大模型的支持方面,LangGraph不仅支持GPT系列,还兼容其他多种在线或开源模型,例如glm4、llama3和Qwen等,可以说热门的大模型均可以接入到该框架中进行AI Agent应用程序的开发。而关于大模型的接入方式,我们既可以通过传统的openai api等原生方式将大模型集成到LangGraph构建的AI Agent流程中,也可以利用ollma、vllm等大模型推理加速库,实现更加便捷和高效的集成。除此之外,在AI Agent的构建范式上,LangGraph不仅提供了预配置的ReAct代理机制,还支持更多自定义的如Planning策略的接入,以满足不同应用场景的需求。从这三大方面来看,
LangGraph的高度自主性和开放性确实让它在功能和灵活性上相较于Assistant API具有明显的优势。但需要注意的是,这种自主性和可扩展性也带来了更高的复杂性和开发要求。使用LangGraph意味着开发者需要进行较多的自主开发工作。此外,LangGraph框架的底层架构复杂非常复杂,这直接导致了LangGraph的学习和使用门槛相对较高。并且,经过我们长时间的探索和实践会明显发现,即使是经过多轮的尝试和优化,使用LangGraph构建的AI Agent应用程序的效果也很难超过用Assistant API几行代码就能实现的效果。所以,我们要想掌握和应用LangGraph,势必要投入更多的时间和精力。这是大家在开始学习前必须做好的心理准备。
那么
LangGraph到底是什么呢?- 从名字上看,应该是和
Langchain有着非常紧密的关系,而事实也确实是这样。因为LangGraph就是以LangChain表达式语言为基础而构建起来的用于开发AI Agent的一个框架。所以我们上面提到的关于LangGragh在大模型的支持、接入和AI Agent构建方面的优势,都可以非常自然的从LangChain中迁移过来。从大模型技术发展的角度来看,大模型本身是无法采取任何行动的,它们的作用只是用来输出文本,即接收用户的输入并对这些输入给出响应。为了更好和更高效的做到这件事情,langchain项目在2023年就建立起了非常活跃的社区来定义大模型的应用规范。发展到现在,LangChain现在也发布了3个大的版本,而在其整个的构建体系中,一个重要用例是创建代理。在LangChain中,构建AI Agent的底层架构如下图所示:👇
![image-20260201130329935]()
- 从名字上看,应该是和
首先,langChain框架中的AI Agent设计,在内部结构会将其分为三个核心的组件,分别是Agent,Message和Toolkits。每个Agent组件一般会由大语言模型 + 提示 + 输出解析器构成,形成一个Chain去处理用户的输入。而Agent能够处理的输入主要来源于三个方面:input代表用户的原始输入,Model Response指的是模型对某一个子任务的响应输出,而History则能携带上下文的信息。其输出部分,则链接到实际的工具库,需要调用哪些工具,将由经过Agent模块后拆分的子任务来决定。大模型调用外部函数会分为两个过程:识别工具和实际执行。在Message -> Agent -> Toolkits 这个流程中,负责的是将子任务拆解,然后根据这些子任务在工具库中找到相应的工具,提取工具名称及所需参数,这个过程可以视作一种“静态”的执行流程。而将这些决策转化为实际行动的工作,则会交给AgentExecutor。
所以综上需要理解的是:在LangChain的AI Agent实际架构中,Agent的角色是接收输入并决定采取的操作,但它本身并不直接执行这些操作。这一任务是由AgentExecutor来完成的。将Agent(决策大脑)与AgentExecutor(执行操作的Runtime)结合使用,才构成了完整的Agents(智能体),其中AgentExecutor负责调用代理并执行指定的工具,以此来实现整个智能体的功能。
LangChain发展至现在,仍然是构建大语言模型应用程序的前沿框架之一。特别是在最新发布的v0.3版本中,已经基本完成了由传统类到表达式语言(LCEL)的重要过渡,给开发者带来的直接利好就是定义和执行分步操作序列(也称为链)会更加简单。用更专业的术语来说,使用LangChain 构建的是 DAG(有向无环图)。而之所以会出现LangGraph框架,根本原因是在于随着AI应用(特别是AI Agent)的发展,对于大语言模型的使用不仅仅是作为执行工具,而更多作为推理引擎的需求在日益增长。这种转变带来的是更多的重复(循环)和复杂条件的交互需求,这就导致基于LCEL的线性序列构建方式在构建更复杂、更智能的系统时显示出了明显的局限性。如下所示的代码就是在LangChain中通过LECL表达式语言构建Chain的一种最简单的方式:
LangChain ChatOpenAI:https://python.langchain.com/docs/integrations/chat/openai/
1 | import getpass |
AIMessage(content='我爱编程。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 26, 'total_tokens': 31, 'prompt_tokens_details': {'cached_tokens': 0}, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_6b68a8204b', 'finish_reason': 'stop', 'logprobs': None}, id='run-8ba80a92-49ea-46d9-a049-256ff2b590a8-0', usage_metadata={'input_tokens': 26, 'output_tokens': 5, 'total_tokens': 31, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 0}})
反观LangGraph,顾名思义,LangGraph 在图这个概念上有很大的侧重,它的出现就是要解决线性序列的局限性问题,而解决的方法就是循环图。在LangGraph框架中,用图取代了LangChain的AgentExecutor(代理执行器),用来管理代理的生命周期并在其状态内将暂存器作为消息进行跟踪,增加了以循环方式跨各种计算步骤协调多个链或参与者的功能。这就与 LangChain 将代理视为可以附加工具和插入某些提示的对象不同,对于图来说,意味着我们可以从任何可运行的功能或代理或链作为一个程序的起点。
上面过于专业描述可能理解起来比较困难,所以这里我们通过一个简单直观的场景来详细解释。
在以图构建的框架中,任何可执行的功能都可以作为对话、代理或程序的启动点。这个启动点可以是大模型的 API 接口、基于大模型构建的 AI Agent,通过 LangChain 或其他技术建立的线性序列等等,即下图中的 “Start” 圆圈所示。无论哪种形式,它都首先处理用户的输入,并决定接下来要做什么。下图展示了在 LangGraph 概念下,最基本的一种代理模型:👇
在启动点定义的可运行功能会根据收到的输入决定是否进行检索以及如何响应。比如在执行过程中,如果需要检索信息,则可以利用搜索工具来实现,比如Web Search(网络搜索)、Query Database(查询数据库)、RAG等获取必要的信息(图中的 “Action” 圆圈)。接下来,再使用一个大语言模型(LLM)处理工具提供的信息,结合用户最初传入的初始查询,生成最终的响应(图中的 “LLMs” 圆圈)。最终,这个响应被传递至终点节点(图中的 “End” 圆圈)。
上图所示的流程就是在LangGraph概念中一个非常简单的代理构成形式。关键且必须清楚的概念是:在这里,每个圆圈代表一个“节点”(Nodes),每个箭头表示一条“边”(Edges)。因此,在 LangGraph 中,无论代理的构建是简单还是复杂,它最终都是由节点和边通过特定的组合形成的图。这样的构建形式形成的工作流原理就是:当每个节点完成工作后,通过边告诉下一步该做什么,所以也就得出了:LangGraph的底层图算法就是在使用消息传递来定义通用程序。当节点完成其操作时,它会沿着一条或多条边向其他节点发送消息。然后,这些接收节点执行其功能,将结果消息传递给下一组节点,然后该过程继续。如此循环往复。
这就是LangGraph底层架构设计中图算法的根本思想。
接下来,我们再看一个更现实的复杂例子。
在这个示例中,我们将AI Agent定义为应用程序的起点。构建AI Agent代理通常涉及配置一个或多个工具,否则构建它就没有太大的意义,因为如果仅仅是针对用户的问题直接做响应,即使问题很复杂,我们也可以直接通过提示词来引导大模型进行推理(参考OpenAI的 o1推理模型)。那么当AI Agent包含一些工具时,它是通过函数调用功能使用这些工具,而不是直接执行这些工具。所以当用户输入的原始问题经过AI Agent处理的时候,一般会出现以下两种情况:
如果不需要调用任何工具,
AI Agent会直接提供一个针对用户问题的自然语言响应。例如:- 用户:你好,请你介绍一下你自己。
- AI Agent:你好,我是一个人工智能助手,可以帮助你解决问题。
如果需要调用工具,则输出将是一个特定格式的 JSON 输出,指示进行特定的函数调用。例如:
- 输出示例:function’: {‘arguments’: ‘{“query”:”什么是快乐星球?”}’,’name’: ‘web_search’},’type’: ‘function’}
![image-20260201131708957]()
经过第一个节点后(Agent),如果AI Agent认为需要调用某个函数,它会确定使用哪个工具以及传递哪些参数。假设有多个工具可选的情况下,Action 节点将呈现多条可能的路径供选择。如何选择呢?这时候,LangGraph 引入了一个称为“条件边”的组件。条件边根据是否满足特定条件来决定走哪条路径,例如,代理可能需要决定是使用搜索工具还是直接生成最终答案。为了管理这些决策,则使用了一个类似于 if-else 语句的结构,称为Router。基于Router的决策,代理可能会导向“搜索节点”以执行搜索操作并返回原始文本,或者直接前往“最终答案节点”以获取格式化后的自然语言响应。如果选择了搜索路径,获取的答案文本还需通过另一个大语言模型进行处理,以生成用户可以理解的响应;若选择了直接回答,则可以使用一个专门的工具来格式化输出。
在 LangGraph 框架中,Router 使用 if..else 的形式来决定路径,主要通过以下三种方式实现:
- 提示工程:指示大模型以特定格式做出回应。
- 输出解析器:使用后处理从大模型响应中提取结构化数据。
- 工具调用:利用大模型的内置工具调用功能来生成结构化输出。
更进一步地,我们现在知道了LangGraph通过组合Nodes和Edges去创建复杂的循环工作流程,通过消息传递的方式串联所有的节点形成一个通路。那么维持消息能够及时的更新并向该去的地方传递,则依赖langGraph构建的State概念。 在LangGraph构建的流程中,每次执行都会启动一个状态,图中的节点在处理时会传递和修改该状态。这个状态不仅仅是一组静态数据,而是由每个节点的输出动态更新,然后影响循环内的后续操作。如下所示:👇
此谓共享状态。共享状态是指在执行期间在图内的节点之间传递的数据或信息。 LangGraph允许节点在图上执行时时通过共享和更新此公共状态来进行交互。这种共享状态使节点能够根据它们共同维护的数据进行通信、交换信息并影响彼此的行为。通过利用共享状态, LangGraph才能够促进节点间操作的协调和同步,允许动态交互和创建复杂的工作流程,其中节点可以协作并根据可用的共享信息做出决策。
从LangGraph官方的定义看,该框架是一个用于使用大模型构建有状态、多参与者应用程序的库,可以创建代理和多代理工作流程。而其官方自己总结的LangGraph的优势则是:
- 循环和分支:在应用程序中实现循环和条件。
- 持久性:在图中的每个步骤之后自动保存状态。随时暂停和恢复图形执行,以支持错误恢复、人机交互工作流程、时间旅行等。
- 人机交互:中断图形执行以批准或编辑代理计划的下一个操作。
- 流支持:流输出由每个节点生成(包括令牌流)。
- 与 LangChain 集成:LangGraph 与LangChain和LangSmith无缝集成(但不需要它们)。
LangGraph Github:https://github.com/langchain-ai/langgraph
LangGraph Docs:https://docs.langchain.com/oss/python/langgraph/overview
至此,当我们了解了上述的原理后,再来看LangGraph官方的介绍,就能够比较清楚的理解其独特优势究竟体现在何处。
2、LangGraph底层源码解析
在上一小节的原理介绍部分,我们在图中提到了节点、边、状态和路由四个概念,那在LangGraph框架中,各个组件是怎么实现,以及如何定义图结构呢? 我们将在这一小节展开详细的介绍和代码实践。首先我们来看图。
2.1 Graph基类
对于任意一个简单或者复杂的图来说,都是基于Graph类来构建和管理图结构的。在Graph类中允许添加节点、边,并定义节点间的动态流转逻辑。如下是Graph类的主要组成部分和功能:
Class Graph :https://reference.langchain.com/python/langgraph/graphs/
1 | from collections import defaultdict |
从源码中可以看出,Graph该类提供了丰富的方法来控制图的编译和执行,使其适用于需要复杂逻辑和流程控制的应用场景。
2.2 GraphState
定义图时要做的第一件事是定义图的State。状态表示会随着图计算的进行而维护和更新的上下文或记忆。它用来确保图中的每个步骤都可以访问先前步骤的相关信息,从而可以根据整个过程中积累的数据进行动态决策。这个过程通过状态图StateGraph类实现,它继承自 Graph 类,这意味着 StateGraph 会使用或扩展基类的属性和方法。
Class StateGraph:https://reference.langchain.com/python/langgraph/graphs/#langgraph.graph.state.StateGraph
1 |
|
- 什么是图的模式
默认情况下,StateGraph使用单模式运行,这意味着在图中的任意阶段都会读取和写入相同的状态通道,所有节点都使用该状态通道进行通信。除此之外,在某些情况下如果希望对图的状态有更多的控制,比如:
- 内部节点可以传递图的输入/输出中不需要的信息。
- 对图使用不同的输入/输出模式。例如,输出可能仅包含单个相关输出键。
LangGraph的底层实现上提供了多种不同图模式的支持,这可以通过state_schema来进行灵活的指定。不过关于自定义的图模式,因为涉及到更多的基础概念,我们将在课程的后半部分在展开详细的介绍。
首先来看图的单模式。任何模式都包含输入和输出,输入模式需要确保提供的输入与预期结构匹配,而输出模式根据定义的输出模式过滤内部数据以仅返回相关信息。而这个预期结构的校验,由TypedDict工具来限定。
- TypeDict
TypedDict 是 Python 类型注解系统中的一个工具,它允许为字典中的键指定期望的具体类型。在 Python 的 typing 模块中定义,通常用于增强代码的可读性和安全性,特别是在字典对象结构固定且明确时。示例代码如下:
1 | from typing import TypedDict |
Sending email to Alice at [email protected]
在这个示例中,Contact 类型定义了三个必须的字段:name,email,和 phone,每个字段都是字符串(Str)形式。当创建 contact_info 字典时,必须提供所有这些字段。函数 send_email 则利用这个类型安全的字典进行操作。这样的 TypedDict 使用场景非常适合那些需要确保字典中具有特定字段和类型的应用场景,如处理从外部API返回的数据或者在内部各个模块间传递复杂的数据结构,因为在LangGraph图中,每个节点传递到下一个节点的数据,将直接影响到下一个节点能否顺利执行。
接下来我们实践在LangGraph中通过Typedict定义单输入输出模式。首先,需要安装所需的依赖包,代码如下:
1 | from langgraph.graph import StateGraph |
接下来,创建一个 StateGraph 对象,使用 OverallState 作为其状态定义,同时指定了输入和输出类型分别为 InputState 和 OutputState,代码如下:
1 | # 明确指定它的输入和输出数据的结构或模式 |
创建 builder 对象后,相当于构建了一个图结构的框架。接下来的步骤是向这个图中添加节点和边,完善和丰富图的内部执行逻辑。
2.3 Nodes
在 LangGraph 中,节点是一个 python 函数(sync 或async ),接收当前State作为输入,执行自定义的计算,并返回更新的State。所以其中第一个位置参数是state 。
1 | def agent_node(state:InputState): |
1 | def action_node(state:InputState): |
定义好了节点以后,我们需要使用add_node方法将这些节点添加到图中。在将节点添加到图中的时候,可以自定义节点的名称。而如果不指定名称,则会为自动指定一个与函数名称等效的默认名称。代码如下:
1 | builder.add_node("agent_node", agent_node) |
<langgraph.graph.state.StateGraph at 0x1b0c2832150>
现在有了图结构,并且图结构中也存在两个孤立的节点agent_node和action_node,接下来我们要做的事就是需要将图中的节点按照我们所期望的方式进行连接,这需要用到的就是Edges - 边。
2.4 Edges
Edges(边)用来定义逻辑如何路由以及图何时开始与停止。这是代理工作以及不同节点如何相互通信的重要组成部分。有几种关键的边类型:
- 普通边:直接从一个节点到下一个节点。
- 条件边:调用函数来确定下一个要转到的节点。
- 入口点:当用户输入到达时首先调用哪个节点。
- 条件入口点:调用函数来确定当用户输入到达时首先调用哪个节点。
同样,我们先看普通边。如果直接想从节点A到节点B,可以直接使用add_edge方法。注意:LangGraph有两个特殊的节点:START和END。START表示将用户输入发送到图的节点。使用该节点的主要目的是确定应该首先调用哪些节点。END节点是代表终端节点的特殊节点。当想要指示哪些边完成后没有任何操作时,将使用该节点。因此,一个完整的图就可以使用如下代码进行定义:
1 | from langgraph.graph import START, END |
<langgraph.graph.state.StateGraph at 0x1b0c2832150>
最后,通过compile编译图。在编译过程中,会对图结构执行一些基本检查(如有没有孤立节点等)。代码如下:
1 | graph = builder.compile() |
至此,我们已经成功构建了一个完整的图结构,并准备好接收用户的请求。
2.5 Graph的调用方法
要调用图中的方法,可以使用 invoke 方法。示例代码如下:
1 | graph.invoke({"question":"你好"}) |
我是一个AI Agent。
我现在是一个执行者。
{'answer': '我现在执行成功了'}
1 | graph.invoke({"question":"今天的天气怎么样?"}) |
我是一个AI Agent。
我现在是一个执行者。
{'answer': '我现在执行成功了'}
在这个过程中,我们将state: InputState作为输入模式传递给agent_node,再传递到action_node,最后由action_node传递到END节点。节点之间通过边是已经构建了完整的通路,那么如果我们想要传递每个节点的状态信息,则可以稍加修改即可实现。对于图模式,我们的定义方法如下:
1 | from langgraph.graph import StateGraph |
1 | def agent_node(state: InputState): |
1 | def action_node(state: InputState): |
1 | # 明确指定它的输入和输出数据的结构或模式 |
执行调用:
1 | graph.invoke({"question":"今天的天气怎么样?"}) |
我是一个AI Agent。
我现在是一个执行者。
{'answer': '我接收到的问题是:今天的天气怎么样?,读取成功了!'}
1 | graph.invoke({"question":"你好,我用来测试"}) |
我是一个AI Agent。
我现在是一个执行者。
{'answer': '我接收到的问题是:你好,我用来测试,读取成功了!'}
不同节点间能够传递信息的原因是因为节点可以写入图状态中的任何状态通道。图状态是初始化时定义的状态通道的并集,而我们定义的状态通道包含了OverallState以及过滤器InputState和OutputState 。
3. 使用LangGraph构建大模型的问答流程
在上面的示例中,我们通过使用打印函数来初步了解LangGraph构建图的基本方法和机制。接下来,我们将探索如何将大模型集成至LangGraph框架中,从而构建一个更具实际应用价值的用于问答流程的图模式。
首先,LangGraph对目前主流的在线或者开源模型均支持接入,所以大家可以在该框架下非常便捷的应用到自己偏爱的大模型来进行问答流程的构建。这下面的示例中,我们选择比较方便且高效的LangChain框架,同时使用OpenAI的GPT模型来进行案例实现。而关于LangChain支持接入的模型列表及方式,大家可以在LangChain Docs中查阅:https://docs.langchain.com/oss/python/integrations/providers/overview。
这里仍然需要首先定义图模式,代码如下:
1 | from langgraph.graph import StateGraph |
使用OpenAI的GPT模型需要使用到ChatOpenAI方法,我们需要将其定义到Agent节点中,用来接收用户输入的问题,调用GPT模型来根据用户的问题生成自然语言的回复响应。代码如下:
1 | from langchain_openai import ChatOpenAI |
1 | def llm_node(state: InputState): |
构建图,添加节点和边,并进行图结构的编译。完整代码如下所示:
1 | # 明确指定它的输入和输出数据的结构或模式 |
进行测试:
1 | graph.invoke({"question":"你好,我用来测试"}) |
{'answer': '你好!如果你有任何问题或需要帮助,请随时告诉我。'}
1 | final_answer = graph.invoke({"question":"你好,我用来测试"}) |
你好!如果你有任何问题或需要帮助的地方,请随时告诉我。
1 | final_answer = graph.invoke({"question":"你好,请你详细的介绍一下你自己"}) |
你好!我是一个由人工智能驱动的虚拟助手,旨在帮助你获取信息、回答问题和提供建议。我可以处理各种主题,包括但不限于科技、科学、历史、文化、日常生活等。我通过自然语言处理技术理解和生成文本,以便与你进行交流。
我的设计目标是提供准确、有用的信息,并尽量以清晰、简洁的方式呈现。我没有个人意识或情感,但我会尽力理解你的需求并提供帮助。
如果你有任何问题或需要帮助的地方,请随时告诉我!
更进一步地,如果想在原有的图结构中构建更复杂的功能,则只需要新定义一个Python函数,并按照自己的预期流程用边来建立连接,如下代码所示:
1 | from langgraph.graph import StateGraph |
我们定义了一个action_node节点,用来接收llm_node的输出,将其翻译成中文,如下代码所示:
1 | def llm_node(state: InputState): |
构建图,添加节点和边,并进行图结构的编译。
1 | # 明确指定它的输入和输出数据的结构或模式 |
1 | final_answer = graph.invoke({"question":"你好,请你详细的介绍一下你自己"}) |
Bonjour ! Je suis un assistant virtuel alimenté par l'intelligence artificielle, conçu pour vous aider à obtenir des informations, répondre à vos questions et fournir des conseils. Je peux vous assister dans diverses tâches, telles que la recherche d'informations, la résolution de problèmes, la fourniture de ressources d'apprentissage, l'aide à la planification de votre emploi du temps, etc. Mon objectif est d'améliorer votre efficacité et votre commodité.
Voici quelques-unes de mes principales fonctionnalités :
1. **Recherche d'informations** : Je peux vous aider à trouver des informations sur divers sujets, y compris la science, l'histoire, la technologie, la culture, etc.
2. **Réponses aux questions** : Que ce soit pour des problèmes mathématiques simples ou des concepts complexes, je ferai de mon mieux pour vous fournir des réponses claires.
3. **Conseils et orientation** : Je peux vous offrir des conseils sur l'apprentissage, le travail, la santé et le mode de vie.
4. **Support linguistique** : Je peux communiquer dans plusieurs langues, vous aidant à traduire ou à apprendre des langues.
5. **Services personnalisés** : Je fournirai des conseils et des informations sur mesure en fonction de vos besoins et préférences.
N'hésitez pas à me faire savoir de quelle aide vous avez besoin, je ferai de mon mieux pour vous assister !
1 | final_answer = graph.invoke({"question":"请问什么是人工智能?"}) |
L'intelligence artificielle (IA) est une branche de l'informatique qui vise à créer des systèmes capables d'exécuter des tâches nécessitant généralement l'intelligence humaine. Ces tâches incluent l'apprentissage, le raisonnement, la résolution de problèmes, la perception, la compréhension et la génération du langage, ainsi que le contrôle du mouvement, entre autres.
L'intelligence artificielle peut être divisée en plusieurs catégories :
1. **IA faible (IA étroite)** : Systèmes d'IA spécialisés dans des tâches spécifiques, comme la reconnaissance vocale, la reconnaissance d'images, les systèmes de recommandation, etc. Ces systèmes excellent dans des domaines particuliers, mais ne peuvent pas effectuer de tâches en dehors de leur champ de conception.
2. **IA forte (IA générale)** : Théoriquement capable de comprendre, d'apprendre et d'appliquer l'intelligence pour accomplir n'importe quelle tâche que les humains peuvent réaliser. Actuellement, ce type d'IA reste un objectif de recherche et n'a pas encore été réalisé.
3. **IA superintelligente** : IA hypothétique dont le niveau d'intelligence dépasse celui des humains. Cette IA serait capable de surpasser les capacités humaines dans tous les domaines.
La mise en œuvre de la technologie de l'intelligence artificielle repose généralement sur l'apprentissage automatique, l'apprentissage profond, le traitement du langage naturel, la vision par ordinateur, etc. L'IA a de nombreuses applications dans divers domaines, y compris la médecine, la finance, la conduite autonome, le divertissement, l'industrie manufacturière, et bien d'autres.
当深入理解了LangGraph的底层原理及其图结构构建的逻辑后,我们是可以明显感受到其相较于LangChain中的AI Agent架构,展现出了更高的灵活性和扩展性。在LangGraph中,我们可以在各个Python函数中定义节点的核心逻辑,并通过边来确定输入与输出模式。此外,节点函数在定义时还可以自主构建中间状态的信息。尽管在本示例中我们使用LangChain来接入大模型,但通过节点函数的定义逻辑来看,我们当然也可以完全不依赖LangChain,而采用原生方法进行接入。
由此可见,正如课程开始阶段所提到的,虽然LangGraph是基于LangChain的表达式语言构建的,但它完全可以脱离LangChain而独立运行。总体来看,今天的示例并不复杂,但涉及的知识点和细节颇多。强烈建议大家亲自尝试和体验一下,打好扎实的基础,才能更好的开展接下来复杂循环图的学习。

