LangGraph简介
LangGraph是LangChain团队开发的低级别编排框架,专为构建、管理和部署长时间运行的有状态AI代理设计,提供持久化执行、灵活控制流和全面内存管理功能,支持循环和条件分支,是开发复杂AI工作流的理想选择。 共享内存,所有节点都可读写的全局数据结构,是代理的"工作记忆"。 示例: 图的基本执行单元,是接收状态并返回更新的函数。 类型: 定义示例: 节点间的连接,定义执行流的路径。 定义示例: LangGraph使用有向图模型表示代理工作流,包含: 特殊节点: 长期内存: LangGraph支持多种存储后端,满足不同场景需求: 长期记忆配置: 1. 定义状态: 2. 构建图: 3. 编译并执行: 核心类: 关键方法: 提供更简洁的方式构建小型工作流: 状态设计: 节点设计: 内存管理: LangGraph无缝集成LangSmith,提供全面的可观察性: 监控功能: 错误处理:为节点添加详细的异常捕获和日志记录: 使用Docker: 生产配置建议: 提供一键式云部署: 优势: LangGraph是构建复杂AI代理的强大框架,通过状态驱动的图结构,提供了持久执行、灵活控制流和全面内存管理能力。使用LangGraph,开发者可以轻松构建具有记忆、能够处理复杂逻辑的AI代理,适用于客服、研究助手、自动化工作流等多种场景。一、概述
1.1 核心特点
二、核心概念
2.1 状态(State)
from typing import TypedDict
class AgentState(TypedDict):
messages: list # 对话消息列表
search_results: list # 搜索结果
user_preferences: dict # 用户偏好2.2 节点(Nodes)
def greet(state: AgentState) -> dict:
return {"greeting": f"Hello, {state['user_name']}!"}2.3 边(Edges)
# 普通边:从"start"到"greet"
graph.add_edge("start", "greet")
# 条件边:根据状态判断是执行"search"还是"reply"
def decide_next(state: AgentState) -> str:
return "search" if state["needs_info"] else "reply"
graph.add_conditional_edges("greet", decide_next)三、架构与工作原理
3.1 图结构
START:执行入口点END:执行结束点3.2 状态管理
Store系统,支持跨会话、跨线程访问namespace和key组织数据,类似文件系统的目录和文件名3.3 执行流程
END或达到递归限制(默认25步)四、存储方案
存储类型 适用场景 特点 配置示例 InMemoryStore 开发测试 速度快,无持久化 store = InMemoryStore()PostgresStore 生产环境 高可靠,支持事务 store = PostgresStore("postgresql://user:pass@host/db")RedisStore 分布式系统 高性能读写,适合缓存 store = RedisStore("redis://host:port")SQLiteStore 轻量级应用 文件存储,无需服务器 store = SQLiteStore("langgraph.db")from langgraph.store.postgres import PostgresStore
from langgraph.backends import CompositeBackend, StateBackend, StoreBackend
# 配置复合存储:/memories/路径下的数据持久化,其他临时存储
def make_backend(runtime):
return CompositeBackend(
default=StateBackend(runtime), # 临时存储
routes={"/memories/": StoreBackend(runtime, PostgresStore("..."))} # 持久存储
)五、使用方法
5.1 安装
pip install -U langgraph # Python版本
npm install @langchain/langgraph # JavaScript版本5.2 基本使用步骤
from typing import TypedDict
class ChatState(TypedDict):
messages: list # 对话消息列表from langgraph.graph import StateGraph, START, END
from langchain.llms import OpenAI
# 初始化图
graph = StateGraph(ChatState)
# 定义节点:调用LLM生成回复
def call_llm(state: ChatState):
llm = OpenAI(temperature=0)
response = llm.invoke(state["messages"])
return {"messages": state["messages"] + [response]}
# 添加节点和边
graph.add_node("generate_response", call_llm)
graph.add_edge(START, "generate_response")
graph.add_edge("generate_response", END)# 编译为可执行应用
app = graph.compile()
# 执行
initial_state = {"messages": [{"role": "user", "content": "Hello!"}]}
final_state = app.invoke(initial_state)
print(final_state["messages"][-1]["content"]) # 输出AI回复5.3 条件执行与循环
# 定义条件函数:检查是否需要调用工具
def needs_tool(state: ChatState) -> Literal["use_tool", "reply"]:
last_message = state["messages"][-1]
return "use_tool" if last_message.get("tool_calls") else "reply"
# 添加条件边
graph.add_conditional_edges("generate_response", needs_tool)
# 添加工具节点和循环边
graph.add_node("use_tool", tool_node)
graph.add_edge("use_tool", "generate_response") # 循环回LLM节点六、API参考
6.1 Graph API
add_node(name, function, **kwargs):添加节点,支持重试策略等配置add_edge(from_node, to_node):添加普通边add_conditional_edges(from_node, condition_func):添加条件边compile(checkpointer=None):编译图为可执行应用,支持持久化配置invoke(input_state, config=None):执行图,返回最终状态6.2 Functional API (简化版)
from langgraph import entrypoint, task
@entrypoint
def my_agent():
state = {"counter": 0}
while state["counter"] < 3:
state = task(increment)(state) # 调用任务函数
return state
@task
def increment(state):
state["counter"] += 1
return state
result = my_agent() # 执行七、开发指南
7.1 构建步骤
7.2 最佳实践
八、调试与监控
8.1 使用LangSmith集成
# 启用LangSmith追踪
import os
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "..."
# 编译图时启用追踪
app = graph.compile(checkpointer=checkpointer, trace=True)8.2 本地调试技巧
print语句,输出关键状态graph.invoke并传入小输入,逐步验证每个节点def safe_node(state):
try:
# 正常逻辑
except Exception as e:
return {"error": str(e)} # 返回错误信息而非崩溃九、部署方案
9.1 自托管部署
# 安装CLI
pip install -U langgraph-cli
# 构建镜像
langgraph build --name my-agent .
# 运行
docker run -p 8124:8124 my-agent9.2 LangSmith Cloud (原LangGraph Platform)
十、完整示例:构建天气查询代理
# 1. 安装依赖
pip install langgraph langchain openai
# 2. 导入必要模块
from typing import TypedDict, Literal
from langchain.llms import OpenAI
from langchain_core.messages import HumanMessage, AIMessage
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver # 内存检查点
# 3. 定义状态
class WeatherAgentState(TypedDict):
messages: list # 对话消息
location: str # 查询的城市
weather_info: str # 天气信息
# 4. 定义工具函数
def get_weather(location: str) -> str:
"""简化的天气查询API"""
if location.lower() == "sf":
return "60°F, foggy"
elif location.lower() == "ny":
return "90°F, sunny"
else:
return "Weather data not available for this location"
# 5. 定义节点
def initial_prompt(state: WeatherAgentState) -> dict:
"""询问用户想查询哪个城市的天气"""
llm = OpenAI(temperature=0)
response = llm.invoke([HumanMessage(content="Which city's weather would you like to check?")])
return {"messages": [response]}
def parse_location(state: WeatherAgentState) -> dict:
"""从用户消息中提取城市名"""
last_message = state["messages"][-1]
location = last_message.content.strip().lower()
return {"location": location, "messages": state["messages"] + [AIMessage(content=f"Checking weather for {location}...")]}
def get_weather_info(state: WeatherAgentState) -> dict:
"""调用天气工具获取信息"""
weather = get_weather(state["location"])
return {"weather_info": weather, "messages": state["messages"] + [AIMessage(content=f"Weather in {state['location']}: {weather}")]}
# 6. 构建图
graph = StateGraph(WeatherAgentState)
# 添加节点
graph.add_node("initial_prompt", initial_prompt)
graph.add_node("parse_location", parse_location)
graph.add_node("get_weather_info", get_weather_info)
# 添加边定义执行流
graph.add_edge(START, "initial_prompt")
graph.add_edge("initial_prompt", "parse_location")
graph.add_edge("parse_location", "get_weather_info")
graph.add_edge("get_weather_info", END)
# 7. 添加内存支持
checkpointer = MemorySaver() # 使用内存检查点保存状态
app = graph.compile(checkpointer=checkpointer)
# 8. 执行代理
first_run = app.invoke({})
print("First run output:")
for msg in first_run["messages"]:
print(f"{msg['role'].capitalize()}: {msg['content']}")
print("\nSecond run (with state persistence):")
# 第二次执行会保留之前的对话状态
second_run = app.invoke({})
for msg in second_run["messages"]:
print(f"{msg['role'].capitalize()}: {msg['content']}")十一、总结