LangGraph:从原型到生产的Agent框架
LangGraph最大的优势不在于功能丰富,而在于它对生产环境的认真对待——状态管理、检查点、人机协作、错误处理,这些生产级需求被设计在框架核心而非附加功能。
状态管理
定义Agent状态
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List
import operator
class AgentState(TypedDict):
messages: Annotated[List, operator.add] # 消息列表(追加)
current_task: str # 当前任务
completed_steps: List[str] # 已完成步骤
tool_results: dict # 工具结果
error_count: int # 错误计数
human_feedback: str # 人类反馈
next_action: str # 下一步行动
# 创建图
graph = StateGraph(AgentState)
状态更新模式
def research_node(state: AgentState):
"""研究节点:执行信息检索"""
query = state["current_task"]
results = search_tool(query)
# 状态更新(自动合并)
return {
"messages": [{"role": "assistant", "content": f"找到{len(results)}条结果"}],
"tool_results": {"search": results},
"completed_steps": state["completed_steps"] + ["research"],
"next_action": "analyze"
}
def analyze_node(state: AgentState):
"""分析节点:分析检索结果"""
results = state["tool_results"]["search"]
analysis = llm.analyze(results)
return {
"messages": [{"role": "assistant", "content": analysis}],
"completed_steps": state["completed_steps"] + ["analyze"],
"next_action": "write" if analysis else "research" # 分析不足则重新检索
}
检查点与恢复
持久化执行状态
from langgraph.checkpoint import MemorySaver, SqliteSaver
# 使用SQLite持久化
checkpointer = SqliteSaver.from_conn_string("agent.db")
graph = StateGraph(AgentState)
graph.add_node("research", research_node)
graph.add_node("analyze", analyze_node)
graph.add_node("write", write_node)
graph.add_edge("research", "analyze")
graph.add_conditional_edges("analyze", lambda s: s["next_action"])
graph.add_edge("write", END)
app = graph.compile(checkpointer=checkpointer)
# 执行(可以中断和恢复)
config = {"configurable": {"thread_id": "task-123"}}
result = app.invoke(
{"current_task": "分析AI芯片市场", "messages": []},
config=config
)
# 恢复执行
restored = app.get_state(config)
# 可以从任意检查点恢复
检查点策略
class CheckpointStrategy:
def __init__(self):
self.saver = SqliteSaver.from_conn_string("checkpoints.db")
def should_checkpoint(self, state):
"""决定是否需要检查点"""
# 关键步骤后检查
if state.get("completed_steps"):
last_step = state["completed_steps"][-1]
if last_step in ["research", "analyze", "write"]:
return True
# 错误后检查
if state.get("error_count", 0) > 0:
return True
return False
人机协作
人工审批节点
# 在关键步骤前暂停,等待人工确认
app = graph.compile(
checkpointer=checkpointer,
interrupt_before=["publish"] # 发布前暂停
)
# 执行到publish节点前会暂停
result = app.invoke(
{"current_task": "撰写技术报告"},
config={"configurable": {"thread_id": "task-456"}}
)
# 人工审查后继续
if human_approved:
result = app.invoke(None, config=config) # 传入None继续执行
else:
# 人工提供修改意见
result = app.invoke(
{"human_feedback": "需要增加市场分析部分"},
config=config
)
交互式Agent
def human_interaction_node(state: AgentState):
"""需要人工输入的节点"""
# 展示当前状态
print(f"已完成步骤: {state['completed_steps']}")
print(f"当前结果: {state.get('tool_results', {})}")
# 请求人工输入
feedback = input("请提供反馈(直接回车确认): ")
return {
"human_feedback": feedback,
"next_action": "revise" if feedback else "continue"
}
错误处理与重试
节点级错误处理
def robust_node(state: AgentState, max_retries=3):
"""带错误处理的节点"""
try:
result = execute_task(state["current_task"])
return {
"tool_results": result,
"error_count": 0,
"next_action": "next"
}
except Exception as e:
retry_count = state.get("error_count", 0) + 1
if retry_count < max_retries:
# 重试
return {
"error_count": retry_count,
"next_action": "retry" # 重新执行当前节点
}
else:
# 超过重试次数,降级处理
return {
"error_count": 0,
"messages": [{"role": "system", "content": f"任务失败: {e}"}],
"next_action": "fallback"
}
条件边实现重试逻辑
graph.add_node("execute", robust_node)
graph.add_node("fallback", fallback_node)
# 正常流程
graph.add_edge("execute", "next_node")
# 重试逻辑
graph.add_conditional_edges(
"execute",
lambda state: state.get("next_action"),
{
"retry": "execute", # 重试当前节点
"next": "next_node", # 正常进入下一步
"fallback": "fallback" # 降级处理
}
)
子图与模块化
# 将复杂Agent拆分为子图
def build_research_subgraph():
"""研究子图"""
subgraph = StateGraph(ResearchState)
subgraph.add_node("search", search_node)
subgraph.add_node("filter", filter_node)
subgraph.add_node("summarize", summarize_node)
subgraph.add_edge("search", "filter")
subgraph.add_edge("filter", "summarize")
subgraph.add_edge("summarize", END)
return subgraph.compile()
# 主图中嵌入子图
main_graph = StateGraph(AgentState)
main_graph.add_node("research", build_research_subgraph()) # 嵌入子图
main_graph.add_node("write", write_node)
main_graph.add_edge("research", "write")
并行执行
from langgraph.graph import StateGraph, END
import operator
from typing import Annotated
class ParallelState(TypedDict):
task: str
results: Annotated[list, operator.add] # 并行结果追加
def parallel_research(state):
"""并行执行多个研究任务"""
sub_tasks = decompose(state["task"])
# 并行执行
results = []
for sub_task in sub_tasks:
result = research_agent.run(sub_task)
results.append(result)
return {"results": results}
# 或者使用LangGraph的Send API实现真正的并行
from langgraph.constants import Send
def fan_out(state):
"""扇出并行任务"""
sub_tasks = decompose(state["task"])
return [
Send("research_node", {"sub_task": st})
for st in sub_tasks
]
生产部署
部署架构
class LangGraphDeployment:
def __init__(self):
self.config = {
"runtime": {
"framework": "FastAPI",
"workers": 4,
"timeout": 300, # 5分钟超时
},
"checkpoint": {
"backend": "PostgreSQL", # 生产用PostgreSQL
"cleanup_interval": 3600, # 1小时清理一次
"retention_days": 7, # 保留7天
},
"monitoring": {
"trace_enabled": True,
"metrics": ["latency", "success_rate", "token_usage"],
"alerting": {
"error_rate_threshold": 0.05,
"latency_p99_threshold": 30000, # 30秒
}
}
}
def deploy(self):
# FastAPI服务
from fastapi import FastAPI
app = FastAPI()
@app.post("/agent/run")
async def run_agent(task: str, thread_id: str):
config = {"configurable": {"thread_id": thread_id}}
result = await self.agent.ainvoke(
{"current_task": task},
config=config
)
return result
return app
性能优化
class PerformanceOptimizer:
def optimize_graph(self, graph):
"""图优化"""
# 1. 节点合并:将总是顺序执行的节点合并
# 2. 冗余边移除:移除不会被执行的边
# 3. 缓存:对确定性节点启用缓存
optimized = graph
# 启用缓存
for node in graph.nodes:
if is_deterministic(node):
node.enable_cache = True
node.cache_ttl = 3600
return optimized
监控与可观测性
class AgentMonitor:
def __init__(self):
self.traces = []
def trace_execution(self, graph, input_state):
"""追踪Agent执行"""
trace = {
"input": input_state,
"nodes_executed": [],
"total_duration": 0,
"token_usage": 0,
"errors": []
}
for node_name, node_output in graph.stream(input_state):
trace["nodes_executed"].append({
"node": node_name,
"duration": measure_duration(),
"output": node_output,
"timestamp": datetime.now()
})
return trace
def visualize(self, trace):
"""可视化执行轨迹"""
return {
"graph": render_execution_graph(trace),
"timeline": render_timeline(trace),
"bottlenecks": identify_bottlenecks(trace)
}
结语
LangGraph的设计哲学是"为生产而构建"。它的图模型提供了精确的控制力,检查点机制保障了可靠性,人机协作支持了复杂业务流程。对于需要从原型走向生产的Agent系统,LangGraph是最稳妥的选择。学习曲线确实陡峭,但这是为生产级功能付出的合理代价——在生产环境中,可靠性和可控性远比开发便利性重要。