详解Multi-Agent核心架构及LangGraph框架
本文主要介绍多智能体集成框架LangGraph的相关概念及使用,关于大模型应用开发的基本的流程可以阅读:《GitHub 12w Star神器!一文详解大模型集成框架LangChain》,详细介绍了构建大模型应用的步骤及概念(提示词模版、输出解析器、记忆、工具、Agent、RAG等)。01 LangGraph概述1.1什么是LangGraphLangGraph 是LangChain 生态的一部分,专门用于构建基于大模型(LLM)的复杂、有状态、多智能体应用的框架,核心思想是将应用的工作流程抽象为一个有向图结构,通过节点和边来定义任务的执行步骤和逻辑流,从而提供了远超传统线性链式调用的灵活性和控制力。相比传统的线性执行模式,LangGraph 支持条件分支、循环、并行等复杂控制流,能够实现状态持久化、断点续跑、时间旅行、人机协作等高级功能,并提供了多智能体协作、层级架构等多种架构模式。在实际应用中,LangGraph已成功应用于智能客服、自动化运维、研究 Agent 等场景,展现出卓越的适应性和扩展性。LangGraph在Github上的热度变化1.2为什么使用LangGraphLangGraph 相比传统的线性执行模式具有显著的技术优势。LangGraph 提供了强大的状态管理机制,允许 Agent 在不同节点之间传递和维护信息,从而实现长期的记忆和多轮对话能力。这种集中式的状态管理避免了传统方法中状态分散在多个变量中的问题,提高了系统的可维护性和可观测性。通过定义节点和边,可以精确控制 Agent 的执行逻辑,包括条件分支、循环和并行执行等LangGraph 能够无缝集成各种外部工具(如搜索引擎、数据库、API 等),让 Agent 能够获取实时信息、执行特定操作,极大地扩展了 LLM 的能力边界。图结构使得 Agent 的运行路径清晰可见,便于理解 Agent 的决策过程,并在出现问题时进行快速定位和调试。模块化与可复用性。每个节点都可以是一个独立的、可复用的组件,维护性高且易于扩展。通过子图机制,复杂的工作流可以被分解为多个可独立开发和测试的模块,提高了开发和测试效率。1.3安装使用安装LangGraphpipinstall -U langgraph使用LangGraph创建一个简单的Agentdefget_weather(city:str) -str: """获取指定城市的天气信息。 Args: city: 城市名称 Returns: 返回该城市的天气描述 """ returnf"今天{city}是晴天"# 创建模型model = ChatOpenAI( model_name=model_name, base_url=base_url, api_key=api_key)# 使用LangGraph提供的API创建Agentagent = create_react_agent( model=model, # 添加模型 tools=[get_weather], # 添加工具 prompt="你是一个天气助手")human_message = HumanMessage(content="今天深圳天气怎么样?")response = agent.invoke( {"messages": [human_message]})print(response)运行模式:Agent可以通过两种主要模式执行同步:使用 .invoke() 或 .stream()异步:使用 await .ainvoke() 或 async for 配合 .astream()最大迭代次数:为了避免Agent无限循环执行,可以设置一个递归限制response = agent.invoke( {"messages": [{"role":"user","content":"预定一个深圳到北京的机票"}]}, {"recursion_limit": 10} # 指定最大迭代次数)02 LangGraph核心2.1Graph(图)图是一种由节点和边组成的用于描述节点之间关系的数据结构,分为无向图和有向图,有向图是带有方向的图。LangGraph通过有向图定义AI工作流中的执行步骤和执行顺序,从而实现复杂、有状态、可循环的应用程序逻辑。2.2LangGraph核心要素(State、Edge、Node)1、State(状态)在LangGraph中,State是一个贯穿整个工作流执行过程中的共享数据的结构,代表当前快照,它存储了从工作流开始到结束的所有必要的信息(历史对话、检索到的文档、工具执行结果等),在各个节点中共享,且每个节点都可以修改。State可以是TypedDict类型,也可以是pydantic中的BaseModel类型。# 定义状态classGraphState(TypedDict): process_data:dict# 默认更新策略为替换(后续会讲更新策略)# 创建一个状态图,并指定状态graph = StateGraph(GraphState)2、Node(节点)Node是LangGraph中的一个基本处理单元,代表工作流中的一个操作步骤,可以是一个Agent、调用大模型、工具或一个函数(说白了就是绑定一个函数,具体逻辑可以干任何事情)。Node的设计原则:单一职责原则:每个节点应该只负责一项职责,避免功能过于复杂无状态设计:节点本身不应该保存状态,所有数据都通过输入状态传递幂等性:相同的输入应该产生相同的输出,确保可重试性可测试性:节点逻辑应该易于单元测试如下是添加一个节点的例子:# 定义一个节点,入参为statedefinput_node(state: GraphState) - GraphState: print(state) return{"process_data": {"input":"input_value"}}# 定义带参数的node节点defprocess_node(state:dict, param1:int, param2:str) -dict: print(state, param1, param2) return{"process_data": {"process":"process_value"}}graph = StateGraph(GraphState)# 添加inpu节点graph.add_node("input", input_node)# 给process_node节点绑定参数process_with_params = partial(process_node, param1=100, param2="test")# 添加带参数的node节点graph.add_node("process", process_with_params)特殊节点:在LangGraph中有两个特殊的节点 __START__ (开始节点)和 __END__(结束节点)__START__节点:开始节点,确定应该首先调用哪些节点。fromlanggraph.graphimportSTART# 第一个执行的节点是 node_startgraph.add_edge(START,"node_start")也可以通过graph.set_entry_point("node_start") 函数设置起始节点,等价于graph.add_edge(START, "node_start")__END__节点:终止节点,表示后续没有其他节点可以继续执行了(非必须)。fromlanggraph.graphimportEND# node_end 节点执行后,没有后续节点了graph.add_edge("node_a", END)也可以通过graph.set_finish_point("node_end") 函数设置结束节点,等价于graph.add_edge("node_start", END)错误处理和重试机制:LangGraph还提供了错误处理和重试机制来指定重试次数、重试间隔、重试异常等,用于保证系统的可靠性。# 重试策略retry_policy = RetryPolicy( max_attempts=3, # 最大重试次数 initial_interval=1, # 初始间隔 jitter=True, # 抖动(添加随机性避免重试风暴) backoff_factor=2, # 退避乘数(每次重试间隔时间的增长倍数) retry_on=[RequestException, Timeout] # 只重试这些异常)graph.add_node("process", process_node, retry=retry_policy)节点缓存:LangGraph 支持根据节点输入对节点进行缓存,用于加快节点的响应速度缓存键与命中:当一个节点开始执行时,系统会使用其配置的 key_func 根据当前节点的输入数据生成一个唯一的键。LangGraph 会检查缓存中是否存在这个键。如果存在(缓存命中),则直接返回之前存储的结果,跳过该节点的实际执行。如果不存在(缓存未命中),则正常执行节点函数,并将结果与缓存键关联后存入缓存。缓存有效期:ttl 参数能控制缓存的有效期。例如,对于依赖实时数据的天气查询节点,可以设置较短的 ttl(如60秒)。而对于处理静态信息或变化不频繁数据的节点,则可以设置较长的 ttl甚至不设置(None),让缓存永久有效,直到手动清除classState(TypedDict): x:int result:intbuilder = StateGraph(State)defexpensive_node(state: State) -dict[str,int]: # 模拟耗时 time.sleep(2) return{"result": state["x"] *2}#添加节点,并指定缓存策略builder.add_node("expensive_node", expensive_node, cache_policy=CachePolicy(ttl=3))builder.set_entry_point("expensive_node")builder.set_finish_point("expensive_node")graph = builder.compile(cache=InMemoryCache())3、Edge(边)Edge定义了节点之间的连接和执行顺序,以及不同节点之间是如何通讯的,一个节点可以有多个出边(指向多个节点),多个节点也可以指向同一个节点(Map-Reduce),如下是添加边的代码:# 添加固定边,执行顺序:start - input - process - output - endgraph.add_edge(START,"input")graph.add_edge("input","process")graph.add_edge("process","output")graph.add_edge("output",END)# 编译图,保证生成的图是正确的,如果添加了边,没添加节点,会报错app = graph.compile()app.invoke({})4、构建一个完整的图图的构建流程:1、初始化一个StateGraph实例。2、添加节点。3、定义边,将所有的节点连接起来。4、设置特殊节点,入口和出口(可选)。5、编译图。6、执行工作流。classGraphState(TypedDict): process_data:dictdefinput_node(state: GraphState) - GraphState: print(state) return{"process_data": {"input":"input_value"}}defoutput_node(state: GraphState) - GraphState: print(state) return{"process_data": {"output":"output_value"}}defprocess_node(state:dict) -dict: print(state) return{"process_data": {"process":"process_value"}}# 创建一个状态图,并指定状态graph = StateGraph(GraphState)# 添加input、process、output节点graph.add_node("input", input_node)graph.add_node("process", process_node)graph.add_node("output", output_node)# 添加固定边,执行顺序:start - input - process - output - endgraph.add_edge(START,"input")graph.add_edge("input","process")graph.add_edge("process","output")graph.add_edge("output", END)# 编译图,保证生成的图是正确的,如果添加了边,没添加节点,会报错app = graph.compile()# 执行app.invoke({})2.3状态合并策略(Reducers)LangGraph工作流中,State作为贯穿整个节点之间共享数据的结构,每一个节点都可以读取当前State的数据,并且可以更新。Reducer是定义多个节点之间State如何更新的(覆盖、合并、添加等)。1、直接覆盖:如果没有为状态字段指定 Reducer,默认会覆盖更新。也就是说,后执行的节点返回的值会直接覆盖先执行节点的值,即下一个节点的State数据是上一个节点的返回。classOverrideState(TypedDict): process_data :dict# 未指定合并策略,默认覆盖,上一个节点的返回是下一个节点的值2、Annotated:使用类型注解指定合并策略classAddState(TypedDict): data_int: Annotated[int, add] # 数字相加 data_list: Annotated[list, add]# 合并两个列表 data_str: Annotated[str, add] # 字符串拼接defadd_node1(state: AddState) - AddState: print(state) return{"data_int":1,"data_list": [1],"data_str":"hello "}defadd_node2(state: AddState) - AddState: print(state) return{"data_int":2,"data_list": [2],"data_str":"world"}3、内置Reducer:add_messages(消息列表合并)LangGraph提供的专用Reducer函数,能智能的合并消息列表,不只是简单的追加,add_messages能够保证消息列表正确被累计,常用在多轮对话系统中,主要逻辑包括:追加新消息:如果新消息的 ID 不在现有列表中,则将其追加到列表末尾。覆盖旧消息:如果新消息的 ID 与列表中某条现有消息的 ID 相同,则用新消息替换掉旧消息。用于处理工具调用中间结果或更新流式生成的临时消息。自动类型转换:如果传入一个字符串(如 "Hello World"),add_messages会自动将其转换为HumanMessage(用户消息)classMessageState(TypedDict): # 消息列表,使用add_messages合并消息列表 messages: Annotated[list, add_messages]defsystem_node(state: MessageState) -dict: return{"messages": [SystemMessage(content="你是一个精通LangGraph的专家工程师.")]}defuser_input_node(state: MessageState) -dict: return{"messages": [HumanMessage(content="什么是LangGraph?")]}defai_response_node(state: MessageState) -dict: return{"messages": [AIMessage(content="LangGraph是一个...")]}deftool_node(state: MessageState) -dict: return{"messages": [ToolMessage(content="工具调用参数params1", tool_call_id="tool_call_id")]}4、自定义Reducer:实现自定义合并逻辑defmerge_dict_reducer(source:dict, new:dict) -dict: # 自定义合并逻辑 result = source.copy() result.update(new) returnresultdefmax_reducer(source:int, new:int) -int: # 自定义合并逻辑 returnmax(source, new)classCustomReducerState(TypedDict): # 使用自定义Reducer的状态 max_score: Annotated[int, max_reducer] # 保留最大值 metadata: Annotated[dict, merge_dict_reducer] # 字典合并2.4条件边(Conditional Edge)实际应用中,工作流的下一个节点可能并不是固定的,需要根据当前的执行状态去确定需要路由到哪一个节点。条件边可以动态控制执行流程,LangGraph中可以指定路由函数,来选择具体要执行的节点(可以是多个节点)defroute_by_sentiment(state: GraphState) -str: # 路由逻辑...返回最终的条件 return"condition_1"graph = StateGraph(GraphState)graph.add_node("node1", node1)graph.add_node("node2", node2)graph.add_node("node3", node3)# 添加路由函数,参数:当前节点,路由函数,路由函数返回的条件与node的映射graph.add_conditional_edges( START, route_by_sentiment, { "condition_1":"node1", "condition_2":"node2", "condition_3":"node3" })# 所有处理节点都连接到ENDgraph.add_edge("node1", END)graph.add_edge("node2", END)graph.add_edge("node3", END)app = graph.compile()LangGraph 提供了图的可视化,可以通过调用函数保存图,用于查看工作流是否与预期定义的规则一致。png_data = app.get_graph().draw_mermaid_png()withopen("graph.png","wb")asf: f.write(png_data)2.5Send 和 CommandSend和Command是两种用于实现高级工作流控制的核心机制,用于支持动态地决定下一步执行哪个节点1、Send:动态创建多个执行分支,实现并行处理,每个Send对象都指定了一个执行目标节点和传递给该节点的参数,LangGraph会并行执行所有的这些任务。比如可以用在Map-Reduce的场景,并行执行多个子节点并最终汇总到一个总节点。def route_tasks(state: MapReduce

