LangGraph完全指南
LangGraph是LangChain生态中用于构建复杂Agent工作流的框架,通过图结构和状态机实现可控的、可循环的AI应用。
什么是LangGraph
为什么需要LangGraph
传统的LangChain Chain是线性的、单向的:
python
1# LangChain Chain - 线性流程2input -> chain1 -> chain2 -> chain3 -> output但实际应用往往需要:
- ✅ 循环和条件分支
- ✅ 多Agent协作
- ✅ 复杂的决策流程
- ✅ 人工干预和审批
- ✅ 状态管理和持久化
LangGraph通过图结构解决这些问题:
python
1# LangGraph - 图状流程2 ┌─────────┐3 │ Input │4 └────┬────┘5 │6 ┌────▼────┐7 │ Agent A │◄────┐8 └────┬────┘ │9 │ │10 ┌───▼───┐ │11 │ Judge │ │12 └───┬───┘ │13 │ │14 ┌─────┴─────┐ │15 │ │ │16 ┌──▼──┐ ┌──▼──┐ │17 │Done │ │Retry├─┘18 └─────┘ └─────┘核心概念
- State (状态): 在图中流动的数据
- Nodes (节点): 处理状态的函数
- Edges (边): 连接节点的路径
- Conditional Edges (条件边): 根据状态动态选择路径
快速开始
安装
bash
1pip install langgraphHello World
python
1from langgraph.graph import Graph2from typing import TypedDict34# 1. 定义状态5class State(TypedDict):6 message: str7 count: int89# 2. 定义节点函数10def process_node(state: State) -> State:11 state["count"] += 112 state["message"] = f"处理了 {state['count']} 次"13 return state1415def check_node(state: State) -> State:16 if state["count"] < 3:17 state["message"] += " - 继续"18 else:19 state["message"] += " - 完成"20 return state2122# 3. 构建图23workflow = Graph()2425# 添加节点26workflow.add_node("process", process_node)27workflow.add_node("check", check_node)2829# 添加边30workflow.add_edge("process", "check")3132# 添加条件边33def should_continue(state: State) -> str:34 if state["count"] < 3:35 return "process"36 return "end"3738workflow.add_conditional_edges(39 "check",40 should_continue,41 {42 "process": "process",43 "end": END44 }45)4647# 设置入口48workflow.set_entry_point("process")4950# 4. 编译并运行51app = workflow.compile()5253result = app.invoke({"message": "", "count": 0})54print(result)55# {'message': '处理了 3 次 - 完成', 'count': 3}核心组件详解
1. State (状态)
状态是图中流动的数据结构。
python
1from typing import TypedDict, Annotated2from operator import add34# 基础状态5class BasicState(TypedDict):6 input: str7 output: str89# 带类型注解的状态10class AdvancedState(TypedDict):11 # 普通字段(替换)12 current_task: str13 14 # 可累加字段(追加)15 messages: Annotated[list, add]16 logs: Annotated[list, add]1718# 使用示例19def node_a(state: AdvancedState) -> AdvancedState:20 return {21 "current_task": "任务A",22 "messages": ["消息A"], # 追加到现有列表23 "logs": ["日志A"]24 }2526def node_b(state: AdvancedState) -> AdvancedState:27 return {28 "current_task": "任务B", # 替换29 "messages": ["消息B"], # 追加30 "logs": ["日志B"]31 }3233# 执行后: messages = ["消息A", "消息B"]2. Nodes (节点)
节点是处理逻辑的载体。
python
1from langchain.chat_models import ChatOpenAI2from langchain.schema import HumanMessage34# 普通函数节点5def simple_node(state: State) -> State:6 state["value"] += 17 return state89# LLM节点10def llm_node(state: State) -> State:11 llm = ChatOpenAI()12 response = llm([HumanMessage(content=state["input"])])13 state["output"] = response.content14 return state1516# 异步节点17async def async_node(state: State) -> State:18 import asyncio19 await asyncio.sleep(1)20 state["processed"] = True21 return state2223# 带错误处理的节点24def safe_node(state: State) -> State:25 try:26 # 处理逻辑27 result = risky_operation(state["data"])28 state["result"] = result29 except Exception as e:30 state["error"] = str(e)31 return state3. Edges (边)
边定义节点间的连接。
python
1# 普通边 - 无条件连接2workflow.add_edge("node_a", "node_b")34# 条件边 - 根据状态选择路径5def router(state: State) -> str:6 if state["value"] > 10:7 return "high_path"8 else:9 return "low_path"1011workflow.add_conditional_edges(12 "decision_node",13 router,14 {15 "high_path": "node_high",16 "low_path": "node_low"17 }18)1920# 入口和出口21workflow.set_entry_point("start_node")22workflow.set_finish_point("end_node")实战项目
项目1: 简单的对话Agent
python
1from langgraph.graph import Graph, END2from langchain.chat_models import ChatOpenAI3from typing import TypedDict, Annotated4from operator import add56class ConversationState(TypedDict):7 messages: Annotated[list, add]8 next_action: str910# 对话节点11def chat_node(state: ConversationState) -> ConversationState:12 llm = ChatOpenAI(model="gpt-4")13 14 response = llm.invoke(state["messages"])15 16 return {17 "messages": [response],18 "next_action": "check"19 }2021# 检查节点 - 判断是否继续22def check_node(state: ConversationState) -> ConversationState:23 last_message = state["messages"][-1].content.lower()24 25 if "再见" in last_message or "拜拜" in last_message:26 state["next_action"] = "end"27 else:28 state["next_action"] = "continue"29 30 return state3132# 构建图33workflow = Graph()3435workflow.add_node("chat", chat_node)36workflow.add_node("check", check_node)3738workflow.add_edge("chat", "check")3940def router(state: ConversationState) -> str:41 return state["next_action"]4243workflow.add_conditional_edges(44 "check",45 router,46 {47 "continue": "chat",48 "end": END49 }50)5152workflow.set_entry_point("chat")5354app = workflow.compile()5556# 使用57from langchain.schema import HumanMessage5859result = app.invoke({60 "messages": [HumanMessage(content="你好")],61 "next_action": ""62})项目2: 多Agent协作系统
python
1from langgraph.graph import Graph, END2from langchain.chat_models import ChatOpenAI3from typing import TypedDict, List45class MultiAgentState(TypedDict):6 task: str7 research_result: str8 code_result: str9 review_result: str10 final_output: str11 current_agent: str1213# 研究Agent14def research_agent(state: MultiAgentState) -> MultiAgentState:15 llm = ChatOpenAI(model="gpt-4")16 17 prompt = f"""18 作为研究专家,请分析以下任务:19 {state['task']}20 21 提供技术方案和建议。22 """23 24 response = llm.invoke([{"role": "user", "content": prompt}])25 26 return {27 "research_result": response.content,28 "current_agent": "coder"29 }3031# 编码Agent32def coder_agent(state: MultiAgentState) -> MultiAgentState:33 llm = ChatOpenAI(model="gpt-4")34 35 prompt = f"""36 基于以下研究结果编写代码:37 {state['research_result']}38 39 任务:{state['task']}40 """41 42 response = llm.invoke([{"role": "user", "content": prompt}])43 44 return {45 "code_result": response.content,46 "current_agent": "reviewer"47 }4849# 审查Agent50def reviewer_agent(state: MultiAgentState) -> MultiAgentState:51 llm = ChatOpenAI(model="gpt-4")52 53 prompt = f"""54 审查以下代码:55 {state['code_result']}56 57 研究背景:{state['research_result']}58 59 如果代码有问题,返回"NEEDS_REVISION: 问题描述"60 如果代码没问题,返回"APPROVED: 审查意见"61 """62 63 response = llm.invoke([{"role": "user", "content": prompt}])64 65 return {66 "review_result": response.content,67 "current_agent": "router"68 }6970# 构建图71workflow = Graph()7273workflow.add_node("researcher", research_agent)74workflow.add_node("coder", coder_agent)75workflow.add_node("reviewer", reviewer_agent)7677workflow.add_edge("researcher", "coder")78workflow.add_edge("coder", "reviewer")7980# 条件路由81def review_router(state: MultiAgentState) -> str:82 if "NEEDS_REVISION" in state["review_result"]:83 return "coder" # 返回重新编码84 else:85 return "end" # 完成8687workflow.add_conditional_edges(88 "reviewer",89 review_router,90 {91 "coder": "coder",92 "end": END93 }94)9596workflow.set_entry_point("researcher")9798app = workflow.compile()99100# 使用101result = app.invoke({102 "task": "实现一个快速排序算法",103 "research_result": "",104 "code_result": "",105 "review_result": "",106 "final_output": "",107 "current_agent": ""108})项目3: RAG增强的问答系统
python
1from langgraph.graph import Graph, END2from langchain.vectorstores import Chroma3from langchain.embeddings import OpenAIEmbeddings4from langchain.chat_models import ChatOpenAI5from typing import TypedDict67class RAGState(TypedDict):8 question: str9 documents: list10 answer: str11 needs_clarification: bool12 clarification: str1314# 检索节点15def retrieve_node(state: RAGState) -> RAGState:16 vectorstore = Chroma(17 persist_directory="./db",18 embedding_function=OpenAIEmbeddings()19 )20 21 docs = vectorstore.similarity_search(22 state["question"],23 k=524 )25 26 return {27 "documents": [doc.page_content for doc in docs]28 }2930# 判断节点 - 是否需要澄清31def judge_node(state: RAGState) -> RAGState:32 if not state["documents"]:33 return {34 "needs_clarification": True,35 "clarification": "没有找到相关文档,请提供更多信息。"36 }37 38 # 检查文档相关性39 llm = ChatOpenAI()40 check_prompt = f"""41 问题:{state['question']}42 文档:{state['documents'][0][:200]}...43 44 这些文档是否足够回答问题?回答YES或NO。45 """46 47 response = llm.invoke([{"role": "user", "content": check_prompt}])48 49 if "NO" in response.content:50 return {51 "needs_clarification": True,52 "clarification": "找到的信息不够完整,请补充更多细节。"53 }54 55 return {"needs_clarification": False}5657# 生成节点58def generate_node(state: RAGState) -> RAGState:59 llm = ChatOpenAI(model="gpt-4")60 61 context = "\n\n".join(state["documents"])62 63 prompt = f"""64 基于以下上下文回答问题:65 66 上下文:67 {context}68 69 问题:{state['question']}70 71 请提供准确、详细的答案。72 """73 74 response = llm.invoke([{"role": "user", "content": prompt}])75 76 return {"answer": response.content}7778# 构建图79workflow = Graph()8081workflow.add_node("retrieve", retrieve_node)82workflow.add_node("judge", judge_node)83workflow.add_node("generate", generate_node)8485workflow.add_edge("retrieve", "judge")8687def judge_router(state: RAGState) -> str:88 if state["needs_clarification"]:89 return "end"90 return "generate"9192workflow.add_conditional_edges(93 "judge",94 judge_router,95 {96 "generate": "generate",97 "end": END98 }99)100101workflow.add_edge("generate", END)102103workflow.set_entry_point("retrieve")104105app = workflow.compile()项目4: 人工审批流程
python
1from langgraph.graph import Graph, END2from langgraph.checkpoint.sqlite import SqliteSaver3from typing import TypedDict45class ApprovalState(TypedDict):6 request: str7 analysis: str8 risk_level: str9 approved: bool10 human_decision: str1112# 分析节点13def analyze_node(state: ApprovalState) -> ApprovalState:14 llm = ChatOpenAI(model="gpt-4")15 16 prompt = f"""17 分析以下请求的风险等级(LOW/MEDIUM/HIGH):18 {state['request']}19 20 提供分析理由和风险评估。21 """22 23 response = llm.invoke([{"role": "user", "content": prompt}])24 analysis = response.content25 26 # 提取风险等级27 if "HIGH" in analysis:28 risk_level = "HIGH"29 elif "MEDIUM" in analysis:30 risk_level = "MEDIUM"31 else:32 risk_level = "LOW"33 34 return {35 "analysis": analysis,36 "risk_level": risk_level37 }3839# 决策路由40def decision_router(state: ApprovalState) -> str:41 if state["risk_level"] == "LOW":42 return "auto_approve"43 else:44 return "human_review"4546# 自动批准节点47def auto_approve_node(state: ApprovalState) -> ApprovalState:48 return {49 "approved": True,50 "human_decision": "自动批准(低风险)"51 }5253# 人工审批节点 - 需要中断54def human_review_node(state: ApprovalState) -> ApprovalState:55 # 这里会中断,等待人工输入56 return state5758# 构建图59workflow = Graph()6061workflow.add_node("analyze", analyze_node)62workflow.add_node("auto_approve", auto_approve_node)63workflow.add_node("human_review", human_review_node)6465workflow.add_conditional_edges(66 "analyze",67 decision_router,68 {69 "auto_approve": "auto_approve",70 "human_review": "human_review"71 }72)7374workflow.add_edge("auto_approve", END)75workflow.add_edge("human_review", END)7677workflow.set_entry_point("analyze")7879# 使用checkpoint支持中断和恢复80memory = SqliteSaver.from_conn_string(":memory:")81app = workflow.compile(checkpointer=memory)8283# 运行84config = {"configurable": {"thread_id": "1"}}8586# 第一次运行 - 可能会在human_review处中断87result = app.invoke({88 "request": "删除生产数据库",89 "analysis": "",90 "risk_level": "",91 "approved": False,92 "human_decision": ""93}, config)9495# 人工决策后继续96if result["risk_level"] in ["HIGH", "MEDIUM"]:97 # 更新状态98 app.update_state(99 config,100 {"approved": True, "human_decision": "人工批准"}101 )102 103 # 继续执行104 final_result = app.invoke(None, config)高级特性
1. 持久化和检查点
python
1from langgraph.checkpoint.sqlite import SqliteSaver23# 创建持久化存储4memory = SqliteSaver.from_conn_string("checkpoints.db")56# 编译时指定checkpointer7app = workflow.compile(checkpointer=memory)89# 使用thread_id跟踪对话10config = {"configurable": {"thread_id": "user-123"}}1112# 第一次调用13app.invoke({"input": "你好"}, config)1415# 稍后可以继续同一对话16app.invoke({"input": "继续之前的话题"}, config)1718# 查看历史状态19for state in app.get_state_history(config):20 print(state)2. 子图(Subgraphs)
python
1# 定义子图2def create_subworkflow():3 subgraph = Graph()4 5 subgraph.add_node("step1", step1_node)6 subgraph.add_node("step2", step2_node)7 subgraph.add_edge("step1", "step2")8 subgraph.add_edge("step2", END)9 subgraph.set_entry_point("step1")10 11 return subgraph.compile()1213# 在主图中使用子图14main_workflow = Graph()1516sub_app = create_subworkflow()1718def use_subgraph(state: State) -> State:19 result = sub_app.invoke({"data": state["data"]})20 state["result"] = result21 return state2223main_workflow.add_node("process", use_subgraph)3. 流式输出
python
1# 流式执行2for chunk in app.stream({"input": "你好"}):3 print(chunk)45# 异步流式6async for chunk in app.astream({"input": "你好"}):7 print(chunk)4. 并行执行
python
1from langgraph.graph import Graph23# 定义可并行的节点4workflow.add_node("task1", task1_node)5workflow.add_node("task2", task2_node)6workflow.add_node("task3", task3_node)7workflow.add_node("merge", merge_node)89# 从同一节点发出多条边 - 并行执行10workflow.add_edge("start", "task1")11workflow.add_edge("start", "task2")12workflow.add_edge("start", "task3")1314# 汇聚到merge节点15workflow.add_edge("task1", "merge")16workflow.add_edge("task2", "merge")17workflow.add_edge("task3", "merge")可视化和调试
可视化图结构
python
1from IPython.display import Image, display23# 生成图的Mermaid表示4graph_diagram = app.get_graph().draw_mermaid()5print(graph_diagram)67# 在Jupyter中显示8display(Image(app.get_graph().draw_mermaid_png()))调试技巧
python
1# 1. 使用verbose模式2app = workflow.compile(debug=True)34# 2. 检查中间状态5def debug_node(state: State) -> State:6 print(f"当前状态: {state}")7 return state89workflow.add_node("debug", debug_node)1011# 3. 使用断点12def breakpoint_node(state: State) -> State:13 import pdb; pdb.set_trace()14 return state最佳实践
1. 状态设计
python
1# ✅ 好的状态设计2class GoodState(TypedDict):3 # 清晰的命名4 user_input: str5 llm_response: str6 7 # 使用Annotated处理累加8 conversation_history: Annotated[list, add]9 10 # 包含元数据11 timestamp: str12 user_id: str1314# ❌ 不好的状态设计15class BadState(TypedDict):16 data: dict # 太模糊17 stuff: list # 不清楚用途18 x: str # 无意义的命名2. 节点职责单一
python
1# ✅ 职责单一2def retrieve_node(state):3 # 只负责检索4 docs = vectorstore.search(state["query"])5 return {"documents": docs}67def generate_node(state):8 # 只负责生成9 answer = llm.generate(state["documents"])10 return {"answer": answer}1112# ❌ 职责混乱13def do_everything_node(state):14 docs = vectorstore.search(state["query"])15 answer = llm.generate(docs)16 score = evaluate(answer)17 # 做太多事情18 return {"result": ...}3. 错误处理
python
1def safe_node(state: State) -> State:2 try:3 result = process(state["data"])4 return {"result": result, "error": None}5 except Exception as e:6 return {7 "result": None,8 "error": str(e),9 "needs_retry": True10 }1112# 在路由中处理错误13def error_router(state: State) -> str:14 if state.get("error"):15 if state.get("retry_count", 0) < 3:16 return "retry"17 return "error_handler"18 return "continue"与其他框架对比
| 特性 | LangGraph | LangChain | CrewAI | AutoGen |
|---|---|---|---|---|
| 循环支持 | ✅ 原生支持 | ❌ 不支持 | ✅ 支持 | ✅ 支持 |
| 条件分支 | ✅ 灵活 | ⚠️ 有限 | ⚠️ 有限 | ✅ 灵活 |
| 状态管理 | ✅ 强大 | ⚠️ 基础 | ⚠️ 基础 | ✅ 强大 |
| 可视化 | ✅ 内置 | ❌ 无 | ❌ 无 | ⚠️ 有限 |
| 学习曲线 | 中等 | 低 | 低 | 高 |
| 灵活性 | 极高 | 中 | 中 | 高 |
总结
LangGraph是构建复杂Agent系统的强大工具,适合:
- ✅ 需要循环和条件判断的场景
- ✅ 多Agent协作系统
- ✅ 需要人工干预的工作流
- ✅ 复杂的决策流程
- ✅ 需要状态持久化的应用
下一步
- LangChain基础 - 了解LangChain生态
- Agent设计模式 - 学习常见的Agent模式
- 生产部署 - 部署LangGraph应用
评论区 / Comments