LangChain LangGraph
Module 1 Module 2 Module 3 Module 4 Module 5 Module 6
Module 1 · 基础入门
1 1-1 Simple Graph
2 1-2 Chain
3 1-3 Router
4 1-4 Agent
5 1-5 Agent Memory
6 1-6 Deployment
SUM Module Summary
HomeLangGraphModule 1 · 基础入门Module Summary
LANGGRAPH MODULE 1 · SUMMARY

LangGraph 基础入门
模块总结

从第一张图到生产部署,Module 1 构建了 LangGraph 的完整基础认知体系。

6子课程
4核心概念
1ReAct 循环
可扩展性
模块学习路径
Simple Graph
L1 · State · Node
Edge · compile
Chain
L2 · Messages
bind_tools · LLM
Router
L3 · ToolNode
tools_condition
Agent
L4 · ReAct 循环
多步推理
Memory
L5 · Checkpointer
thread_id
Deployment
L6 · Studio
langgraph.json
📌 模块知识脉络
图的三要素(L1)
  • State:节点间共享的数据
  • Node:处理逻辑单元
  • Edge:控制执行流向
消息与工具(L2+L3)
  • MessagesState 管理对话
  • bind_tools 注册工具
  • ToolNode 自动执行
Agent 与记忆(L4+L5)
  • ReAct 循环:推理→行动→观察
  • Checkpointer:持久化
  • thread_id:会话隔离
6 个子课程详解
1

Simple Graph

StateGraph · Node · Edge · State

LangGraph 的最小运行单元:一张由 State、Node、Edge 构成的有向图。这是理解后续所有课程的基础骨架。

  • State(TypedDict):图内节点共享的"共用白板",所有节点读写同一份数据
  • Node(函数):接收 State、返回更新字典的普通 Python 函数
  • Edge:普通边(固定方向)与条件边(运行时动态决定)
  • compile + invoke:编译图为可执行对象,传入初始 State 启动执行
  • START / END:图的虚拟入口和出口节点
核心洞察:LangGraph 用"图"代替 if/else——当 AI 需要循环调用工具、并行执行或人工介入时,图结构让流程可视化、可测试、可维护。
深度讲解 →
2

Chain

MessagesState · bind_tools · add_messages

在图中接入真实 LLM,引入消息对话系统。这是从"演示图"到"真实 AI 应用"的关键一步。

  • HumanMessage / AIMessage:LangChain 的标准消息格式,统一对话历史结构
  • MessagesState:内置 messages: Annotated[list, add_messages],开箱即用的对话状态
  • llm.invoke(messages):在 Node 内调用 LLM,输入消息列表,输出 AIMessage
  • bind_tools:将工具定义注入 LLM,让模型知道可以调用什么
  • add_messages Reducer:确保消息追加而非覆盖,保留完整对话历史
核心洞察:MessagesState 是 LangGraph 对话型 Agent 的标配起点,它预装了 add_messages Reducer,无需手动配置即可正确累积对话历史。
深度讲解 →
3

Router

ToolNode · tools_condition · 条件路由

让图根据 LLM 的输出自动决定"调用工具"还是"直接结束",是构建工具调用 Agent 的核心路由机制。

  • ToolNode:LangGraph 内置节点,自动解析 AIMessage 中的工具调用请求并执行
  • tools_condition:内置条件函数,检测 LLM 是否输出了工具调用 → 路由到 ToolNode 或 END
  • add_conditional_edges:将条件函数绑定到图边,实现动态路由
  • @tool 装饰器:将普通 Python 函数声明为 LangChain 工具,自动生成 JSON Schema
核心洞察:ToolNode + tools_condition 是 LangGraph 工具调用的"标准套件"——二者搭配可以用 4 行代码完成工具路由,无需手动解析工具调用结果。
深度讲解 →
4

Agent

ReAct 架构 · 工具循环 · 多步推理

在 Router 基础上加一条回边,构成真正的 Agent 循环:LLM 推理 → 调用工具 → 观察结果 → 再推理,直到问题解决。

  • ReAct 模式:Reasoning(推理)+ Acting(行动)交替迭代,是现代 LLM Agent 的主流范式
  • 循环边tools → agent 的回边让图形成环,支持无限次工具调用迭代
  • 工具调用序列:每次循环产生 AIMessage(含 tool_call)+ ToolMessage(工具结果)
  • 自动终止:LLM 不再输出工具调用时,tools_condition 路由到 END
