公司动态
LangGraph实战:构建可编排的多智能体工作流系统
如果你正在尝试构建一个能自主协作、完成复杂任务的AI智能体系统大概率会遇到这样的困境单个Agent能力有限而让多个Agent协同工作代码很快就会变成难以维护的“意大利面条”——状态流转混乱、消息传递复杂、错误处理困难。这正是LangGraph要解决的核心问题。它不是一个全新的Agent框架而是LangChain生态中一个专门用于构建有状态、多智能体工作流的库。很多人误以为它只是LangChain的一个“高级版”但实际上它的设计理念更接近一个为Agent协作而生的“微服务编排引擎”。它把复杂的多智能体交互抽象成清晰、可调试的“图”Graph让你能用声明式的方式定义谁在什么时候、做什么、以及接下来该谁做。本文将带你彻底搞懂LangGraph并手把手实现一个从零到一的多智能体协作系统。你将学到的不只是几个API调用而是如何用“图”的思维来设计和实现可扩展的智能体架构。读完本文你将能理解核心清晰掌握LangGraph中State、Node、Edge、Condition等核心概念及其设计哲学。搭建环境快速配置开发环境并理解不同大模型后端OpenAI、Ollama等的接入方式。实战编码完成一个完整的“旅行规划多智能体”项目涵盖从需求分析到代码落地的全流程。掌握进阶学会如何为智能体添加“记忆”、实现循环判断、以及进行错误处理和调试。避开深坑识别开发中的常见陷阱并获得可直接用于生产的最佳实践建议。我们直接从最关键的架构思想开始。1. 为什么你需要LangGraph从“脚本”到“编排”的思维跃迁在LangGraph出现之前构建多智能体系统通常有两种方式线性脚本式在代码里硬编码调用顺序例如先调用“研究Agent”拿到结果后再调用“写作Agent”。这种方式简单但毫无灵活性增加一个审核Agent就需要重写流程。消息队列式让每个Agent监听一个消息队列进行异步通信。这解决了耦合问题但带来了新的复杂度消息格式定义、序列化、错误重试、状态全局管理等需要大量基础设施工作。LangGraph提供了一种折中且优雅的方案用“图”来显式定义工作流。你可以把每个智能体或任何函数看作图中的一个“节点”Node节点之间的连线“边”Edge定义了执行路径。一个特殊的“状态”State对象在整个图中流转携带了所有上下文信息。这种模式带来了几个立竿见影的好处可视化与可调试性工作流不再是隐藏在代码逻辑里而是可以直观地画出来。LangGraph Studio甚至能让你实时调试图的执行。内置状态管理你不用自己设计一个全局变量或数据库来传递数据State对象帮你安全地管理。灵活的流程控制支持条件分支if-else、循环while、并行等复杂逻辑轻松实现“如果分析结果不完整则重新分析”这类需求。与LangChain无缝集成可以直接使用LangChain丰富的组件Tools, Prompts, LLMs生态优势明显。接下来我们深入其核心概念。2. LangGraph核心四要素State, Node, Edge, Conditional Edge理解这四个概念就掌握了LangGraph的命门。2.1 State工作流的共享内存State是一个字典或Pydantic模型它是在整个图执行过程中唯一传递的对象。所有节点都读取和修改它。设计一个好的State结构是成功的第一步。关键点State应该是扁平的、描述当前任务进度的数据结构。例如一个写作Agent的State可能包含{topic: str, research_materials: list, outline: str, final_draft: str}。2.2 Node执行单元Node就是一个普通的Python函数或可调用对象它接收当前的State执行一些操作如调用LLM、运行工具、处理数据然后返回一个包含对State修改的字典。def research_agent(state: dict): 研究节点根据主题搜集信息 topic state[topic] # 调用LLM或搜索工具进行研究 research_result call_llm(f请搜集关于{topic}的资料) # 返回要更新到State中的内容 return {research_materials: research_result}2.3 Edge执行路径Edge定义了节点执行完毕后下一步应该去哪个节点。最简单的边是“起始边”和“普通边”它们直接连接两个节点。2.4 Conditional Edge让图“活”起来这是LangGraph最强大的特性之一。条件边根据当前State的内容动态决定下一个节点。这实现了if-else和循环逻辑。def should_continue(state: dict) - str: 根据大纲质量决定下一步继续润色还是结束 outline_quality state.get(outline_quality, poor) if outline_quality good: return end # 前往结束节点 else: return rewrite # 前往重写节点把这四个要素组合起来你就得到了一个能处理复杂逻辑的工作流“图”。下面我们进入实战环节。3. 环境准备模型、依赖与工具选择在开始写代码前需要准备好基础环境。本文以OpenAI GPT-4o模型为例同时也会说明如何切换为本地模型如通过Ollama。3.1 创建虚拟环境与安装依赖强烈建议使用虚拟环境来管理依赖。# 1. 创建并激活虚拟环境 (以conda为例) conda create -n langgraph-demo python3.10 conda activate langgraph-demo # 2. 安装核心库 pip install langgraph langchain langchain-openai # 3. 安装可选工具库用于示例中的搜索、计算等 pip install langchain-community duckduckgo-search tavily-pythonlanggraph: 核心库。langchain: 提供链、提示词模板等基础组件。langchain-openai: OpenAI模型官方集成。langchain-community,duckduckgo-search,tavily-python: 用于给Agent提供搜索、计算等能力的工具。3.2 配置API密钥你需要准备OpenAI的API密钥。将其设置为环境变量是最安全的方式。# Linux/Mac export OPENAI_API_KEYyour-api-key-here # Windows (PowerShell) $env:OPENAI_API_KEYyour-api-key-here在代码中可以通过os.getenv读取。如果你想使用本地模型如Ollama安装Ollama并拉取模型如llama3.1ollama pull llama3.1安装对应的LangChain集成pip install langchain-ollama在代码中将ChatOpenAI替换为ChatOllama并指定基础URL和模型名。from langchain_ollama import ChatOllama llm ChatOllama(modelllama3.1, base_urlhttp://localhost:11434)注意本地模型在复杂逻辑推理和指令遵循上可能弱于GPT-4建议在概念验证阶段使用GPT-4部署时根据成本和要求选择模型。4. 实战构建一个旅行规划多智能体系统我们将构建一个包含三个智能体的系统目的地研究Agent根据用户模糊需求如“我想去一个温暖的海边放松”推荐具体目的地并列出理由。行程规划Agent针对选定的目的地生成一份详细的每日行程安排。预算评估Agent根据行程估算大致花费并给出省钱建议。4.1 第一步定义StateState是我们工作流的蓝图。我们使用Pydantic BaseModel来获得类型提示和验证。from typing import TypedDict, List, Optional, Annotated from langgraph.graph.message import add_messages import operator # 使用TypedDict定义StateLangGraph推荐方式 class TravelPlanState(TypedDict): 旅行规划工作流的状态 # 用户原始输入 user_request: str # 研究Agent的输出推荐的目的地列表 recommended_destinations: List[str] # 用户选择或系统首选的目的地 selected_destination: Optional[str] # 行程规划Agent输出的详细行程 detailed_itinerary: Optional[str] # 预算评估Agent输出的预算分析 budget_analysis: Optional[str] # 用于在节点间传递消息的历史可选用于更复杂的对话 messages: Annotated[list, add_messages]这里我们使用了TypedDict和Annotated。add_messages是一个特殊的缩减器reducer它能自动将新的消息追加到messages列表中这对于构建对话式Agent非常有用。在本例中我们主要用前几个字段。4.2 第二步创建各个智能体节点每个节点都是一个函数接收State返回State的更新。from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate import os # 初始化LLM llm ChatOpenAI(modelgpt-4o, api_keyos.getenv(OPENAI_API_KEY)) def research_destination_node(state: TravelPlanState) - dict: 节点1研究目的地 user_request state[user_request] # 构建提示词 prompt ChatPromptTemplate.from_messages([ (system, 你是一个专业的旅行顾问擅长根据用户的模糊描述推荐具体目的地。), (human, 用户的需求是{request}。请推荐2-3个最符合要求的具体旅行目的地城市或地区并为每个目的地用一句话说明推荐理由。) ]) # 创建链并调用 chain prompt | llm response chain.invoke({request: user_request}) # 解析响应这里简单返回内容实际可做结构化解析 recommendations response.content # 更新State return { recommended_destinations: [rec.strip() for rec in recommendations.split(\n) if rec.strip()], selected_destination: recommendations.split(\n)[0].split(。)[0] if recommendations else None # 简单取第一个作为默认选择 } def plan_itinerary_node(state: TravelPlanState) - dict: 节点2规划行程 destination state[selected_destination] if not destination: return {detailed_itinerary: 错误未选择目的地} prompt ChatPromptTemplate.from_messages([ (system, 你是一个资深的行程规划师能为任何目的地制定详尽的3天2晚行程。), (human, 为目的地 {dest} 规划一份详细的3天2晚行程。包括每天的上午、下午、晚上的活动安排餐饮建议以及交通提示。格式清晰。) ]) chain prompt | llm response chain.invoke({dest: destination}) return {detailed_itinerary: response.content} def assess_budget_node(state: TravelPlanState) - dict: 节点3评估预算 destination state[selected_destination] itinerary state[detailed_itinerary] prompt ChatPromptTemplate.from_messages([ (system, 你是一个精明的财务分析师擅长估算旅行开销。), (human, 目的地{dest} 参考行程 {itinerary} 请根据以上行程估算一位中等消费水平旅行者的总花费按人民币计算。请按以下类别拆分 1. 机票/交通大交通 2. 住宿 3. 餐饮 4. 门票与活动 5. 市内交通与其他 最后给出一个总预算范围并提供2-3条节省预算的实用建议。 ) ]) chain prompt | llm response chain.invoke({dest: destination, itinerary: itinerary}) return {budget_analysis: response.content}4.3 第三步构建图并定义流程这是将节点和边组装起来的关键步骤。from langgraph.graph import StateGraph, END # 1. 创建一个图并指定State的类型 workflow StateGraph(TravelPlanState) # 2. 将节点添加到图中 workflow.add_node(research, research_destination_node) workflow.add_node(plan, plan_itinerary_node) workflow.add_node(assess_budget, assess_budget_node) # 3. 设置入口点 workflow.set_entry_point(research) # 4. 添加普通边线性执行 workflow.add_edge(research, plan) workflow.add_edge(plan, assess_budget) workflow.add_edge(assess_budget, END) # END是LangGraph内置的结束节点 # 5. 编译图 app workflow.compile()现在一个简单的线性工作流就定义好了研究 - 规划 - 评估预算 - 结束。4.4 第四步运行与测试让我们运行这个工作流看看效果。# 定义初始状态 initial_state: TravelPlanState { user_request: 我想在12月去一个温暖、有美食、适合放松的海边目的地预算中等。, recommended_destinations: [], selected_destination: None, detailed_itinerary: None, budget_analysis: None, messages: [] } # 运行图 final_state app.invoke(initial_state) # 打印结果 print(*50) print(用户需求:, final_state[user_request]) print(\n--- 推荐目的地 ---) for i, dest in enumerate(final_state[recommended_destinations], 1): print(f{i}. {dest}) print(\n--- 选定目的地 ---) print(final_state[selected_destination]) print(\n--- 详细行程 ---) print(final_state[detailed_itinerary]) print(\n--- 预算评估 ---) print(final_state[budget_analysis]) print(*50)执行上述代码你将得到一份完整的旅行规划报告。但这只是一个开始。真正的威力在于引入条件逻辑。5. 进阶引入条件边与循环打造智能工作流假设我们想让系统更智能如果研究Agent推荐的目的地都不太理想例如LLM自己判断推荐信心不足则让一个“人工审核”节点介入或者让用户选择。我们需要修改State和流程。5.1 扩展State并修改研究节点class EnhancedTravelState(TypedDict): user_request: str recommended_destinations: List[str] # 新增研究质量评分 research_confidence: float selected_destination: Optional[str] detailed_itinerary: Optional[str] budget_analysis: Optional[str] # 新增是否需要人工介入 needs_human_review: bool messages: Annotated[list, add_messages] def research_destination_node_v2(state: EnhancedTravelState) - dict: 增强版研究节点同时输出信心评分 user_request state[user_request] prompt ChatPromptTemplate.from_messages([ (system, 你是一个专业的旅行顾问。请根据用户需求推荐2-3个目的地并为你这次推荐的总体信心打分0.0-1.0。 信心基于需求的明确性和目的地的匹配度。输出格式为 目的地1: 理由1 目的地2: 理由2 信心: 0.85), (human, 用户需求{request}) ]) chain prompt | llm response chain.invoke({request: user_request}) content response.content # 简单解析实际应用应使用更稳健的解析如OutputParser lines [l.strip() for l in content.split(\n) if l.strip()] dests [] confidence 0.7 # 默认值 for line in lines: if line.startswith(信心:): try: confidence float(line.split(:)[1].strip()) except: pass elif : in line and not line.startswith(信心): dests.append(line) return { recommended_destinations: dests, research_confidence: confidence, selected_destination: dests[0].split(:)[0] if dests else None, needs_human_review: confidence 0.6 # 信心低于0.6则需人工审核 }5.2 创建人工审核节点和条件路由函数def human_review_node(state: EnhancedTravelState) - dict: 模拟人工审核节点实际中可能是发送邮件、写入工单系统 print(f\n[模拟人工审核] 系统对推荐目的地信心不足({state[research_confidence]:.2f})。) print(f推荐结果: {state[recommended_destinations]}) # 模拟人工输入这里我们硬编码一个选择 # 实际场景中这里可以连接到一个UI界面或等待API回调 manual_choice 三亚 print(f[模拟人工审核] 人工干预选择目的地: {manual_choice}) return {selected_destination: manual_choice, needs_human_review: False} def route_after_research(state: EnhancedTravelState) - str: 条件路由函数决定研究后是去人工审核还是继续规划 if state.get(needs_human_review, False): return human_review else: return plan5.3 重新构建带条件分支的图from langgraph.graph import StateGraph, END workflow_v2 StateGraph(EnhancedTravelState) # 添加节点 workflow_v2.add_node(research, research_destination_node_v2) workflow_v2.add_node(human_review, human_review_node) workflow_v2.add_node(plan, plan_itinerary_node) # 复用之前的节点 workflow_v2.add_node(assess_budget, assess_budget_node) # 复用之前的节点 # 设置入口 workflow_v2.set_entry_point(research) # 添加条件边研究完成后根据条件路由 workflow_v2.add_conditional_edges( research, route_after_research, # 这个函数返回下一个节点的名字 { human_review: human_review, plan: plan } ) # 添加普通边 workflow_v2.add_edge(human_review, plan) # 人工审核后继续规划 workflow_v2.add_edge(plan, assess_budget) workflow_v2.add_edge(assess_budget, END) app_v2 workflow_v2.compile()现在当你运行app_v2.invoke(initial_state)时如果LLM对推荐信心不足比如用户需求非常模糊“我想出去走走”工作流会自动跳转到“人工审核”节点模拟人工干预后再继续后续流程。6. 运行、调试与可视化6.1 运行与检查状态LangGraph的app.invoke()返回最终状态。你还可以使用app.stream()来流式执行观察每个节点执行前后的状态变化这对调试至关重要。# 流式执行观察每一步 inputs EnhancedTravelState(user_request我想去个有意思的地方, ...) # 初始化其他字段 for step in app_v2.stream(inputs): node_name, node_output next(iter(step.items())) print(f--- 节点 [{node_name}] 执行完成 ---) print(f输出: {node_output}\n)6.2 使用LangGraph Studio进行可视化强烈推荐LangGraph Studio是一个Web界面可以可视化你的图结构并逐步调试执行过程。安装pip install langgraph-cli在项目目录下启动langgraph studio浏览器打开http://localhost:8501将你的图编译代码app workflow.compile()保存到一个Python文件如travel_agent.py然后在Studio中打开它。你可以看到节点和边的可视化图点击节点可以查看输入/输出极大地简化了复杂工作流的理解和调试。7. 常见问题与排查思路在开发LangGraph应用时你可能会遇到以下典型问题问题现象可能原因排查方式解决方案KeyError当访问State字段1. State的TypedDict定义与节点返回的更新字典键不匹配。2. 前驱节点未返回该字段。1. 检查State类型定义和所有节点的返回值。2. 使用app.stream()观察每个节点后的State。确保所有节点返回的字典键都在State类型中有定义或使用Optional类型。图编译失败提示节点未定义在add_edge或add_conditional_edges中引用了未添加的节点名。仔细检查add_node和add_edge调用中的节点名字符串是否完全一致。使用常量或枚举来定义节点名避免拼写错误。条件边路由函数返回的值不在映射中add_conditional_edges的映射字典未包含路由函数所有可能的返回值。检查路由函数的所有return语句确保每个返回值都出现在边映射的key中。在边映射中使用default键设置默认路由或确保全覆盖。LLM调用超时或报错1. API密钥错误或额度不足。2. 网络问题。3. 提示词导致LLM输出格式不符合预期。1. 检查环境变量和账单。2. 增加超时设置。3. 简化提示词使用OutputParser。1. 配置正确的API密钥和代理。2. 使用llm ChatOpenAI(..., timeout30)。3. 使用with_structured_output或PydanticOutputParser确保输出格式。图陷入无限循环条件边逻辑错误导致在几个节点间来回跳转无法到达END。使用LangGraph Studio可视化执行流程检查循环路径。在条件路由函数中添加“最大重试次数”逻辑或确保存在指向END的路径。状态更新不符合预期多个节点并发修改同一字段如果设置了并发或缩减器reducer逻辑有误。理解Annotated字段的缩减器如add_messages是如何工作的。对于非列表的简单字段直接赋值覆盖即可。对于列表明确使用operator.add等缩减器或手动合并逻辑。8. 最佳实践与工程建议将LangGraph用于实际项目时遵循以下建议可以避免很多麻烦精心设计State保持扁平避免嵌套过深的结构简化数据的存取。明确类型始终使用TypedDict或Pydantic BaseModel来定义State以获得良好的类型提示和早期错误检测。区分持久态与临时态考虑哪些数据需要在整个工作流中持久化哪些只是中间计算产物。节点设计原则单一职责每个节点只做一件事。例如一个节点负责调用LLM另一个节点负责解析LLM的响应。幂等性与容错节点函数应尽可能设计成幂等的并包含基本的错误处理如重试、降级。可测试性将节点函数与LangGraph的绑定逻辑分离使其可以独立进行单元测试。利用LangChain生态工具Tools为你的Agent配备搜索、计算、代码执行等工具大幅扩展其能力。使用tool装饰器轻松创建。提示词模板使用ChatPromptTemplate管理复杂的提示词支持少样本、聊天历史等。输出解析器使用PydanticOutputParser或JsonOutputParser确保LLM输出结构化数据避免脆弱的字符串解析。生产环境部署持久化State对于长时间运行或需要中断恢复的工作流需要将State持久化到数据库。LangGraph的Checkpointer抽象支持此功能。异步支持LangGraph天然支持异步节点async def在需要调用外部API时使用异步可以极大提高吞吐量。监控与日志为关键节点添加详细的日志记录记录输入、输出和耗时。考虑集成像LangSmith这样的LLM应用监控平台。版本控制与团队协作将工作流图的定义代码化并纳入Git版本控制。当工作流逻辑变更时通过LangGraph Studio可视化对比变更确保理解对执行路径的影响。9. 总结与下一步探索通过本文你已经掌握了LangGraph构建多智能体系统的核心脉络从State设计、Node实现、Edge连接到条件分支。我们完成了一个具备基础决策能力的旅行规划多智能体并探讨了可视化调试和工程化实践。LangGraph的真正价值在于它将Agent从“一次性对话”的范畴提升到了“可编程、可观测、可维护的复杂业务流程”的层面。这为开发AI原生应用提供了坚实的工程基础。下一步你可以从这些方向深入集成真实工具为你的Agent接入搜索引擎API、数据库查询、邮件发送等真实工具让它能真正操作外部系统。探索更复杂模式研究StateGraph的add_node()和add_edge()之外的高级API如实现子图as_node、并行执行、动态节点添加等。接入记忆与知识库结合LangChain的RAG检索增强生成技术让Agent拥有长期记忆和专属知识库处理更专业的领域问题。实现人工在环在关键决策点如预算超标、方案冲突设计human_review节点将决策权交给人构建人机协同系统。性能优化对于耗时长的节点如网络请求使用异步实现对于可以并行的分支利用LangGraph的并发执行能力。建议你将本文的示例代码作为起点复制到本地修改提示词、增加节点、尝试不同的条件逻辑亲手体验“画”出一个智能工作流的感觉。当你遇到问题时多利用app.stream()和LangGraph Studio进行调试它们是你理解复杂工作流的最佳伙伴。