文章目录
- LangGraph技术详细解析:图结构智能体框架核心特性
-
- 前言
- [一、LangGraph 核心优势](#一、LangGraph 核心优势)
- [二、LangGraph 生产级目录结构](#二、LangGraph 生产级目录结构)
- [三、LangGraph 核心概念与快速入门](#三、LangGraph 核心概念与快速入门)
- [四、LangGraph 关键特性深度解析(含代码示例)](#四、LangGraph 关键特性深度解析(含代码示例))
-
- [1. 循环执行:支持任务迭代优化](#1. 循环执行:支持任务迭代优化)
- [2. 分支决策:基于状态动态选择流程](#2. 分支决策:基于状态动态选择流程)
- [3. 工具调用:集成外部系统能力](#3. 工具调用:集成外部系统能力)
- [4. 多智能体协作:节点间交互完成复杂任务](#4. 多智能体协作:节点间交互完成复杂任务)
- 五、生产级实践:关键功能集成
-
- [1. 状态持久化(支持任务中断恢复)](#1. 状态持久化(支持任务中断恢复))
-
- [代码示例:Redis 状态持久化](#代码示例:Redis 状态持久化)
- [2. 错误处理与重试](#2. 错误处理与重试)
- [3. 图结构可视化](#3. 图结构可视化)
-
- 代码示例:可视化图结构
- [生成的 Mermaid 代码(示例)](#生成的 Mermaid 代码(示例))
- [4. 部署方案(FastAPI + LangGraph)](#4. 部署方案(FastAPI + LangGraph))
-
- [代码示例:FastAPI 部署](#代码示例:FastAPI 部署)
- [六、框架对比:LangGraph vs 传统线性 LLM 应用 vs LangChain Agents](#六、框架对比:LangGraph vs 传统线性 LLM 应用 vs LangChain Agents)
- 七、总结
LangGraph技术详细解析:图结构智能体框架核心特性
前言
若对您有帮助的话,请点赞收藏加关注哦,您的关注是我持续创作的动力!有问题请私信或联系邮箱:funian.gm@gmail.com
在大语言模型(LLM)应用开发中,简单的"输入-输出"线性流程已无法满足复杂场景需求------比如多步骤数据分析、跨系统协作、需要循环迭代的任务(如报告优化)、分支决策的业务流程(如客服工单分配)。LangGraph 作为 LangChain 生态下的图结构智能体框架,通过"节点-边-状态"的图模型,完美解决了线性流程的局限性,支持循环执行、分支路由、状态持久化、多智能体协作等核心能力,成为构建复杂 LLM 应用的首选工具。

一、LangGraph 核心优势
LangGraph 基于 LangChain 构建,专注于"复杂流程建模",其核心优势围绕"图结构"展开,精准解决线性 LLM 应用的痛点:
| 核心优势 | 具体说明 |
|---|---|
| 图结构流程建模 | 用"节点(任务)+ 边(流转规则)"描述复杂流程,支持循环、分支、并行等任意拓扑结构 |
| 内置状态管理 | 统一维护全局状态(任务上下文、中间结果、历史交互),无需手动传递数据 |
| 循环与迭代支持 | 支持任务重复执行(如答案优化、数据校验),突破线性流程的单次执行限制 |
| 分支决策能力 | 基于状态动态选择执行路径(如"是否需要调用工具""是否需要人工审核") |
| 多智能体协作 | 支持多个智能体作为节点交互(如"分析智能体→写作智能体→审核智能体") |
| LangChain 生态兼容 | 无缝集成 LangChain 的 LLM 模型、工具、向量库、记忆组件,降低开发成本 |
| 可视化与调试 | 内置图结构可视化工具,支持流程轨迹追踪,便于复杂流程调试 |
| 状态持久化 | 支持将全局状态存储到外部数据库(如 Redis、PostgreSQL),支持任务中断恢复 |
二、LangGraph 生产级目录结构
LangGraph 没有强制目录规范,但生产级项目需遵循"模块化、高内聚低耦合"原则,结合 LangChain 生态特点,以下是经过实践验证的标准目录结构(适用于中大型智能体应用):
langgraph-project/
├── .env # 环境变量(LLM API密钥、数据库地址等,不提交Git)
├── .env.example # 环境变量示例(提交Git,指导部署)
├── .gitignore # Git忽略文件
├── requirements.txt # 项目依赖
├── main.py # 项目入口(FastAPI部署、图实例初始化)
├── src/ # 核心源代码目录
│ ├── api/ # 接口层(FastAPI路由,对外提供服务)
│ │ ├── endpoints/ # 接口端点(如智能体调用、任务查询)
│ │ │ └── agent.py
│ │ └── router.py # 路由汇总
│ ├── graphs/ # 图结构定义(核心目录)
│ │ ├── base_graph.py # 基础图类(封装通用逻辑,如持久化、可视化)
│ │ ├── data_analysis_graph.py # 数据分析智能体图
│ │ └── customer_service_graph.py # 客服智能体图
│ ├── agents/ # 智能体节点(图中的核心执行单元)
│ │ ├── analyzer_agent.py # 分析智能体(数据处理、逻辑推理)
│ │ ├── writer_agent.py # 写作智能体(结果生成、格式优化)
│ │ └── reviewer_agent.py # 审核智能体(结果校验、风险控制)
│ ├── tools/ # 工具定义(智能体可调用的外部工具)
│ │ ├── base_tool.py # 基础工具类(统一工具调用接口)
│ │ ├── database_tool.py # 数据库查询工具
│ │ └── file_tool.py # 文件读写工具
│ ├── schemas/ # 数据模型(Pydantic,状态、请求/响应校验)
│ │ ├── state.py # 图全局状态模型
│ │ └── request.py # 接口请求/响应模型
│ ├── core/ # 核心配置(全局常量、LLM初始化、持久化配置)
│ │ ├── config.py # 配置加载(从.env读取)
│ │ ├── llm.py # LLM模型初始化(OpenAI/本地化模型)
│ │ └── storage.py # 状态持久化(Redis/PostgreSQL)
│ └── utils/ # 工具函数(日志、异常处理、格式转换)
│ ├── logger.py # 日志配置
│ └── exceptions.py # 自定义异常
└── tests/ # 单元测试与集成测试
├── test_graph_flow.py # 图流程测试
└── test_agent_tool.py # 智能体工具调用测试
核心目录说明(表格汇总)
| 目录/文件 | 核心作用 | 关键注意点 |
|---|---|---|
src/graphs |
图结构定义(节点、边、状态流转规则) | 每个业务场景对应一个独立图文件,复用基础图逻辑 |
src/agents |
智能体节点(图的执行单元,封装LLM+业务逻辑) | 单个智能体专注单一职责(如仅负责分析/写作) |
src/tools |
外部工具封装(数据库、文件、API等) | 遵循LangChain Tool接口规范,便于智能体调用 |
src/schemas/state.py |
全局状态模型(图的核心数据载体) | 用Pydantic定义,明确状态字段(如input、output、history) |
src/core/storage |
状态持久化(支持任务中断恢复) | 生产环境推荐Redis(高性能)或PostgreSQL(结构化存储) |
src/api |
对外提供HTTP接口(如FastAPI) | 封装图的运行逻辑,提供同步/异步调用接口 |
目录设计原则
- 单一职责:每个智能体/工具/图仅负责特定功能(如分析智能体不负责写作);
- 可复用性:基础图类、工具基类封装通用逻辑,避免重复代码;
- 可扩展性:支持新增智能体节点、工具、图结构,不影响现有功能;
- 可调试性:日志、状态追踪、图可视化能力贯穿整个目录设计。
三、LangGraph 核心概念与快速入门
核心概念拆解
LangGraph 的核心是"图(Graph)",由三个基础组件构成:
| 组件 | 作用说明 |
|---|---|
| 节点(Node) | 执行单元(智能体、工具调用、数据处理函数),输入状态,输出新状态 |
| 边(Edge) | 节点间的流转规则(条件分支、固定流转、循环流转),决定"下一步执行哪个节点" |
| 状态(State) | 全局数据载体(Pydantic模型),存储任务上下文、中间结果、历史记录,所有节点共享 |
快速入门:最小化图示例(问答+记忆功能)
以下示例实现一个"接收问题→LLM回答→存储历史"的简单图,覆盖核心流程:
步骤1:安装依赖
bash
pip install langgraph langchain openai pydantic python-dotenv # 核心依赖
pip install fastapi uvicorn # 可选,用于接口部署
步骤2:定义全局状态(src/schemas/state.py)
python
from pydantic import BaseModel
from typing import List, Optional
# 全局状态模型:所有节点共享和修改该状态
class QAMemoryState(BaseModel):
question: Optional[str] = None # 用户问题
answer: Optional[str] = None # LLM回答
history: List[tuple] = [] # 对话历史((question, answer))
步骤3:定义节点函数(src/agents/qa_agent.py)
python
from langchain_openai import ChatOpenAI
from src.schemas.state import QAMemoryState
from src.core.config import settings
# 初始化LLM(从环境变量读取API密钥)
llm = ChatOpenAI(
model="gpt-3.5-turbo",
api_key=settings.OPENAI_API_KEY,
temperature=0.7
)
# 节点1:LLM回答问题
def answer_node(state: QAMemoryState) -> QAMemoryState:
"""接收问题,生成回答,更新状态"""
# 构建提示词(包含历史对话)
history_str = "\n".join([f"Q: {q}\nA: {a}" for q, a in state.history])
prompt = f"""
你是一个问答助手,基于历史对话和当前问题生成回答:
历史对话:{history_str}
当前问题:{state.question}
"""
# 调用LLM
response = llm.invoke(prompt)
# 更新状态
return QAMemoryState(
question=state.question,
answer=response.content,
history=state.history + [(state.question, response.content)] # 追加历史
)
# 节点2:结束节点(无实际逻辑,标记流程结束)
def end_node(state: QAMemoryState) -> QAMemoryState:
"""流程结束节点"""
print(f"流程结束,最终回答:{state.answer}")
return state
步骤4:构建图结构(src/graphs/qa_graph.py)
python
from langgraph.graph import Graph, END
from src.schemas.state import QAMemoryState
from src.agents.qa_agent import answer_node, end_node
# 1. 初始化图(指定状态模型)
qa_graph = Graph(QAMemoryState)
# 2. 添加节点(节点名称→节点函数)
qa_graph.add_node("answer", answer_node) # 回答节点
qa_graph.add_node("end", end_node) # 结束节点
# 3. 定义边(流转规则)
qa_graph.add_edge("answer", "end") # 回答节点执行后,直接进入结束节点
qa_graph.set_entry_point("answer") # 设置入口节点(流程开始于answer节点)
# 4. 编译图(生成可运行的图实例)
qa_graph_compiled = qa_graph.compile()
# 5. 可视化图(生成Mermaid语法,可在https://mermaid-js.github.io/渲染)
def visualize_graph():
return qa_graph_compiled.get_graph().draw_mermaid()
步骤5:运行图(测试流程)
python
# main.py 测试代码
from src.graphs.qa_graph import qa_graph_compiled
from src.schemas.state import QAMemoryState
if __name__ == "__main__":
# 输入初始状态
initial_state = QAMemoryState(question="什么是LangGraph?")
# 运行图(同步执行)
result = qa_graph_compiled.invoke(initial_state)
# 输出结果
print(f"用户问题:{result.question}")
print(f"LLM回答:{result.answer}")
print(f"对话历史:{result.history}")
运行结果
用户问题:什么是LangGraph?
LLM回答:LangGraph是LangChain生态下的图结构智能体框架,用于构建复杂的LLM应用...
对话历史:[('什么是LangGraph?', 'LangGraph是LangChain生态下的图结构智能体框架...')]
流程结束,最终回答:LangGraph是LangChain生态下的图结构智能体框架...
四、LangGraph 关键特性深度解析(含代码示例)
1. 循环执行:支持任务迭代优化
核心场景:需要反复优化结果(如报告修改、答案精炼)、重复校验数据(如数据准确性校验)。
代码示例:循环优化回答
python
from langgraph.graph import Graph, END
from src.schemas.state import QAMemoryState
from src.agents.qa_agent import llm
# 新增节点:判断是否需要继续优化
def should_optimize(state: QAMemoryState) -> str:
"""根据当前回答判断是否继续优化(返回下一个节点名称)"""
prompt = f"""
请判断以下回答是否满足要求(准确、详细、逻辑清晰):
回答:{state.answer}
要求:1. 解释清楚核心概念;2. 给出应用场景;3. 说明优势。
若满足要求,返回"end";否则返回"optimize"。
"""
response = llm.invoke(prompt)
return response.content.strip().lower()
# 新增节点:优化回答
def optimize_node(state: QAMemoryState) -> QAMemoryState:
"""优化现有回答"""
prompt = f"""
请优化以下回答,满足要求:1. 解释清楚核心概念;2. 给出应用场景;3. 说明优势。
原始回答:{state.answer}
优化后回答:
"""
optimized_answer = llm.invoke(prompt).content
# 更新状态(保留历史,替换当前回答)
return QAMemoryState(
question=state.question,
answer=optimized_answer,
history=state.history[:-1] + [(state.question, optimized_answer)] # 替换最后一条历史
)
# 构建带循环的图
optimize_graph = Graph(QAMemoryState)
optimize_graph.add_node("answer", answer_node) # 初始回答
optimize_graph.add_node("optimize", optimize_node) # 优化节点
optimize_graph.add_node("should_optimize", should_optimize) # 决策节点
optimize_graph.add_node("end", end_node) # 结束节点
# 定义边(核心:根据决策结果流转)
optimize_graph.add_edge("answer", "should_optimize") # 初始回答后进入决策
optimize_graph.add_conditional_edges(
"should_optimize", # 决策节点
lambda x: x # 决策函数的输出直接作为下一个节点名称
)
optimize_graph.add_edge("optimize", "should_optimize") # 优化后再次进入决策
optimize_graph.add_edge("should_optimize", "end") # 满足要求则结束
# 入口节点
optimize_graph.set_entry_point("answer")
optimize_graph_compiled = optimize_graph.compile()
# 运行图
initial_state = QAMemoryState(question="什么是LangGraph?")
result = optimize_graph_compiled.invoke(initial_state)
核心亮点
- 用
add_conditional_edges实现"决策-流转"逻辑; - 循环次数可通过
max_steps限制(避免无限循环):optimize_graph_compiled.invoke(initial_state, config={"max_steps": 3})。
2. 分支决策:基于状态动态选择流程
核心场景:根据任务类型分配不同智能体(如"技术问题→技术客服""订单问题→售后客服")、根据输入条件选择是否调用工具(如"是否需要查询数据库")。
代码示例:客服工单分支路由
python
from langgraph.graph import Graph, END
from pydantic import BaseModel
from typing import Optional
# 定义客服场景状态
class SupportTicketState(BaseModel):
ticket_content: str # 工单内容
ticket_type: Optional[str] = None # 工单类型(技术问题/订单问题/其他)
reply: Optional[str] = None # 客服回复
# 节点1:分类工单类型
def classify_ticket(state: SupportTicketState) -> SupportTicketState:
"""判断工单类型"""
prompt = f"请将以下工单分类为:技术问题、订单问题、其他。工单内容:{state.ticket_content}"
ticket_type = llm.invoke(prompt).content.strip()
return SupportTicketState(
ticket_content=state.ticket_content,
ticket_type=ticket_type,
reply=state.reply
)
# 节点2:技术客服回复
def tech_support_node(state: SupportTicketState) -> SupportTicketState:
"""技术问题回复"""
prompt = f"作为技术客服,回复以下工单:{state.ticket_content}"
reply = llm.invoke(prompt).content
return SupportTicketState(**state.dict(), reply=reply)
# 节点3:售后客服回复
def order_support_node(state: SupportTicketState) -> SupportTicketState:
"""订单问题回复"""
prompt = f"作为售后客服,回复以下工单:{state.ticket_content}"
reply = llm.invoke(prompt).content
return SupportTicketState(**state.dict(), reply=reply)
# 节点4:通用客服回复
def general_support_node(state: SupportTicketState) -> SupportTicketState:
"""其他问题回复"""
prompt = f"作为通用客服,回复以下工单:{state.ticket_content}"
reply = llm.invoke(prompt).content
return SupportTicketState(**state.dict(), reply=reply)
# 构建分支图
support_graph = Graph(SupportTicketState)
support_graph.add_node("classify", classify_ticket)
support_graph.add_node("tech_support", tech_support_node)
support_graph.add_node("order_support", order_support_node)
support_graph.add_node("general_support", general_support_node)
support_graph.add_node("end", end_node)
# 定义边:分类后根据类型跳转不同客服节点
support_graph.add_edge("classify", "tech_support", cond=lambda x: x.ticket_type == "技术问题")
support_graph.add_edge("classify", "order_support", cond=lambda x: x.ticket_type == "订单问题")
support_graph.add_edge("classify", "general_support", cond=lambda x: x.ticket_type == "其他")
# 所有客服节点执行后进入结束节点
support_graph.add_edge("tech_support", "end")
support_graph.add_edge("order_support", "end")
support_graph.add_edge("general_support", "end")
# 入口节点
support_graph.set_entry_point("classify")
support_graph_compiled = support_graph.compile()
# 运行图
initial_state = SupportTicketState(ticket_content="我的订单支付成功但没收到货,怎么处理?")
result = support_graph_compiled.invoke(initial_state)
print(f"工单类型:{result.ticket_type}")
print(f"客服回复:{result.reply}")
3. 工具调用:集成外部系统能力
核心场景:智能体需要查询数据库、调用API、读写文件等外部操作(LangGraph 无缝集成 LangChain 工具)。
代码示例:智能体调用数据库工具
python
from langchain.tools import tool
from langgraph.graph import Graph, END
from src.schemas.state import DataQueryState
from src.core.config import settings
# 1. 定义LangChain工具(数据库查询)
@tool
def query_database(sql: str) -> str:
"""
调用数据库执行SQL查询,仅用于查询数据(SELECT语句)
参数:sql - 合法的SQL SELECT语句
"""
# 模拟数据库查询(实际项目用SQLAlchemy/数据库驱动)
import sqlite3
conn = sqlite3.connect(settings.DB_PATH)
cursor = conn.cursor()
try:
cursor.execute(sql)
results = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
return f"查询结果:{columns}\n{results}"
except Exception as e:
return f"查询失败:{str(e)}"
finally:
conn.close()
# 2. 定义状态模型
class DataQueryState(BaseModel):
user_query: str # 用户自然语言查询
sql: Optional[str] = None # 生成的SQL语句
query_result: Optional[str] = None # 数据库查询结果
final_answer: Optional[str] = None # 最终自然语言回答
# 3. 节点1:自然语言转SQL
def nl2sql_node(state: DataQueryState) -> DataQueryState:
"""将用户自然语言查询转换为SQL"""
prompt = f"""
数据库表结构:users(id INT, name TEXT, email TEXT, register_time DATETIME)
请将以下自然语言查询转换为SQL SELECT语句,仅返回SQL,不包含其他内容:
用户查询:{state.user_query}
"""
sql = llm.invoke(prompt).content.strip()
return DataQueryState(**state.dict(), sql=sql)
# 4. 节点2:调用数据库工具
def tool_call_node(state: DataQueryState) -> DataQueryState:
"""调用数据库工具执行SQL"""
if not state.sql:
return DataQueryState(**state.dict(), query_result="SQL生成失败")
# 调用LangChain工具
query_result = query_database.invoke({"sql": state.sql})
return DataQueryState(**state.dict(), query_result=query_result)
# 5. 节点3:生成最终回答
def answer_generation_node(state: DataQueryState) -> DataQueryState:
"""根据查询结果生成自然语言回答"""
prompt = f"""
用户查询:{state.user_query}
数据库查询结果:{state.query_result}
请将查询结果转换为自然语言回答,简洁明了:
"""
final_answer = llm.invoke(prompt).content
return DataQueryState(**state.dict(), final_answer=final_answer)
# 6. 构建图
data_query_graph = Graph(DataQueryState)
data_query_graph.add_node("nl2sql", nl2sql_node)
data_query_graph.add_node("tool_call", tool_call_node)
data_query_graph.add_node("answer_generation", answer_generation_node)
data_query_graph.add_node("end", end_node)
# 定义边
data_query_graph.add_edge("nl2sql", "tool_call")
data_query_graph.add_edge("tool_call", "answer_generation")
data_query_graph.add_edge("answer_generation", "end")
data_query_graph.set_entry_point("nl2sql")
data_query_graph_compiled = data_query_graph.compile()
# 运行图
initial_state = DataQueryState(user_query="查询2024年注册的用户数量")
result = data_query_graph_compiled.invoke(initial_state)
print(f"生成SQL:{result.sql}")
print(f"查询结果:{result.query_result}")
print(f"最终回答:{result.final_answer}")
4. 多智能体协作:节点间交互完成复杂任务
核心场景:需要多个智能体分工协作(如"数据分析→报告写作→合规审核""产品经理→开发→测试")。
代码示例:多智能体报告生成流程
python
from langgraph.graph import Graph, END
from src.schemas.state import ReportState
# 状态模型
class ReportState(BaseModel):
topic: str # 报告主题
data_analysis: Optional[str] = None # 数据分析结果
draft_report: Optional[str] = None # 报告草稿
reviewed_report: Optional[str] = None # 审核后报告
# 节点1:数据分析智能体
def data_analyst_node(state: ReportState) -> ReportState:
"""分析报告主题相关数据"""
prompt = f"作为数据分析师,分析以下主题的核心数据和趋势:{state.topic},输出分析结果(300字内)"
data_analysis = llm.invoke(prompt).content
return ReportState(**state.dict(), data_analysis=data_analysis)
# 节点2:写作智能体
def writer_node(state: ReportState) -> ReportState:
"""基于数据分析结果生成报告草稿"""
prompt = f"基于以下数据分析结果,生成一份结构化报告(包含标题、核心发现、趋势预测):{state.data_analysis}"
draft_report = llm.invoke(prompt).content
return ReportState(**state.dict(), draft_report=draft_report)
# 节点3:审核智能体
def reviewer_node(state: ReportState) -> ReportState:
"""审核报告的合规性和准确性"""
prompt = f"作为合规审核员,审核以下报告是否存在虚假信息、违规内容,若有问题请修正:{state.draft_report}"
reviewed_report = llm.invoke(prompt).content
return ReportState(**state.dict(), reviewed_report=reviewed_report)
# 构建多智能体协作图
report_graph = Graph(ReportState)
report_graph.add_node("data_analyst", data_analyst_node)
report_graph.add_node("writer", writer_node)
report_graph.add_node("reviewer", reviewer_node)
report_graph.add_node("end", end_node)
# 定义流转顺序:分析→写作→审核→结束
report_graph.add_edge("data_analyst", "writer")
report_graph.add_edge("writer", "reviewer")
report_graph.add_edge("reviewer", "end")
report_graph.set_entry_point("data_analyst")
report_graph_compiled = report_graph.compile()
# 运行图
initial_state = ReportState(topic="2024年AI行业发展趋势")
result = report_graph_compiled.invoke(initial_state)
print(f"最终报告:{result.reviewed_report}")
五、生产级实践:关键功能集成
1. 状态持久化(支持任务中断恢复)
生产环境中,任务可能因网络异常、服务重启中断,LangGraph 支持将状态存储到外部数据库,实现中断恢复。
代码示例:Redis 状态持久化
python
# src/core/storage.py
from langgraph.checkpoint.redis import RedisSaver
from src.core.config import settings
# 初始化Redis持久化器
def init_redis_checkpointer() -> RedisSaver:
return RedisSaver(
redis_url=settings.REDIS_URL, # 从.env读取:redis://:password@localhost:6379/0
namespace="langgraph:checkpoints" # 命名空间,避免key冲突
)
# src/graphs/base_graph.py
from langgraph.graph import Graph
from src.core.storage import init_redis_checkpointer
# 基础图类(封装持久化能力)
class PersistentGraph(Graph):
def __init__(self, state_schema, use_checkpoint=True):
super().__init__(state_schema)
self.checkpointer = init_redis_checkpointer() if use_checkpoint else None
def compile(self):
"""编译图时启用持久化"""
return super().compile(checkpointer=self.checkpointer)
# 使用基础图类构建带持久化的图
report_graph = PersistentGraph(ReportState)
# ... 添加节点和边 ...
report_graph_compiled = report_graph.compile()
# 运行图时指定任务ID(用于恢复)
task_id = "report-2024-ai-trend" # 自定义任务ID
initial_state = ReportState(topic="2024年AI行业发展趋势")
# 首次运行(创建任务)
result = report_graph_compiled.invoke(initial_state, config={"configurable": {"thread_id": task_id}})
# 中断后恢复(根据task_id加载状态)
restored_result = report_graph_compiled.invoke(None, config={"configurable": {"thread_id": task_id}})
2. 错误处理与重试
节点执行失败(如LLM调用超时、工具调用异常)时,需支持重试、降级处理。
代码示例:节点错误重试
python
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from langgraph.graph import Graph
import requests.exceptions
# 带重试的LLM节点
@retry(
stop=stop_after_attempt(3), # 最多重试3次
wait=wait_exponential(multiplier=1, min=2, max=10), # 指数退避(2s→4s→8s)
retry=retry_if_exception_type((requests.exceptions.RequestException, TimeoutError)) # 仅重试网络异常
)
def answer_node_with_retry(state: QAMemoryState) -> QAMemoryState:
try:
response = llm.invoke(f"回答问题:{state.question}")
return QAMemoryState(
question=state.question,
answer=response.content,
history=state.history + [(state.question, response.content)]
)
except Exception as e:
print(f"节点执行失败:{str(e)},将重试...")
raise # 抛出异常触发重试
# 构建图时使用带重试的节点
qa_graph = Graph(QAMemoryState)
qa_graph.add_node("answer", answer_node_with_retry)
qa_graph.add_node("end", end_node)
qa_graph.add_edge("answer", "end")
qa_graph.set_entry_point("answer")
3. 图结构可视化
LangGraph 支持生成 Mermaid 语法的图结构,可在 Mermaid 在线编辑器 渲染,便于调试和文档编写。
代码示例:可视化图结构
python
# src/graphs/qa_graph.py
def visualize_graph(graph_compiled) -> str:
"""生成Mermaid语法的图结构"""
return graph_compiled.get_graph().draw_mermaid()
# 运行后输出Mermaid代码
if __name__ == "__main__":
mermaid_code = visualize_graph(qa_graph_compiled)
print("Mermaid图结构:")
print(mermaid_code)
生成的 Mermaid 代码(示例)
answer end A
4. 部署方案(FastAPI + LangGraph)
将 LangGraph 包装为 HTTP 接口,支持外部系统调用。
代码示例:FastAPI 部署
python
# src/api/endpoints/agent.py
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from src.graphs.report_graph import report_graph_compiled
from src.schemas.state import ReportState
router = APIRouter(prefix="/agent", tags=["智能体接口"])
# 请求模型
class ReportRequest(BaseModel):
topic: str
task_id: Optional[str] = None
# 响应模型
class ReportResponse(BaseModel):
task_id: str
report: str
status: str = "success"
@router.post("/generate-report", response_model=ReportResponse)
async def generate_report(request: ReportRequest):
try:
# 生成任务ID(若未提供)
task_id = request.task_id or f"report-{uuid.uuid4()}"
# 初始化状态
initial_state = ReportState(topic=request.topic)
# 运行图
result = report_graph_compiled.invoke(
initial_state,
config={"configurable": {"thread_id": task_id}}
)
# 返回结果
return ReportResponse(
task_id=task_id,
report=result.reviewed_report
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"报告生成失败:{str(e)}")
# src/api/router.py
from fastapi import APIRouter
from src.api.endpoints import agent
api_router = APIRouter()
api_router.include_router(agent.router)
# main.py
from fastapi import FastAPI
from src.api.router import api_router
app = FastAPI(title="LangGraph 智能体服务")
app.include_router(api_router)
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
六、框架对比:LangGraph vs 传统线性 LLM 应用 vs LangChain Agents
| 框架/方案 | 复杂流程支持 | 状态管理 | 循环/分支 | 多智能体协作 | 调试难度 | 适用场景 |
|---|---|---|---|---|---|---|
| LangGraph | 极强(图结构) | 内置全局状态 | 原生支持 | 原生支持 | 低(可视化+轨迹追踪) | 多步骤任务、循环迭代、分支决策、多智能体协作 |
| 传统线性 LLM 应用 | 极弱(线性流程) | 手动传递 | 不支持 | 不支持 | 中(需手动打印日志) | 简单问答、单次生成任务 |
| LangChain Agents | 中等(工具链) | 有限状态 | 部分支持 | 需手动集成 | 高(流程黑盒) | 单智能体工具调用、简单决策任务 |
七、总结
LangGraph 作为 LangChain 生态的核心扩展,以"图结构"为核心,彻底解决了复杂 LLM 应用的流程建模问题。其关键亮点总结如下:
- 核心价值:专注于"有状态、多步骤、需循环/分支"的复杂 LLM 任务,填补了线性流程与简单智能体的能力空白;
- 目录结构:遵循"模块化+分层架构",核心目录(graphs/agents/tools)职责清晰,支持中大型项目扩展;
- 关键特性:循环执行、分支决策、工具集成、多智能体协作四大核心能力,覆盖绝大多数复杂场景;
- 生产实践:状态持久化、错误重试、可视化调试、FastAPI 部署等能力,满足生产级稳定性与可维护性要求;
- 适用场景:数据分析报告、客服工单处理、多步骤问题解决、智能体协作系统、流程化业务处理(如合同审核、简历筛选)。