核心洞察:Agent = Router + 一条回边。这一条回边的差异,让图从"单次决策"变成了"持续推理循环"——这是 LangGraph 图结构相对于 LangChain 链式调用最核心的能力提升。
深度讲解 →
5

Agent Memory

Checkpointer · MemorySaver · thread_id

为 Agent 加装"记忆",让它在多轮对话中记住之前的内容,在同一次运行的不同步骤间保持状态。

  • Checkpointer:LangGraph 的状态持久化机制,每个节点执行后自动保存 State 快照
  • MemorySaver:内存级 Checkpointer,进程内有效,开发调试首选
  • thread_id:对话会话的唯一标识,相同 thread_id 共享历史,不同 ID 互相隔离
  • compile(checkpointer=):挂载 Checkpointer 的唯一入口,编译时传入即可
核心洞察:MemorySaver 仅是入门版——它把状态存在内存里,进程重启就丢失。Module 2 会学习将其升级为 SqliteSaver(持久化到磁盘),这才是生产可用的记忆方案。
深度讲解 →
6

Deployment

LangGraph Studio · langgraph.json · API

将本地开发的图部署为生产服务。LangGraph Studio 提供可视化调试,LangGraph Cloud 提供一键 API 部署。

  • langgraph.json:部署配置文件,声明图的入口、依赖、环境变量
  • LangGraph Studio:本地可视化 IDE,实时查看图结构、State 快照、节点执行过程
  • LangGraph CLIlanggraph dev 启动本地服务,langgraph build 打包 Docker 镜像
  • RemoteGraph:通过 URL 连接远程部署的图,像本地图一样调用
核心洞察:Studio 的最大价值是调试而非部署——它让你在开发时能直观看到图的每一步 State 变化,比打印日志高效 10 倍。部署本身只需一个配置文件。
深度讲解 →
核心概念横向对比

Module 1 知识点速查表

6 个课程的核心 API、使用场景与关键说明

概念 / API所属课程核心作用关键用法
StateGraphL1图的构建器,接受 Schema 类StateGraph(MyState)
add_node / add_edgeL1向图中添加节点和边builder.add_node("n", fn)
compile / invokeL1编译图 / 执行图graph.invoke({"key": val})
MessagesStateL2内置对话状态,含 add_messagesclass S(MessagesState): ...
bind_toolsL2将工具列表注入 LLMllm.bind_tools([tool1, tool2])
ToolNodeL3自动执行 LLM 请求的工具ToolNode([tool1, tool2])
tools_conditionL3检测是否有工具调用,路由决策add_conditional_edges("agent", tools_condition)
ReAct 回边L4tools→agent 的循环边,实现迭代推理add_edge("tools", "agent")
MemorySaverL5内存级 Checkpointer,保存 State 快照compile(checkpointer=MemorySaver())
thread_idL5标识对话会话,相同 ID 共享历史{"configurable": {"thread_id": "x"}}
langgraph.jsonL6部署配置,声明图入口和依赖{"graphs": {"agent": "./graph.py:graph"}}
langgraph devL6启动 Studio 可视化本地调试服务CLI 命令
模块核心收获
🧩

图 = 流程控制的语言

LangGraph 用 Node + Edge 描述 AI 的执行流程,比 if/else 更直观,比 LangChain Chain 更灵活——图天然支持分支、循环、并行。

💬

MessagesState 是对话的基石

MessagesState + add_messages Reducer 是所有对话型 Agent 的起点。理解它如何追加消息,是写出正确 Chatbot 的前提。

🔧

ToolNode 封装了工具调用细节

ToolNode + tools_condition 自动处理工具调用的解析和执行,无需手动提取 tool_calls 字段,显著减少样板代码。

🔁

一条回边造就 ReAct Agent

Agent = Router + add_edge("tools", "agent")。这条回边让图形成环,LLM 得以持续推理直到自主判断任务完成。

🧠

thread_id 是记忆的钥匙

每次 invoke 传入相同 thread_id,图就能从上次结束的地方继续。不同用户用不同 ID,状态完全隔离。

🚀

Studio 让调试可视化

LangGraph Studio 能实时展示图结构、每步 State、工具调用详情。开发复杂 Agent 时,它比任何 print 语句都有效。

返回 Module 1 首页
综合实战项目
Project

带工具调用与持久记忆的智能旅行助手
Travel Planning Agent

