1. 什么是 LangGraph 智能体
LangGraph 是 LangChain 生态中专门用于构建有状态、多步骤 智能体(Agent)的框架。与传统"一次调用大模型就了事"不同,LangGraph 将智能体的决策流程建模为图(Graph),允许你定义节点、分支、循环,实现复杂的思考与工具调用逻辑。
核心思想:把智能体的决策过程看作有向图------每一个节点代表一次状态更新(例如调用工具、思考、输出最终答案),边代表状态转移条件。这让你既能利用 LLM 的推理能力,又能精确控制流程,非常适合需要多次工具调用、多轮推理、甚至人工中断的场景。
2. 为什么选择 LangGraph
| 优势 | 说明 |
|---|---|
| 显式流程控制 | 用代码定义决策路径,而不是完全依赖 prompt 引导,避免"自由探索"导致的不稳定 |
| 支持循环与条件分支 | 轻松实现 ReAct、Self-Reflection 等需要多次迭代的模式 |
| 内置状态管理 | 每一步都维护完整状态,方便回溯、调试与日志记录 |
| 与 LangChain 无缝集成 | 可直接使用 LangChain 的工具、模型、记忆组件 |
| 支持人工介入 | 可插入中断点(interrupt),实现"思考→人工审核→继续"的协作模式 |
3. 环境准备
bash
pip install langgraph langchain-openai
我们使用 OpenAI 兼容接口(这里以通义千问为例,你也可以替换为任何 LangChain 支持的模型)。
python
import os
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="qwen-max",
openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
openai_api_key=os.getenv("DASHSCOPE_API_KEY"),
)
4. 最简单的智能体:三节点图
先从一个极度简化的例子入手:一个图包含三个节点------start(接收用户输入)、think(让模型思考)、answer(返回最终答案)。虽然没有工具调用,但它能帮助你快速理解 LangGraph 的基本结构。
python
from typing import TypedDict, Annotated
import operator
from langgraph.graph import StateGraph, END
# 定义状态(state)
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
final_answer: str
# 节点1:接收用户输入(实际上不做修改)
def start_node(state: AgentState):
return state
# 节点2:调用大模型
def think_node(state: AgentState):
response = model.invoke(state["messages"])
# 将模型的回复添加到消息列表
return {"messages": [response], "final_answer": response.content}
# 节点3:返回最终答案
def answer_node(state: AgentState):
return {"final_answer": state["final_answer"]}
# 构建图
builder = StateGraph(AgentState)
builder.add_node("start", start_node)
builder.add_node("think", think_node)
builder.add_node("answer", answer_node)
builder.set_entry_point("start")
builder.add_edge("start", "think")
builder.add_edge("think", "answer")
builder.add_edge("answer", END)
graph = builder.compile()
# 运行
result = graph.invoke({"messages": [("user", "什么是 LangGraph?")]})
print(result["final_answer"])
5. 引入工具调用:ReAct 智能体
真正的智能体需要能调用工具(搜索、计算器、数据库查询等)。下面实现一个经典的 ReAct 智能体:让模型决定是调用工具还是给出最终答案。为此我们需要:
- 定义工具列表
- 将工具绑定到模型
- 添加条件边,根据模型返回判断下一步
python
from langchain_core.tools import tool
from langgraph.prebuilt import ToolNode
from langgraph.graph import MessagesState, StateGraph, START, END
# 定义工具
@tool
def get_weather(city: str) -> str:
"""获取指定城市的实时天气(模拟)"""
# 实际项目中替换为真实 API 调用
return f"{city} 当前晴朗,26°C"
@tool
def multiply(a: float, b: float) -> float:
"""计算两数乘积"""
return a * b
tools = [get_weather, multiply]
tool_node = ToolNode(tools)
# 绑定工具到模型
model_with_tools = model.bind_tools(tools)
# 定义调用模型的节点
def call_model(state: MessagesState):
messages = state["messages"]
response = model_with_tools.invoke(messages)
return {"messages": [response]}
# 条件判断函数:如果有工具调用,则走向 tools 节点,否则结束
def should_continue(state: MessagesState):
messages = state["messages"]
last_message = messages[-1]
if last_message.tool_calls:
return "tools"
return END
# 构建图
workflow = StateGraph(MessagesState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
workflow.add_edge(START, "agent")
workflow.add_conditional_edges("agent", should_continue, ["tools", END])
workflow.add_edge("tools", "agent")
app = workflow.compile()
# 运行
input_message = [("user", "北京天气怎么样?")]
for chunk in app.stream({"messages": input_message}, stream_mode="values"):
chunk["messages"][-1].pretty_print()
执行后,智能体会先调用 get_weather 工具,获取结果后再次调用模型整合信息,最终输出友好的回答。
6. 高级特性:中断与人工审核
LangGraph 支持在关键节点插入中断点(interrupt),让流程暂时停止,等待外部输入(如人类确认)。这对高风险的决策场景非常有用。
python
from langgraph.checkpoint.memory import MemorySaver
# 在编译时传入 checkpointer 并启用 interrupt_before
memory = MemorySaver()
app_with_interrupt = workflow.compile(
checkpointer=memory,
interrupt_before=["tools"] # 在调用工具前暂停
)
config = {"configurable": {"thread_id": "1"}}
# 首次运行,触发中断
events = app_with_interrupt.stream(
{"messages": [("user", "请先用工具告诉我北京天气,再计算 5*7")]},
config,
stream_mode="values"
)
for event in events:
if "messages" in event:
event["messages"][-1].pretty_print()
此时流程会停在 tools 节点之前,你可以执行 app_with_interrupt.get_state(config) 查看当前状态,决定继续执行或修改后放行。
python
# 人工确认后继续
app_with_interrupt.invoke(None, config)
7. 记忆与多轮对话
为了让智能体记住之前的对话历史,LangGraph 利用 checkpoint 机制保存每次交互的状态。你只需为每次对话指定一个唯一的 thread_id,所有消息和状态就会被自动持久化。
python
config = {"configurable": {"thread_id": "user-123"}}
app.invoke({"messages": [("user", "我叫小明")]}, config)
app.invoke({"messages": [("user", "我叫什么名字?")]}, config)
# 模型会基于之前的记忆回答
因为状态中保存了完整消息历史,而且 operator.add 会自动追加消息,所以智能体自然地拥有了多轮对话能力。
8. 小结与最佳实践
- 从简单图开始:先用几个节点跑通流程,再逐步加入工具、条件分支、中断。
- 状态设计要清晰:使用 TypedDict 定义你需要的字段,避免无限制膨胀。
- 工具描述要准确:工具函数的 docstring 直接影响模型调用正确性,务必写清楚用途和参数格式。
- 善用 checkpointer:生产环境推荐使用持久化后端(如 SQLite、Postgres)保存对话历史。
- 结合 LangSmith 调试:LangGraph 的每一次运行都可与 LangSmith 集成,可视化决策路径,极大提升调试效率。
现在,你可以尝试用 LangGraph 构建自己的智能体------无论是客服机器人、数据分析助手,还是更复杂的多步推理系统,它都能为你提供清晰、可控的架构。