使用LangGraph构建智能体:从基础到高级实战

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. 小结与最佳实践

  1. 从简单图开始:先用几个节点跑通流程,再逐步加入工具、条件分支、中断。
  2. 状态设计要清晰:使用 TypedDict 定义你需要的字段,避免无限制膨胀。
  3. 工具描述要准确:工具函数的 docstring 直接影响模型调用正确性,务必写清楚用途和参数格式。
  4. 善用 checkpointer:生产环境推荐使用持久化后端(如 SQLite、Postgres)保存对话历史。
  5. 结合 LangSmith 调试:LangGraph 的每一次运行都可与 LangSmith 集成,可视化决策路径,极大提升调试效率。

现在,你可以尝试用 LangGraph 构建自己的智能体------无论是客服机器人、数据分析助手,还是更复杂的多步推理系统,它都能为你提供清晰、可控的架构。

相关推荐
tqs_123451 小时前
Agent智能体+Skill插件引擎+Milvus混合检索 技术沉淀
java·python·milvus
KaneLogger1 小时前
一套系统,让 AI 写代码的速度变成生产力
人工智能·程序员·代码规范
眼泪划过的星空1 小时前
LangChain 两大基础提示词模板:PromptTemplate 与 ChatPromptTemplate 详解
人工智能·python·langchain
狗都不学爬虫_1 小时前
AI逆向 - 99aq中心滑块验证+登录(wasm纯算)
爬虫·python·网络爬虫
小码哥哥1 小时前
如何评价“构建企业级 AI 知识库“这一趋势?从技术架构到落地实践的完整分析
人工智能·架构
小罗水2 小时前
第18章 接口回归、异常演练与轻量压测
人工智能·数据挖掘·回归
卷福同学2 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
逻辑君2 小时前
ANNA 认知引擎 · Humanoid 机器人训练白皮书
人工智能·深度学习·机器学习·机器人
hans汉斯2 小时前
计算机科学与应用|改进MeanShift算法在智能监控视频中的应用研究
图像处理·人工智能·功能测试·深度学习·算法·音视频
重庆传粉科技2 小时前
AI推荐生态下品牌内容筛选标准重构与GEO优化路径
人工智能