一个能够多步推理、自动调用工具、跨轮记忆用户偏好的旅行规划助手。它将 Module 1 的全部 6 个核心知识点串联成一个完整的可运行项目。

L1 StateGraph L2 MessagesState L3 ToolNode L4 ReAct 循环 L5 MemorySaver L6 Studio 部署
项目能力
查询城市天气
搜索景点信息
估算旅行预算
多步推理规划行程
记住用户跨轮偏好
Studio 可视化调试
图结构 · ReAct Agent + Checkpointer
L4 · ReAct 执行循环
START
初始消息
agent 节点
L2 · LLM 推理
tools_condition L3 · 路由判断
tools 节点
L3 · ToolNode 执行
回边 L4
END
无工具调用时
💾 MemorySaver Checkpointer · L5 · 每步快照 → thread_id 隔离会话
代码块 1 / 5
工具定义 —— L1 + L2 + L3
# ── 依赖导入 ───────────────────────────────────────────
from typing import Annotated
from typing_extensions import TypedDict
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import MemorySaver

# ════════════════════════════════════════════════════
# 【L3】工具定义:@tool 装饰器自动生成 JSON Schema
#   LLM 通过 Schema 了解每个工具的参数和用途
#   ToolNode 根据 LLM 输出的 tool_call 自动匹配并执行
# ════════════════════════════════════════════════════
@tool
def get_weather(city: str) -> str:
    """获取指定城市的当前天气信息。"""
    # 实际项目中调用真实天气 API,此处模拟返回
    weather_data = {
        "北京": "晴,26°C,微风",
        "上海": "多云,22°C,东南风3级",
        "成都": "阴,18°C,无风",
    }
    return weather_data.get(city, f"{city}:天气数据暂不可用")

@tool
def search_attractions(city: str, category: str = "all") -> str:
    """搜索城市的热门景点。category 可为 'nature'(自然)、'culture'(文化)或 'all'(全部)。"""
    attractions = {
        "北京": ["故宫", "长城", "颐和园", "天坛"],
        "上海": ["外滩", "豫园", "东方明珠", "田子坊"],
        "成都": ["大熊猫基地", "宽窄巷子", "武侯祠", "锦里"],
    }
    spots = attractions.get(city, [])
    return f"{city}热门景点:{', '.join(spots)}" if spots else f"暂无{city}景点数据"

@tool
def estimate_budget(city: str, days: int, style: str = "standard") -> str:
    """估算旅行预算。style 可为 'budget'(经济)、'standard'(标准)、'luxury'(豪华)。"""
    per_day = {"budget": 300, "standard": 600, "luxury": 1500}
    daily_cost = per_day.get(style, 600)
    total = daily_cost * days
    return f"{city} {days}天{style}旅行预计费用:¥{total}(每天约¥{daily_cost})"

# 工具列表:注册所有可用工具
tools = [get_weather, search_attractions, estimate_budget]
L3 · @tool 装饰器的作用

@tool 做了两件事:①读取函数的类型注解和 docstring,自动生成 LLM 能理解的 JSON Schema;②将普通函数包装成 BaseTool 对象,供 ToolNodebind_tools 使用。函数的 docstring 就是工具描述,写得越清晰,LLM 越能准确判断何时调用该工具。

代码块 2 / 5
State 定义与 Agent 节点 —— L1 + L2
# ════════════════════════════════════════════════════
# 【L1 + L2】State 定义
#   · 继承 MessagesState(L2):内置 messages 字段 +
#     add_messages Reducer,开箱即用
#   · 扩展自定义字段(L1):TypedDict 风格添加额外状态
# ════════════════════════════════════════════════════
class TravelState(MessagesState):
    # MessagesState 已内置:messages: Annotated[list[AnyMessage], add_messages]
    # 下面是扩展字段
    destination: str         # 用户确定的目的地(默认覆盖策略)
    travel_days: int          # 旅行天数

# ════════════════════════════════════════════════════
# 【L2】LLM 初始化 + bind_tools
#   · bind_tools 将工具的 JSON Schema 注入 LLM 的系统提示
#   · LLM 输出 tool_call 时,内容是 JSON 格式的参数
# ════════════════════════════════════════════════════
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
llm_with_tools = llm.bind_tools(tools)  # 【L2】核心:让 LLM 知道有哪些工具

