跳到正文
Joeplover
AI Agent·2025-12-28·约 3 分钟阅读

LangGraph 入门:第一个智能代理

理解 LangGraph 状态图、节点编排和 Checkpoint 持久化。

AI 智能体

LangGraph 入门:搭建第一个智能代理

为什么从 ReAct 升级到 LangGraph

LangChain 的 ReAct 循环(Think → Act → Observe)在简单场景下够用,但一旦需要条件分支、循环控制、多角色协作,它的线性结构就显得力不从心。LangGraph 用图结构定义 Agent 执行流程,让复杂 Agent 的设计和调试都清晰很多。

核心概念

StateGraph = 状态 + 节点 + 边

from langgraph.graph import StateGraph, END
from typing import TypedDict, List

# 1. 定义状态
class SearchState(TypedDict):
    query: str
    results: List[str]
    refined: bool

# 2. 创建图
graph = StateGraph(SearchState)

# 3. 添加节点
def search(state: SearchState) -> SearchState:
    results = search_engine(state["query"])
    return {"results": results}

def refine(state: SearchState) -> SearchState:
    better_query = rewrite_query(state["query"])
    return {"query": better_query, "refined": True}

graph.add_node("search", search)
graph.add_node("refine", refine)

# 4. 添加条件边
def check_results(state: SearchState) -> str:
    if not state["results"] and not state["refined"]:
        return "refine"  # 结果为空则优化搜索
    return END  # 有结果则结束

graph.add_conditional_edges("search", check_results)
graph.add_edge("refine", "search")
graph.set_entry_point("search")

# 5. 编译
app = graph.compile()

状态驱动

LangGraph 的核心设计理念:节点读取状态 → 处理 → 更新状态 → 条件边决定下一个节点。状态是整个图的"共享内存",每个节点可以读取和写入。

关键点:

  • 状态类型通过 TypedDict 定义,类型安全
  • 节点函数接收当前状态,返回要更新的字段(不是完整状态)
  • 条件函数返回字符串,匹配边的命名

节点(Node)

节点可以是:

  1. 普通函数:同步处理,适合数据转换、API 调用
  2. Async 函数:异步处理,适合 LLM 调用
  3. Runnable:LangChain 的可运行对象

边(Edge)

  • 普通边:无条件从一个节点到另一个节点
  • 条件边:根据条件函数的返回值决定目标节点
  • 入口边:指定起始节点

首次调试经验

LangGraph 的调试不像普通 Python 函数那样简单——状态在节点间传递,很难直观看到中间结果。解决方法是开启 LangGraph 的 debug 模式:

app = graph.compile(debug=True)

这个模式会在每次节点执行后打印状态变化,对理解执行流程帮助很大。

另一个实用技巧:在节点函数中打印关键状态字段,也就是"手动插桩",简单但有效。

使用场景

LangGraph 适合的典型场景:

  • 多步骤问答:理解问题 → 检索知识 → 生成回答 → 验证回答
  • 条件分支 Agent:根据中间结果决定下一步策略
  • 循环执行:错误重试、迭代优化
  • 人机协作:AI 处理→人工确认→继续执行

总结

LangGraph 把 Agent 从"一个怎么都调不好的提示词"变成了"一个可设计、可调试的图执行引擎"。虽然入门门槛比 ReAct 高一些,但对于生产级的 Agent 应用来说,这个投入是值得的。