引言:为什么你的AI应用需要一个"大脑"?
想象一下这个场景:你用LangChain写了个智能客服,把用户问题扔进去,AI生成回答,结束。你觉得一切都很完美------直到用户问了一个需要多步推理的问题:"我想查一下我的账户余额,再看看最近有没有优惠活动,如果两样都有的话,帮我买个最合适的套餐。"
单次LLM调用显然搞不定。你需要分支判断、条件循环、状态记忆,甚至需要多个智能体协同工作。
这就是LangGraph出场的时刻。
LangGraph是LangChain生态中专门构建有状态、多步骤AI工作流的框架。它把复杂任务建模为有向图(Graph) ,通过节点(Node) 和边(Edge) 来编排执行流程。自2024年首次发布以来,经过多个版本迭代,LangGraph已成长为生产级智能体开发的基石工具。
本文将带你从核心概念走到实战落地,全程干货,可以直接复制代码跟着跑。
一、核心概念:用图来思考AI工作流
LangGraph的核心思想其实很简单:一个图由节点和边组成,节点负责做事,边负责决定下一步去哪里。
StateGraph:状态的共享黑板
LangGraph最核心的抽象是StateGraph------一个拥有全局状态的图。所有节点通过读写同一个State对象来通信。就像办公室里的共享白板:每个人可以在白板上写东西,其他人看到后继续执行自己的任务。
State定义示例:
python
from typing import TypedDict, Annotated, List, Literal
import operator
class AgentState(TypedDict):
question: str # 用户原始问题
next_action: Literal["calc", "wiki", "respond", "end"] # 路由决策
tool_input: str # 工具参数
tool_output: str # 工具返回结果
scratchpad: Annotated[List[str], operator.add] # 思考日志(自动合并)
final_answer: str # 最终输出
其中scratchpad使用Annotated声明合并规则,框架会自动将多个节点追加的日志合并成一个列表------省去手动拼接的麻烦。
节点:业务逻辑的封装单元
每个节点就是一个函数,接收当前State,返回状态的增量更新(partial state):
python
def calculator_node(state: AgentState) -> dict:
"""数学计算节点示例"""
if state["next_action"] != "calc":
return {} # 不匹配则跳过
try:
result = eval(state["tool_input"])
return {"tool_output": str(result), "scratchpad": [f"计算结果: {result}"]}
except Exception as e:
return {"tool_output": f"ERROR: {str(e)}"}
节点遵循纯函数原则:相同输入必然产生相同输出,无副作用,易于测试和组合。
边:动态决策的交通枢纽
LangGraph提供两种边:
· 确定性边:固定指向下一个节点
· 条件边:根据State内容动态选择下一个节点
python
from langgraph.graph import StateGraph, END
def router(state: AgentState) -> str:
if state["tool_output"].startswith("ERROR"):
return "error_handler"
elif state["next_action"] == "respond":
return "final_node"
else:
return "continue"
# 条件边配置
graph.add_conditional_edges(
"calculator_node", # 源节点
router, # 路由函数
{
"error_handler": "error_node",
"final_node": END,
"continue": "next_node"
}
)
构建与执行:三部曲
使用StateGraph分三步:定义 → 添加节点和边 → 编译。
python
from langgraph.graph import StateGraph
# 1. 初始化图
workflow = StateGraph(AgentState)
# 2. 添加节点
workflow.add_node("calculator", calculator_node)
workflow.add_node("formatter", formatter_node)
workflow.add_node("error_handler", error_node)
# 3. 设置入口和边
workflow.set_entry_point("calculator")
workflow.add_edge("calculator", "formatter")
workflow.add_conditional_edges("formatter", check_errors)
# 4. 编译后执行
app = workflow.compile()
result = app.invoke({
"question": "计算 25 * 4",
"next_action": "calc",
"tool_input": "25 * 4"
})
编译后,等待执行,就得到最终结果。
二、实战案例:从零搭建ReAct智能体
纸上谈兵不如动手写代码。我们从最经典的ReAct模式开始------这个模式的本质是循环执行"思考→行动→观察",直到任务完成。
什么是ReAct? 它是Reasoning + Acting的组合,让AI在思考(Reason)和行动(Act)之间来回切换。例如用户问"明天北京天气怎么样",AI先思考"需要查天气API",然后执行天气查询的行动,最后观察结果并给出回答------就像人类的"先想后做、边做边想"。
完整代码实现:
python
from typing import TypedDict, Annotated, List, Literal
import operator
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
# 1. 定义状态结构
class ReActState(TypedDict):
messages: Annotated[List[dict], operator.add] # 对话历史,自动合并
next_action: Literal["think", "act", "respond", "end"]
tool_name: str
tool_input: dict
tool_result: str
final_answer: str
# 2. 定义工具
@tool
def search(query: str) -> str:
"""模拟搜索功能"""
return f"关于'{query}'的搜索结果:找到3条相关信息..."
@tool
def calculate(expression: str) -> str:
"""计算表达式"""
return str(eval(expression))
tools_by_name = {"search": search, "calculate": calculate}
# 3. 定义节点函数
def think_node(state: ReActState) -> dict:
"""思考节点:LLM决定下一步做什么"""
model = ChatOpenAI(model="gpt-4", temperature=0)
prompt = f"""
你是一个智能助手。当前对话: {state['messages']}
请判断下一步操作,输出格式:
THINK: 推理过程
ACTION: 工具名
ACTION_INPUT: 工具输入
"""
response = model.invoke(prompt)
# 简化示例:根据用户输入判断
last_msg = state["messages"][-1]["content"] if state["messages"] else ""
if "计算" in last_msg:
# 提取表达式
expr = last_msg.replace("计算", "").strip()
return {"tool_name": "calculate", "tool_input": {"expression": expr},
"next_action": "act", "messages": [{"role": "assistant", "content": f"我需要计算: {expr}"}]}
elif "搜索" in last_msg:
query = last_msg.replace("搜索", "").strip()
return {"tool_name": "search", "tool_input": {"query": query},
"next_action": "act", "messages": [{"role": "assistant", "content": f"正在搜索: {query}"}]}
else:
return {"next_action": "respond", "messages": [{"role": "assistant", "content": "我直接回答您的问题"}]}
def act_node(state: ReActState) -> dict:
"""执行节点:调用工具执行具体操作"""
tool = tools_by_name.get(state["tool_name"])
if not tool:
return {"tool_result": f"错误:找不到工具 {state['tool_name']}", "next_action": "think"}
try:
# 调用工具
result = tool.invoke(state["tool_input"])
return {"tool_result": str(result), "next_action": "think",
"messages": [{"role": "assistant", "content": f"执行结果: {result}"}]}
except Exception as e:
return {"tool_result": f"执行出错: {str(e)}", "next_action": "think"}
def respond_node(state: ReActState) -> dict:
"""回答节点:生成最终回复"""
model = ChatOpenAI(model="gpt-4", temperature=0.7)
prompt = f"根据上下文,回答用户:{state['messages']}\n工具执行结果:{state.get('tool_result', '无')}"
response = model.invoke(prompt)
return {"final_answer": response.content, "next_action": "end"}
# 4. 构建路由函数
def route_after_think(state: ReActState) -> str:
if state["next_action"] == "act":
return "act_node"
elif state["next_action"] == "respond":
return "respond_node"
else:
return END
def route_after_act(state: ReActState) -> str:
return "think_node"
# 5. 构建状态图
workflow = StateGraph(ReActState)
# 添加节点
workflow.add_node("think", think_node)
workflow.add_node("act", act_node)
workflow.add_node("respond", respond_node)
# 设置入口
workflow.set_entry_point("think")
# 添加边
workflow.add_conditional_edges("think", route_after_think)
workflow.add_edge("act", "think_node") # 循环:行动后回到思考
workflow.add_edge("respond", END)
# 6. 编译并运行
app = workflow.compile()
result = app.invoke({
"messages": [{"role": "user", "content": "计算 123 * 456"}],
"next_action": "",
"tool_name": "",
"tool_input": {},
"tool_result": "",
"final_answer": ""
})
print(f"最终回答: {result['final_answer']}")
这个例子展示了一个完整的ReAct循环:思考→行动→记录结果→再思考→最终回答。整个流程清晰可追踪。
你可以在此基础上拓展:
扩展方向 实现方式
添加更多工具 用@tool装饰器封装API调用、数据库查询等
增加重试机制 在act_node中添加异常处理和max_retries参数
实现状态持久化 集成LangGraph内置的MemorySaver或Redis存储
三、多智能体协作:从独行侠到团队作战
单智能体的天花板很明显:工具选择困难、上下文爆炸、角色功能混杂等问题会拖垮系统性能。
LangGraph天然支持多智能体架构,将复杂任务拆解给多个专业化Agent协同处理。某电商客服系统案例显示,采用多智能体方案后,工单处理效率提升了80%以上。
三种主流协作架构
- 主管模式(Supervisor Pattern)
主管Agent统一接收请求,分析后分配给专业子Agent。适用于结构清晰、需要集中管控的场景。
python
from langgraph.graph import StateGraph, END
from typing import TypedDict, Literal
class SupervisorState(TypedDict):
query: str
current_agent: Literal["billing", "technical", "sales", "supervisor"]
result: str
def supervisor_node(state: SupervisorState):
"""主管:分析请求并分发给专门的Agent"""
query = state["query"]
if "账单" in query or "支付" in query:
return {"current_agent": "billing"}
elif "技术" in query or "报错" in query:
return {"current_agent": "technical"}
elif "购买" in query or "价格" in query:
return {"current_agent": "sales"}
else:
return {"current_agent": "supervisor"} # 自己处理
def billing_agent(state: SupervisorState):
"""账单处理智能体"""
return {"result": f"已为您查询账单: {state['query']}"}
def technical_agent(state: SupervisorState):
"""技术问题处理智能体"""
return {"result": f"技术团队已收到: {state['query']},预计24小时内回复"}
def sales_agent(state: SupervisorState):
"""销售处理智能体"""
return {"result": f"销售团队已关注: {state['query']},即刻为您报价"}
def router_after_supervisor(state: SupervisorState) -> str:
return state["current_agent"]
# 构建图
workflow = StateGraph(SupervisorState)
workflow.add_node("supervisor", supervisor_node)
workflow.add_node("billing", billing_agent)
workflow.add_node("technical", technical_agent)
workflow.add_node("sales", sales_agent)
workflow.set_entry_point("supervisor")
workflow.add_conditional_edges("supervisor", router_after_supervisor)
workflow.add_edge("billing", END)
workflow.add_edge("technical", END)
workflow.add_edge("sales", END)
电信巨头Fastweb + Vodafone正是采用这种架构构建了服务近950万用户的AI客服系统,主管Agent负责识别用户意图并路由到专业用例模块。
- 网络模式(Network Pattern)
Agent之间自由通信,形成网状拓扑。灵活性极高,但需要处理通信复杂度和冲突仲裁。
- 分层模式(Hierarchical Pattern)
引入多层管理结构,协调层负责跨Agent通信,执行层专注任务完成。适合超大型企业系统,如ServiceNow用其构建覆盖客户全旅程的多智能体系统。
四、进阶玩法:让LangGraph更好用
- Context API:告别配置地狱
LangGraph v0.6引入了革命性的Context API,解决了传统开发中上下文传递脆弱、类型不安全、扩展受限三大痛点。
旧模式(痛点) :
python
def process_request(config: dict):
user_id = config.get("user", {}).get("id") # 可能返回None
db_conn = config["database"]["connection"] # 潜在KeyError
新模式(类型安全) :
python
from dataclasses import dataclass
@dataclass
class AppContext:
user_id: str
session_token: str
max_retries: int = 3
allowed_tools: list[str] = None
def handle_request(runtime: Runtime[AppContext]):
if runtime.context.user_id == "admin":
return special_admin_handler(runtime)
通过dataclass定义上下文,IDE自动补全,编译时检查类型错误,整体开发效率提升60%以上。
- 状态持久化与检查点
生产环境中,工作流可能执行几分钟甚至几小时。LangGraph内置的检查点机制可以随时保存状态,支持中断恢复:
python
from langgraph.checkpoint import MemorySaver
# 使用内存存储(也可以换成RedisSaver、SqliteSaver等)
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)
# 带thread_id的执行,可中断后恢复
config = {"configurable": {"thread_id": "session_001"}}
result = app.invoke({"query": "我的订单" + "..." * 1000}, config)
执行中断后,用相同thread_id调用invoke即可从中断点继续执行。
- 生产环境部署最佳实践
从原型到生产,需要关注以下关键点:
依赖管理:使用Conda虚拟环境隔离,通过requirements-prod.txt固化生产版本。
yaml
name: langgraph-prod
dependencies:
- python=3.9.12
- langgraph=1.0.3
可观测性:集成ELK日志栈实现全链路追踪,用Prometheus+Grafana监控智能体响应延迟、状态同步成功率等关键指标。
弹性扩展:基于Kubernetes部署,支持API服务器与队列分离、独立扩缩容。某个采用LangGraph重构的智能客服系统,并发处理能力提升400%,故障恢复时间从小时级缩短至秒级。
五、LangGraph vs 传统方案:一张表看懂优势
对比维度 传统LangChain Chain LangGraph
控制流 线性管道,分支需要嵌套 完整图模型:分支、循环、并发
状态管理 隐式传递,难以追踪 显式State对象,全局可观察
可调试性 断点困难,像黑盒 每个节点都是独立单元,易测试
长时间任务 不支持中断恢复 检查点机制,天然支持持久化
多智能体 需手写协调器 内置多智能体模式
在复杂业务场景中,LangGraph的任务完成率比传统方案提升37%。
结语:LangGraph的无限可能
LangGraph远不止本文介绍的这些。从基础的ReAct模式到分布式多智能体系统,从单一工作流编排到千级智能体协同,LangGraph正在重新定义AI应用开发的边界。
正如Fastweb + Vodafone用它支撑近950万用户对话,ServiceNow用它构建企业级多智能体系统------LangGraph已经证明了自己在生产环境中的可靠性。
如果你还没有尝试过LangGraph,现在就是最好的开始时机。别把复杂的业务逻辑硬塞进线性Chain里了------用图来思考,用LangGraph来构建。