# ════════════════════════════════════════════════════
# 【L2 + L4】Agent 节点:ReAct 循环的推理端
#   · 读取完整消息历史,带入工具上下文,调用 LLM
#   · 返回 {"messages": [新的 AIMessage]}
#   · add_messages Reducer 自动追加,不覆盖历史
# ════════════════════════════════════════════════════
def agent(state: TravelState):
    system_prompt = SystemMessage(content=(
        "你是一个专业的旅行规划助手。你可以查询天气、搜索景点、估算预算。"
        "请根据用户需求,综合使用工具制定完整的旅行建议。"
    ))
    # state["messages"] 包含完整的对话历史(由 add_messages Reducer 维护)
    response = llm_with_tools.invoke([system_prompt] + state["messages"])
    return {"messages": [response]}  # 返回字典,Reducer 自动追加
L2 · MessagesState 的继承优势

继承 MessagesState 比从零定义 TypedDict 省去了 Annotated[list, add_messages] 的配置。同时支持自由扩展字段——destinationtravel_days 使用默认覆盖策略,节点每次写入都会替换旧值。

L2 · bind_tools 的底层机制

llm.bind_tools(tools) 在每次请求时把工具的 JSON Schema 附加到 API 调用的 tools 参数里。LLM 看到工具列表后,可以输出一个特殊的 AIMessage,其 tool_calls 字段包含工具名和参数——这就是触发 ToolNode 执行的信号。

代码块 3 / 5
图的构建:ReAct 结构 —— L1 + L3 + L4
# ════════════════════════════════════════════════════
# 【L1】StateGraph:图的构建器
# 【L3】ToolNode:自动执行工具调用的内置节点
# ════════════════════════════════════════════════════
tool_node = ToolNode(tools)  # 【L3】传入工具列表,自动匹配 tool_call 并执行

builder = StateGraph(TravelState)   # 【L1】创建图,传入 State Schema

# ── 注册节点 ────────────────────────────────────────
builder.add_node("agent", agent)       # 【L1】LLM 推理节点
builder.add_node("tools", tool_node)  # 【L3】工具执行节点

# ── 连接边 ──────────────────────────────────────────
builder.add_edge(START, "agent")       # 【L1】入口 → agent

# 【L3】条件边:LLM 有工具调用 → tools,否则 → END
builder.add_conditional_edges(
    "agent",
    tools_condition,   # 内置路由函数,检测 tool_calls 是否存在
)

# 【L4】关键!这条回边让图形成环,实现 ReAct 循环
# tools 执行完工具后,把结果(ToolMessage)追加进 messages,
# 然后重新路由到 agent,让 LLM 看到工具结果继续推理
builder.add_edge("tools", "agent")

# ── 【L5】挂载 MemorySaver,实现跨轮对话记忆 ──────
memory = MemorySaver()
graph = builder.compile(checkpointer=memory)  # 【L5】编译时注入 Checkpointer
L4 · 一条回边如何造就 ReAct 循环

没有 add_edge("tools", "agent") 时,图在调用一次工具后就结束。加上这条回边后:工具结果(ToolMessage)追加进 messages → agent 节点重新读取完整消息历史(含工具结果)→ LLM 基于新信息再次推理 → 可能继续调用工具或直接回答。这个循环持续到 LLM 不再输出工具调用为止,tools_condition 此时路由到 END。

代码块 4 / 5
运行与多轮记忆 —— L5
# ════════════════════════════════════════════════════
# 【L5】thread_id:会话标识
#   · 相同 thread_id → 共享同一对话历史
#   · 不同 thread_id → 完全独立,互不干扰
# ════════════════════════════════════════════════════
config = {"configurable": {"thread_id": "user_alice_trip_001"}}

# ── 第 1 轮:询问北京旅行建议 ─────────────────────
result_1 = graph.invoke(
    {"messages": [HumanMessage(content="我想去北京旅行3天,帮我规划一下")]},
    config=config,
)
# Agent 会自动调用:get_weather("北京") → search_attractions("北京") →
# estimate_budget("北京", 3, "standard"),然后综合给出回答

# ── 第 2 轮:追问(自动记得第 1 轮内容)────────────
result_2 = graph.invoke(
    {"messages": [HumanMessage(content="如果改成豪华出行,费用大概是多少?")]},
    config=config,  # 同一 thread_id → 记得"北京3天"的上下文
)
# LLM 知道上下文是北京3天,直接调用 estimate_budget("北京", 3, "luxury")

