Files
ai-agent-dev/14_LangGraph概述.ipynb
2026-07-08 10:09:42 +08:00

300 lines
10 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 14 LangGraph 概述\n",
"\n",
"## 学习目标\n",
"1. 理解为什么需要 LangGraph复杂智能体流程的控制需求\n",
"2. 掌握 LangGraph 的核心概念StateGraph、State、Node、Edge\n",
"3. 理解 LangGraph 与 LangChain 的关系和分工\n",
"4. 能够编写一个最简单的 LangGraph 状态图\n",
"5. 了解 LangGraph 的典型应用场景"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 为什么需要 LangGraph\n",
"\n",
"前面我们用 LangChain 构建了链式应用和简单的工具调用智能体。但当智能体流程变得复杂时,会遇到一些问题:\n",
"\n",
"- **流程不可控**:标准 Agent 的黑盒决策难以调试和约束\n",
"- **循环和分支困难**:难以实现多轮循环、条件分支、人机协作\n",
"- **状态管理复杂**:多步骤之间的状态传递不清晰\n",
"- **缺乏持久化**:无法暂停、恢复或检查执行历史\n",
"\n",
"**LangGraph** 就是为了解决这些问题而设计的。它把智能体流程建模为一个**状态图StateGraph**,让开发者精确控制每个步骤。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. LangGraph 是什么\n",
"\n",
"LangGraph 是 LangChain 生态中的一个库,用于构建基于**状态图**的智能体应用。它的核心思想是:\n",
"\n",
"- 把应用看作一个图Graph\n",
"- 图中的每个节点Node是一个函数或操作\n",
"- 边Edge控制流程走向\n",
"- 状态State在节点之间传递\n",
"\n",
"LangGraph 基于 LangChain 的 Runnable 接口构建,因此可以无缝使用 LangChain 的模型、工具、Prompt 等组件。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. LangGraph 与 LangChain 的关系\n",
"\n",
"| 对比项 | LangChain | LangGraph |\n",
"| --- | --- | --- |\n",
"| 核心抽象 | Chain / Agent | StateGraph |\n",
"| 流程控制 | 线性或简单循环 | 任意图结构、条件分支、循环 |\n",
"| 状态管理 | 隐式传递 | 显式 State 对象 |\n",
"| 适用场景 | 简单流水线、单次调用 | 复杂多智能体、多轮交互 |\n",
"| 关系 | 基础组件库 | 基于 LangChain 构建的流程编排层 |\n",
"\n",
"可以把 LangChain 理解为「零件库」LangGraph 理解为「装配线控制系统」。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. 核心概念\n",
"\n",
"### 4.1 State状态\n",
"状态是整个图共享的数据结构。每个节点读取状态、修改状态,然后把状态传递给下一个节点。\n",
"\n",
"### 4.2 StateGraph状态图\n",
"状态图是 LangGraph 最核心的类。它负责定义节点、边和状态类型。\n",
"\n",
"### 4.3 Node节点\n",
"节点是图中的执行单元,通常是一个 Python 函数。节点接收当前状态,返回对状态的更新。\n",
"\n",
"### 4.4 Edge\n",
"边定义节点之间的连接关系。LangGraph 支持:\n",
"- 普通边:固定从一个节点到另一个节点\n",
"- 条件边:根据状态决定下一个节点\n",
"- START / END图的起点和终点"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. 第一个 LangGraph 程序\n",
"\n",
"下面构建一个最简单的图:两个节点 `node_a` 和 `node_b``node_a` 给状态加 1`node_b` 再给状态乘 2。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from typing_extensions import TypedDict\n",
"from langgraph.graph import StateGraph, START, END\n",
"\n",
"# 1. 定义状态类型\n",
"class MyState(TypedDict):\n",
" \"\"\"图中的共享状态。\"\"\"\n",
" value: int\n",
"\n",
"# 2. 定义节点函数\n",
"def node_a(state: MyState):\n",
" \"\"\"把 value 加 1。\"\"\"\n",
" print(f'Node A 接收:{state[\"value\"]}')\n",
" return {'value': state['value'] + 1}\n",
"\n",
"def node_b(state: MyState):\n",
" \"\"\"把 value 乘 2。\"\"\"\n",
" print(f'Node B 接收:{state[\"value\"]}')\n",
" return {'value': state['value'] * 2}\n",
"\n",
"# 3. 构建状态图\n",
"builder = StateGraph(MyState)\n",
"builder.add_node('node_a', node_a)\n",
"builder.add_node('node_b', node_b)\n",
"\n",
"# 4. 添加边\n",
"builder.add_edge(START, 'node_a')\n",
"builder.add_edge('node_a', 'node_b')\n",
"builder.add_edge('node_b', END)\n",
"\n",
"# 5. 编译图\n",
"graph = builder.compile()\n",
"\n",
"# 6. 运行图\n",
"result = graph.invoke({'value': 3})\n",
"print(f'\\n最终结果{result}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 代码解释\n",
"\n",
"- `TypedDict` 定义状态结构,告诉 LangGraph 图中有哪些字段\n",
"- `StateGraph(MyState)` 创建状态图实例\n",
"- `add_node(name, func)` 添加节点\n",
"- `add_edge(START, 'node_a')` 设置从图起点到 node_a 的边\n",
"- `compile()` 编译图,生成可执行的 Runnable\n",
"- `invoke({'value': 3})` 运行图,传入初始状态\n",
"\n",
"这个例子的执行流程是:`START -> node_a(value=3 -> 4) -> node_b(value=4 -> 8) -> END`,最终结果是 8。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. LangGraph 执行流程可视化\n",
"\n",
"LangGraph 提供了 `get_graph()` 方法,可以查看图的结构。\n",
"\n",
"在线查看Mermaid 图https://mermaid.live/edit\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 打印图的节点和边\n",
"print(graph.get_graph().nodes)\n",
"print(graph.get_graph().edges)\n",
"\n",
"# 使用 mermaid 格式可视化(在支持 mermaid 的 Markdown 查看器中可显示)\n",
"print('\\nMermaid 图:')\n",
"print(graph.get_graph().draw_mermaid())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. 在 LangGraph 中使用 LangChain 组件\n",
"\n",
"LangGraph 的节点可以使用任何 LangChain 组件。下面是一个使用 LLM 和 Prompt 的节点示例。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"from langchain_core.prompts import ChatPromptTemplate\n",
"from langgraph.graph.message import add_messages\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv()\n",
"\n",
"\n",
"# 定义带消息历史的状态\n",
"class ChatState(TypedDict):\n",
" messages: list # 对话历史\n",
"\n",
"llm = ChatOpenAI(model='qwen3.6-35b-A3b', temperature=0.7)\n",
"\n",
"def chat_node(state: ChatState):\n",
" \"\"\"调用 LLM 回复用户。\"\"\"\n",
" prompt = ChatPromptTemplate.from_messages([\n",
" ('system', '你是友好的 AI 助手。'),\n",
" *state['messages']\n",
" ])\n",
" response = (prompt | llm).invoke({})\n",
" return {'messages': [response]}\n",
"\n",
"builder = StateGraph(ChatState)\n",
"builder.add_node('chat', chat_node)\n",
"builder.add_edge(START, 'chat')\n",
"builder.add_edge('chat', END)\n",
"\n",
"chat_graph = builder.compile()\n",
"\n",
"result = chat_graph.invoke({\n",
" 'messages': [('user', '请用一句话介绍 LangGraph')]\n",
"})\n",
"print(result['messages'][-1].content)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 代码解释\n",
"\n",
"- `messages` 是列表类型,每个元素是 `(role, content)` 元组\n",
"- `ChatPromptTemplate.from_messages([...])` 中的 `*state['messages']` 把历史消息展开\n",
"- 节点返回 `{'messages': [response]}`LangGraph 会自动合并到状态中\n",
"- 这里只是一个单节点图,后续课程会扩展到多轮对话和循环"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. LangGraph 的典型应用场景\n",
"\n",
"LangGraph 特别适合以下场景:\n",
"\n",
"| 场景 | 说明 |\n",
"| --- | --- |\n",
"| **多轮工具调用** | 在循环中反复调用工具,直到获得足够信息 |\n",
"| **人机协作Human-in-the-loop** | 在关键节点暂停,等待人类确认 |\n",
"| **多智能体系统** | 多个 Agent 通过图结构协作完成任务 |\n",
"| **复杂审批流程** | 根据条件分支决定流程走向 |\n",
"| **长期记忆** | 通过持久化状态实现跨会话记忆 |\n",
"\n",
"这些场景在后面几节课会逐一展开。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. 本节课练习\n",
"\n",
"1. 修改第一个 LangGraph 示例,增加第三个节点 `node_c`,实现 value = value - 2\n",
"2. 改变三个节点的连接顺序,观察最终结果如何变化\n",
"3. 在 ChatState 中增加一个 `topic` 字段,让 system prompt 根据 topic 动态变化\n",
"4. 尝试画出本节课第一个示例的状态图START -> node_a -> node_b -> END\n",
"5. 思考LangGraph 与你之前学过的 LangChain Chain 相比,最大的优势是什么?"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.14.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}