LangGraph 基本用法指南
一、LangGraph 是什么?
LangGraph 是 LangChain 团队推出的 基于图的 AI Agent 编排框架,将工作流建模为有向图(状态图),支持:
- 有条件的分支和循环
- 共享状态在节点间传递
- 内置持久化和检查点
- 可视化调试
- 人机交互中断/恢复
核心理念:用图来描述复杂的 Agent 执行流程。
二、核心概念
1. State(状态)
整个图的共享数据结构,所有节点都可以读取和修改。
python
from typing import TypedDict, Annotated
from operator import add
class AgentState(TypedDict):
messages: Annotated[list, add] # 消息列表,自动追加
current_step: str
result: str
- 使用
TypedDict定义结构 Annotated[list, add]表示该字段用add函数合并(列表追加)
2. Node(节点)
每个节点是一个函数,接收 state 并返回需要更新的状态字段。
python
def researcher(state: AgentState):
# 执行研究任务
return {
"current_step": "analysis",
"result": "研究结果..."
}
节点 不需要 返回完整的 state,只返回要更新的字段即可。
3. Edge(边)
定义节点之间的流转关系:
- 普通边:固定流向下一个节点
- 条件边:根据当前状态动态选择下一个节点
- 入口点:图的起始节点
- 结束点:END,表示流程终止
4. Conditional Edge(条件边)
python
def decide_next_step(state: AgentState):
if state["result"]:
return "analysis"
return "research"
graph.add_conditional_edges("router", decide_next_step)
三、安装
bash
pip install langgraph
四、基本用法示例
示例 1:最简单的图
python
from typing import TypedDict
from langgraph.graph import StateGraph, END
# 1. 定义状态
class State(TypedDict):
value: str
# 2. 定义节点
def node_a(state: State):
print("节点 A 执行")
return {"value": "经过 A 处理"}
def node_b(state: State):
print("节点 B 执行")
return {"value": state["value"] + " → 经过 B 处理"}
# 3. 构建图
graph = StateGraph(State)
graph.add_node("a", node_a)
graph.add_node("b", node_b)
# 4. 定义边
graph.set_entry_point("a") # A 为入口
graph.add_edge("a", "b") # A → B
graph.add_edge("b", END) # B → 结束
# 5. 编译并运行
app = graph.compile()
result = app.invoke({"value": "初始值"})
print(result)
# 输出: {'value': '初始值 → 经过 A 处理 → 经过 B 处理'}
示例 2:条件分支
python
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, END
class State(TypedDict):
input: str
decision: str
result: str
def classifier(state: State):
if "价格" in state["input"]:
return {"decision": "price"}
elif "功能" in state["input"]:
return {"decision": "feature"}
else:
return {"decision": "general"}
def price_handler(state: State):
return {"result": "价格信息已处理"}
def feature_handler(state: State):
return {"result": "功能信息已处理"}
def general_handler(state: State):
return {"result": "通用信息已处理"}
def router(state: State) -> Literal["price", "feature", "general"]:
return state["decision"]
graph = StateGraph(State)
graph.add_node("classifier", classifier)
graph.add_node("price", price_handler)
graph.add_node("feature", feature_handler)
graph.add_node("general", general_handler)
graph.set_entry_point("classifier")
graph.add_conditional_edges("classifier", router)
app = graph.compile()
# 测试
result = app.invoke({"input": "这个产品的价格是多少?", "decision": "", "result": ""})
print(result["result"]) # 价格信息已处理
示例 3:循环执行(带退出条件)
python
from typing import TypedDict
from langgraph.graph import StateGraph, END
class State(TypedDict):
count: int
result: str
def increment(state: State):
count = state["count"] + 1
print(f"第 {count} 次执行")
return {"count": count}
def should_continue(state: State) -> str:
if state["count"] >= 3:
return "end"
return "loop"
graph = StateGraph(State)
graph.add_node("increment", increment)
graph.set_entry_point("increment")
graph.add_conditional_edges(
"increment",
should_continue,
{"loop": "increment", "end": END}
)
app = graph.compile()
result = app.invoke({"count": 0, "result": ""})
print(result) # {'count': 3, 'result': ''}
示例 4:多 Agent 协作
python
from typing import TypedDict
from langgraph.graph import StateGraph, END
class State(TypedDict):
task: str
planner_result: str
writer_result: str
reviewer_result: str
def planner(state: State):
plan = f"计划:分三步完成 - {state['task']}"
return {"planner_result": plan}
def writer(state: State):
draft = f"基于计划撰写草稿:{state['planner_result']}"
return {"writer_result": draft}
def reviewer(state: State):
if "需要修改" in state.get("reviewer_result", ""):
return {"reviewer_result": "通过"}
return {"reviewer_result": "需要修改"}
def should_revise(state: State):
if state.get("reviewer_result") == "需要修改":
return "writer"
return END
graph = StateGraph(State)
graph.add_node("planner", planner)
graph.add_node("writer", writer)
graph.add_node("reviewer", reviewer)
graph.set_entry_point("planner")
graph.add_edge("planner", "writer")
graph.add_edge("writer", "reviewer")
graph.add_conditional_edges("reviewer", should_revise)
app = graph.compile()
result = app.invoke({
"task": "写一篇技术博客",
"planner_result": "",
"writer_result": "",
"reviewer_result": ""
})
五、高级特性
1. 持久化(Checkpointer)
python
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
app = graph.compile(checkpointer=checkpointer)
# 运行时指定线程 ID
config = {"configurable": {"thread_id": "conversation-1"}}
result = app.invoke(input_data, config)
# 可以从检查点恢复
state = app.get_state(config)
2. 人机交互中断(Human-in-the-loop)
python
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
class State(TypedDict):
task: str
status: str
def research(state: State):
return {"status": "研究完成,等待审核"}
def human_review(state: State):
return {"status": "已审核"}
def publish(state: State):
return {"status": "已发布"}
graph = StateGraph(State)
graph.add_node("research", research)
graph.add_node("human_review", human_review)
graph.add_node("publish", publish)
graph.set_entry_point("research")
graph.add_edge("research", "human_review")
graph.add_edge("human_review", "publish")
checkpointer = MemorySaver()
app = graph.compile(checkpointer=checkpointer)
# 第一次运行到 human_review 前自动暂停
config = {"configurable": {"thread_id": "review-1"}}
result = app.invoke({"task": "调研 AI 趋势", "status": ""}, config)
# 查看当前状态
state = app.get_state(config)
print(state.values) # {'task': '调研 AI 趋势', 'status': '研究完成,等待审核'}
# 人工审核后继续执行
app.invoke(None, config) # 继续执行 human_review → publish
3. 流式输出(Streaming)
python
# 流式获取每个节点的输出
for event in app.stream(input_data):
for node_name, output in event.items():
print(f"节点 {node_name}: {output}")
4. 图可视化
python
# 生成 Mermaid 图
print(app.get_graph().draw_mermaid())
# 或者用 Pillow 生成图片
from IPython.display import Image
Image(app.get_graph().draw_mermaid_png())
六、与 LangChain 集成示例
python
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langgraph.graph import StateGraph, END
from typing import TypedDict
class State(TypedDict):
topic: str
outline: str
article: str
llm = ChatOpenAI(model="gpt-4")
def create_outline(state: State):
prompt = ChatPromptTemplate.from_template("为以下主题写一个大纲:{topic}")
chain = prompt | llm | StrOutputParser()
outline = chain.invoke({"topic": state["topic"]})
return {"outline": outline}
def write_article(state: State):
prompt = ChatPromptTemplate.from_template("根据大纲写一篇文章:\n{outline}")
chain = prompt | llm | StrOutputParser()
article = chain.invoke({"outline": state["outline"]})
return {"article": article}
graph = StateGraph(State)
graph.add_node("outline", create_outline)
graph.add_node("write", write_article)
graph.set_entry_point("outline")
graph.add_edge("outline", "write")
graph.add_edge("write", END)
app = graph.compile()
result = app.invoke({"topic": "LangGraph 入门", "outline": "", "article": ""})
print(result["article"])
七、API 一览
| 方法 | 说明 |
|---|---|
StateGraph(State) |
创建状态图 |
graph.add_node(name, func) |
添加节点 |
graph.set_entry_point(name) |
设置入口节点 |
graph.add_edge(src, dst) |
添加固定边 |
graph.add_conditional_edges(src, func, mapping) |
添加条件边 |
graph.compile() |
编译为可执行应用 |
app.invoke(input) |
同步执行 |
app.astream(input) |
异步流式执行 |
app.get_state(config) |
获取当前状态 |
app.update_state(config, values) |
手动更新状态 |
八、总结
LangGraph 的核心价值在于把 LLM 工作流 从线性链升级为 有向图,提供了:
- 灵活的控制流:条件分支、循环、并行
- 可靠的状态管理:共享 State + 持久化检查点
- 生产级特性:人机交互、时间旅行、流式输出
- 与 LangChain 无缝集成:复用其丰富的组件生态
适用场景:多 Agent 系统、复杂 RAG 流程、需要循环的工作流、人机协作系统。