# ── 多用户隔离示例 ──────────────────────────────────
alice_config = {"configurable": {"thread_id": "alice_001"}}
bob_config   = {"configurable": {"thread_id": "bob_001"}}
# alice 和 bob 的对话历史完全隔离,互不影响

# ── 查看完整消息历史 ────────────────────────────────
for msg in result_2["messages"]:
    role = msg.__class__.__name__.replace("Message", "")
    print(f"[{role}] {msg.content[:80]}")
L5 · MemorySaver 的工作原理

每次节点执行完毕,LangGraph 将当前 State 序列化并用 (thread_id, checkpoint_id) 为 key 存入 MemorySaver(内存字典)。下次 invoke 传入相同 thread_id 时,LangGraph 先加载最新快照作为初始 State,再执行新的节点。这就是为什么第 2 轮能"记得"第 1 轮的内容。

L5 · 为什么第 2 轮 Agent 知道是"北京3天"?

messages 字段由 add_messages Reducer 维护,它会把每轮的 HumanMessage、AIMessage、ToolMessage 全部追加进历史列表。第 2 轮开始时,agent 节点拿到的 state["messages"] 包含第 1 轮所有消息——LLM 看到完整上下文,自然知道目的地是北京。

代码块 5 / 5
部署配置 —— L6
# ── langgraph.json(项目根目录)──────────────────────
# 【L6】LangGraph Studio / Cloud 的部署配置文件
# · "graphs":声明图的名称 → 对应的 Python 模块路径
# · "dependencies":项目依赖,打包时自动安装
# · "env":环境变量文件路径

# langgraph.json
{
  "graphs": {
    "travel_agent": "./travel_agent.py:graph"
    //                    ↑ 文件路径        ↑ 变量名
  },
  "dependencies": ["."],
  "env": ".env"
}

# ── 本地启动 LangGraph Studio ────────────────────────
# 【L6】在项目根目录运行,会自动打开 Studio 界面
# $ langgraph dev
#   → 启动本地 API 服务(默认 http://127.0.0.1:2024)
#   → 自动打开 Studio 可视化界面
#   → 可在 Studio 里直接输入消息测试图的运行

# ── Studio 的调试能力 ────────────────────────────────
# 【L6】每次执行可以看到:
#   · 图结构可视化(节点 + 边,含 ReAct 循环)
#   · 每个节点执行前后的 State 快照对比
#   · 工具调用的输入参数和返回结果
#   · 每条消息的完整内容(AIMessage 含 tool_calls)
#   · 可以在任意步骤"时间旅行"(查看历史快照)

# ── 云端部署(可选)─────────────────────────────────
# $ langgraph build -t my-travel-agent  # 构建 Docker 镜像
# $ langgraph up                        # 启动生产服务
L6 · langgraph.json 的最小配置

langgraph.json 是 Studio 和 Cloud 识别项目的唯一入口。"graphs" 键声明了"图名 → Python 文件中的变量"的映射关系——只要 travel_agent.py 里有一个叫 graph 的已编译图对象,Studio 就能找到并可视化它。langgraph dev 命令会在后台启动 FastAPI 服务并暴露标准 LangGraph API,Studio 通过这个 API 与图交互。

知识点对应关系总览

项目各部分与 6 个子课程的精确映射

项目组成对应课程核心 API解决的问题
TravelState(MessagesState)L1 + L2class S(MessagesState)定义数据契约 + 内置对话消息管理
@tool 工具定义L2 + L3@tool 装饰器自动生成 JSON Schema,供 LLM 理解和调用
llm.bind_tools(tools)L2bind_tools([...])将工具信息注入 LLM,让其知道可以调什么
agent 节点函数L2 + L4llm_with_tools.invoke(messages)读取完整消息历史,LLM 推理决定下一步
ToolNode(tools)L3ToolNode([...])自动解析 tool_calls,执行对应工具,返回结果
tools_condition 条件边L3add_conditional_edges("agent", tools_condition)检测是否有工具调用,路由到 tools 或 END
add_edge("tools", "agent")L4add_edge("tools", "agent")构成 ReAct 循环——工具结果重新送回 LLM 推理
MemorySaver checkpointerL5compile(checkpointer=MemorySaver())每步 State 快照,支持跨轮多步对话记忆
thread_id 配置L5{"configurable": {"thread_id": "x"}}标识会话,相同 ID 恢复历史,不同 ID 隔离
langgraph.json 配置L6{"graphs": {"name": "./file.py:var"}}声明部署入口,Studio / Cloud 识别项目
返回 Module 1 首页