LangGraph 超详细教程,附源码
作者身份:资深踩坑程序员(5年后端开发,最近半年沉迷AI Agent)
一、为什么你需要 LangGraph?
上周我的AI Agent项目又挂了。
不是代码逻辑问题,也不是API调用错误------是状态管理。我写了个多步骤的搜索-分析-报告流程,用普通的LangChain Chain搞了三天,每次运行到第三步就不知道上一步的输出去哪了。
vbnet
Step 1: 搜索完成 ✅
Step 2: 分析完成 ✅
Step 3: 报告生成 ❌ 上下文丢失
后来在LangChain的GitHub issue里看到有人问同样的问题,维护者回复了一句让我醍醐灌顶的话:
"Chain是线性的,但Agent的工作流是图状的。"
于是有了 LangGraph。
一句话理解 LangGraph:它不是另一个框架,而是 LangChain 官方对"如何让Agent工作流可追踪、可调试、可持久化"的终极答案。
二、环境准备
2.1 安装依赖
bash
pip install langgraph langchain-openai langchain-anthropic
如果你用 Claude(推荐,Agent能力更强):
bash
export ANTHROPIC_API_KEY="sk-ant-api03-..."
如果用 OpenAI:
bash
export OPENAI_API_KEY="sk-..."
2.2 项目结构
bash
langgraph-demo/
├── agent.py # 核心Agent定义
├── graph.py # 图结构定义
├── tools.py # 工具函数
└── requirements.txt
三、完整代码实战
3.1 定义工具(tools.py)
别小看工具,Agent的"手"全靠它。
python
import requests
from typing import TypedDict, Annotated
class SearchTool:
"""模拟一个搜索工具,实际可以接 Serper/Brave API"""
def search(self, query: str) -> str:
# 真实场景换成: requests.get(f"https://serper.dev/search?q={query}")
results = {
"AI Agent 框架": "LangGraph、AutoGen、CrewAI 是当前主流框架",
"MCP 协议": "Model Context Protocol,让AI模型统一访问外部数据",
"LangChain": "最流行的LLM应用开发框架,LangGraph是其子项目"
}
return results.get(query, f"未找到关于'{query}'的结果")
class Calculator:
"""一个简单的计算器工具"""
def calculate(self, expression: str) -> str:
try:
# 生产环境请用 sympy 或 ast.literal_eval
result = eval(expression, {"__builtins__": {}}, {})
return f"计算结果: {result}"
except Exception as e:
return f"计算失败: {str(e)}"
3.2 定义状态(graph.py)
这是 LangGraph 的核心------状态机。
python
from typing import TypedDict, Annotated, List
import operator
class AgentState(TypedDict):
"""Agent运行时的状态容器"""
# 用户输入
query: str
# 搜索到的信息
search_results: List[str]
# 分析结果
analysis: str
# 最终报告
report: str
# 中间步骤记录(用于调试)
steps: Annotated[List[str], operator.add]
# 是否需要继续(用于循环控制)
should_continue: str
关键点 :steps 用了 Annotated[..., operator.add],这意味着每次添加步骤会自动追加到列表,而不是覆盖。这是 LangGraph 处理累积状态的标准方式。
3.3 定义节点函数(agent.py)
节点 = 工作流中的一个步骤。
python
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
def search_node(state: AgentState) -> AgentState:
"""第一步:搜索相关信息"""
print(f"🔍 搜索: {state['query']}")
tool = SearchTool()
results = [tool.search(state['query'])]
return {
"search_results": results,
"steps": ["搜索完成"]
}
def analyze_node(state: AgentState) -> AgentState:
"""第二步:分析搜索结果"""
print("📊 分析搜索结果...")
prompt = f"""基于以下搜索结果,进行分析:
搜索结果: {state['search_results']}
请分析:
1. 关键信息提取
2. 信息可信度评估
3. 还需要补充哪些信息?
"""
response = llm.invoke([HumanMessage(content=prompt)])
return {
"analysis": response.content,
"steps": ["分析完成"]
}
def generate_report_node(state: AgentState) -> AgentState:
"""第三步:生成最终报告"""
print("📝 生成报告...")
prompt = f"""请根据以下信息生成一份技术报告:
用户问题: {state['query']}
搜索结果: {state['search_results']}
分析结果: {state['analysis']}
报告格式:
- 标题
- 核心结论(3条以内)
- 详细说明
- 参考文献/来源
"""
response = llm.invoke([HumanMessage(content=prompt)])
return {
"report": response.content,
"steps": ["报告生成完成"]
}
def should_continue_node(state: AgentState) -> dict:
"""条件节点:判断是否需要继续搜索"""
if len(state.get("search_results", [])) < 2:
return {"should_continue": "search_more"}
return {"should_continue": "end"}
3.4 构建图并运行(agent.py 续)
python
def create_agent_graph():
"""构建完整的Agent工作流图"""
# 初始化图
workflow = StateGraph(AgentState)
# 添加节点
workflow.add_node("search", search_node)
workflow.add_node("analyze", analyze_node)
workflow.add_node("generate_report", generate_report_node)
workflow.add_node("decision", should_continue_node)
# 定义边(工作流路径)
workflow.set_entry_point("search")
workflow.add_edge("search", "analyze")
workflow.add_edge("analyze", "decision")
# 条件边:根据 decision 节点的输出决定走向
workflow.add_conditional_edges(
"decision",
lambda s: s["should_continue"],
{
"search_more": "search", # 循环回去
"end": "generate_report"
}
)
workflow.add_edge("generate_report", END)
return workflow.compile()
# 运行!
if __name__ == "__main__":
graph = create_agent_graph()
result = graph.invoke({
"query": "AI Agent 框架",
"steps": [],
"search_results": [],
"analysis": "",
"report": "",
"should_continue": ""
})
print("\n" + "="*50)
print("📄 最终报告:")
print("="*50)
print(result["report"])
print("\n📋 执行步骤:")
for step in result["steps"]:
print(f" - {step}")
四、运行效果
markdown
🔍 搜索: AI Agent 框架
📊 分析搜索结果...
📝 生成报告...
==================================================
📄 最终报告:
==================================================
# AI Agent 框架技术报告
## 核心结论
1. LangGraph 是当前生产环境最成熟的 Agent 框架
2. MCP 协议正在成为 AI 模型访问外部数据的标准
3. 选择框架需考虑团队技术栈和部署环境
## 详细说明
...
📋 执行步骤:
- 搜索完成
- 分析完成
- 报告生成完成
五、常见问题 FAQ
Q1: LangGraph 和 LangChain 是什么关系?
不是替代关系,是互补关系。
- LangChain:提供 LLM 调用、Prompt 模板、Chain 等基础能力
- LangGraph:在 LangChain 基础上,专门解决多步骤工作流的状态管理问题
你可以只用 LangChain 不用 LangGraph(简单场景够用),但复杂 Agent 项目几乎都需要 LangGraph。
Q2: 为什么我的图运行时报错 "Node X not found"?
90% 的原因是 entry_point 设置错了。
python
# ❌ 错误:entry_point 指向不存在的节点名
workflow.set_entry_point("start") # 但实际节点叫 "search"
# ✅ 正确:必须和 add_node 的 name 一致
workflow.set_entry_point("search")
Q3: 如何实现"人类介入"(Human-in-the-loop)?
LangGraph 的杀手级功能。
python
from langgraph.checkpoint.memory import MemorySaver
# 添加持久化检查点
memory = MemorySaver()
graph = workflow.compile(checkpointer=memory)
# 运行到某个节点后暂停,等待人类确认
config = {"configurable": {"thread_id": "session_1"}}
result = graph.invoke(input, config=config)
# 人类确认后继续
graph.invoke(None, config=config) # None 表示继续
实际场景:Agent 生成报告后,暂停等待你确认是否发布,你点"确认"后它才执行发布操作。
Q4: 状态太大怎么办?
用 Annotated 做增量更新,而不是全量覆盖。
python
class AgentState(TypedDict):
# ❌ 每次都覆盖整个文档
document: str
# ✅ 只追加新内容,节省内存
document_chunks: Annotated[List[str], operator.add]
六、总结
LangGraph 的核心价值就三个词:
- 状态可追踪:每一步的输出都保存在状态里,随时可查
- 流程可调试:条件边 + 循环边,复杂逻辑一目了然
- 运行可持久化:配合 checkpointer,支持断点续跑、人类介入
我之前的项目如果用 LangGraph,那三天的状态丢失问题根本不会发生。
建议:如果你已经在用 LangChain 做 Agent,下一步就是学 LangGraph。官方文档很详细,但建议先看这个教程再去看文档,否则容易被概念绕晕。
如果觉得有帮助,欢迎点赞收藏 ❤️ 更多AI工具实战教程,关注我第一时间获取~