第06章:LangGraph 入门

2 阅读4分钟

第06章:LangGraph 入门

版本:LangChain v1.3.7 | 讲师:汤姆小白


1. LangGraph 是什么

LangGraph 是 LangChain 生态的底层编排运行时,专门用于构建有状态、长时间运行的 Agent。

简单理解:LangChain 做"零件",LangGraph 做"组装线"

三者关系

产品定位适用场景
LangChain基础构件(LLM、Tools、Retrieval)提供标准化的组件
LangGraph编排运行时复杂工作流、多步推理、持久化
Deep Agents开箱即用 Agent 套件高级 Agent,内置规划/子代理

create_agent 底层就是基于 LangGraph 实现的。学 LangGraph 就是学 Agent 的底层原理。

安装

pip install langgraph

2. StateGraph:定义工作流

2.1 最简单的图

from langgraph.graph import StateGraph, MessagesState, START, END
from langchain.chat_models import init_chat_model

model = init_chat_model("openai:gpt-4o-mini")

def call_model(state: MessagesState):
    """节点函数:调用模型"""
    response = model.invoke(state["messages"])
    return {"messages": [response]}

# 创建图
graph = StateGraph(MessagesState)

# 添加节点
graph.add_node("model", call_model)

# 添加边
graph.add_edge(START, "model")
graph.add_edge("model", END)

# 编译并执行
app = graph.compile()
result = app.invoke({"messages": [{"role": "user", "content": "你好!"}]})
print(result["messages"][-1].content)

2.2 StateGraph 核心概念

概念说明
StateGraph图的容器,定义工作流的状态类型
State在节点间传递的共享数据(如 MessagesState 是预定义的消息列表状态)
Node(节点)一个可执行的函数,接收 State 并返回 State 的部分更新
Edge(边)节点之间的连接,定义执行顺序
START / END特殊内置节点,表示图的起点和终点

2.3 自定义 State

from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END

class MyState(TypedDict):
    messages: list
    counter: int
    final_answer: str

def step1(state: MyState):
    return {"counter": state["counter"] + 1}

def step2(state: MyState):
    return {"final_answer": f"执行了 {state['counter']} 步"}

graph = StateGraph(MyState)
graph.add_node("step1", step1)
graph.add_node("step2", step2)
graph.add_edge(START, "step1")
graph.add_edge("step1", "step2")
graph.add_edge("step2", END)

app = graph.compile()
result = app.invoke({"messages": [], "counter": 0, "final_answer": ""})
print(result["final_answer"])  # 执行了 1 步

3. 条件边:根据状态选择路径

条件边让工作流能根据运行时状态动态决定下一步。

import random
from langgraph.graph import StateGraph, MessagesState, START, END

model = init_chat_model("openai:gpt-4o-mini")

def call_model(state: MessagesState):
    response = model.invoke(state["messages"])
    return {"messages": [response]}

def should_continue(state: MessagesState) -> str:
    """条件判断函数:返回下一个节点名"""
    last_message = state["messages"][-1]
    # 检查是否需要工具调用
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "tools"
    return END

def call_tools(state: MessagesState):
    """执行工具"""
    last_message = state["messages"][-1]
    # 这里简化处理
    return {"messages": [{"role": "tool", "content": "工具结果"}]}

graph = StateGraph(MessagesState)
graph.add_node("model", call_model)
graph.add_node("tools", call_tools)

graph.add_edge(START, "model")
graph.add_conditional_edges("model", should_continue, {
    "tools": "tools",
    END: END,
})
graph.add_edge("tools", "model")  # 工具结果返回模型

app = graph.compile()

条件边的三个参数:(源节点, 判断函数, 路由映射)。判断函数返回的字符串必须在路由映射中存在。


4. 持久化:断点恢复

Agent 执行中可能因网络、API 限流等原因中断。持久化让 Agent 能从断点继续,不丢失进度。

from langgraph.checkpoint.memory import MemorySaver

# 创建内存检查点(生产环境推荐用 SqliteSaver 或 PostgresSaver)
checkpointer = MemorySaver()

graph = StateGraph(MessagesState)
# ... 添加节点和边 ...
app = graph.compile(checkpointer=checkpointer)

# 执行时指定 thread_id
config = {"configurable": {"thread_id": "user_123"}}

# 第一次调用
result1 = app.invoke(
    {"messages": [{"role": "user", "content": "列出3个Python框架"}]},
    config=config
)

# 即使程序崩溃重启,用同一个 thread_id 继续
result2 = app.invoke(
    {"messages": [{"role": "user", "content": "详细说明第一个"}]},
    config=config  # 同一个 thread_id,自动加载历史
)

5. 人机协同:关键节点人工审批

在敏感操作(如删除文件、发送邮件)前暂停,等待人工确认。

from langgraph.types import interrupt

def sensitive_operation(state: MessagesState):
    """需要人工审批的节点"""
    # 暂停并询问用户
    approval = interrupt("即将删除重要数据,是否继续?")
    
    if approval == "yes":
        # 执行操作
        return {"messages": [{"role": "ai", "content": "操作已执行"}]}
    else:
        return {"messages": [{"role": "ai", "content": "操作已取消"}]}

# 在图中使用
graph.add_node("sensitive_op", sensitive_operation)
app = graph.compile(checkpointer=checkpointer)

# 第一次调用:会在 interrupt() 处暂停
result = app.invoke(input_data, config)
# 此时 result 包含中断信息

# 用户确认后,恢复执行
app.invoke(
    None,  # 无新输入
    config,
    # 传入用户确认的 Command
)

6. Stream:实时监控执行过程

# 流式输出每个节点的结果
for event in app.stream(
    {"messages": [{"role": "user", "content": "你好"}]},
    config={"configurable": {"thread_id": "1"}},
    stream_mode="values",
):
    # event 是当前完整状态
    last_msg = event["messages"][-1]
    print(f"[{last_msg.get('role', 'node')}] {last_msg.get('content', '')}")

7. LangGraph 与 create_agent 的关系

create_agent 本质上就是预先配置好的 LangGraph:

# create_agent 内部做的事 ≈
from langgraph.prebuilt import create_react_agent

# create_agent 自动创建了:
# - model 节点
# - tools 节点
# - 条件边(有工具调用→继续,无→结束)
# - 中间件机制
# - 流式支持

理解 LangGraph 后,你就能:

  • create_agent 不够灵活时,用 LangGraph 自定义 Agent 行为
  • 添加自定义逻辑到 Agent 循环中
  • 实现复杂的多 Agent 协作

本章小结

概念作用
StateGraph定义工作流图的容器
Node可执行函数,操作 State
Edge节点间的执行顺序
Conditional Edge根据状态动态路由
Checkpointer持久化状态,断点恢复
interrupt暂停等待人工审批
stream实时监控图执行

LangGraph 是 Agent 的"骨架",create_agent 是 LangGraph 的"快捷方式"。先学 create_agent 快速上手,再用 LangGraph 深入定制。