相关新闻

OpenClaw登顶GitHub,满天飞的智能体Skills要怎样设计?

OpenClaw登顶GitHub,满天飞的智能体Skills要怎样设计?

OpenClaw 短短 4 个月突破 250K 的 Star,登顶 GitHub 成为史上获星最多的软件项目,要知道 React 登顶可是花了十几年的积累。智能体 Skills 成就了 OpenClaw,而 OpenClaw 让 Skills 大爆发。Skills 给大模型智能体装上能够沉淀经验的程序化记…

2026/7/6 17:22:05 阅读更多 →
告别“无效打卡”:不同规模企业如何构建适配的考勤与工时体系?

告别“无效打卡”:不同规模企业如何构建适配的考勤与工时体系?

现如今,不少企业在考勤中依然依赖Excel拼表和微信群核对,尽管已有一部分企业上线了专门的考勤系统,可小微企业嫌系统笨重,中大型企业也需要应对算薪慢、取证难等问题。究其实质,问题往往不在于缺少打卡工具&#xff0c…

2026/7/6 17:13:15 阅读更多 →
好写作AI:短篇也能写出深度,AI辅助短篇学术文章的高效秘诀

好写作AI:短篇也能写出深度,AI辅助短篇学术文章的高效秘诀

会议论文、观点短文、学术评论——篇幅虽短,要求不低,AI帮你精准拿捏短篇学术文章(如会议论文、简报、评论、观点文章)往往是学术写作中最高难度的挑战:几百到两千字的篇幅,要讲清楚问题、方法、贡献&#…

2026/7/5 8:22:19 阅读更多 →

最新新闻

AI视频生成技术在游戏特效制作中的应用实践

AI视频生成技术在游戏特效制作中的应用实践

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 这次我们来看一个基于AI视频生成技术的"恐惧魔王 吞噬魔法"特效测试项目。这个项目展示了如何利用AI技术实现游戏角色特效的…

2026/7/7 2:40:13 阅读更多 →
本地AI部署实战指南:从环境配置到性能优化的完整解决方案

本地AI部署实战指南:从环境配置到性能优化的完整解决方案

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 今天我们来聊聊一个让很多开发者头疼的问题:本地AI部署。虽然标题提到了"一人公司"的困境,但本文重…

2026/7/7 2:38:12 阅读更多 →
Claude偷改了你一行代码

Claude偷改了你一行代码

摘要:2026 年 6 月底,Reddit 开发者逆向 Claude Code 客户端,发现 Anthropic 用隐写术在中国用户请求里嵌入隐藏标记——读系统时区、比对 147 个加密域名、在日期字符串里替换 Unicode 字符。这段代码静默运行三个月,从未披露。三…

2026/7/7 2:36:12 阅读更多 →
面向AI应用的后端架构设计:协议选型、服务治理与可观测性

面向AI应用的后端架构设计:协议选型、服务治理与可观测性

引言:AI应用的后端挑战与传统架构的差异 在AI应用从概念验证走向生产部署的过程中,后端架构面临的挑战与传统互联网应用有本质差异。传统后端系统追求的是低延迟、高吞吐、确定性响应,而AI应用的核心瓶颈往往不在业务逻辑,而在于…

2026/7/7 2:36:12 阅读更多 →
[实战]Python爬取全国考研数据与可视化(附源码)

[实战]Python爬取全国考研数据与可视化(附源码)

很多考研同学都会关注院校招生人数、专业分数线等信息,手动整理效率极低。本篇用 Python 完成接 口爬虫 数据存储 可视化分析全流程实战,从考研网站抓取院校专业数据,再通过图表直观分析数据,适合爬虫、数据分析入门学习。 一、…

2026/7/7 2:36:12 阅读更多 →
ComfyUI整合包+KREA2模型:AI绘画本地部署全攻略

ComfyUI整合包+KREA2模型:AI绘画本地部署全攻略

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 如果你正在为AI绘画的复杂环境配置而头疼,特别是想要体验最新的KREA2模型却苦于繁琐的安装过程,那么萝卜大佬的…

2026/7/7 2:34:11 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