07-08-周三_10-09-42

This commit is contained in:
AaronXu
2026-07-08 10:09:42 +08:00
commit 825bcf47fa
30 changed files with 16488 additions and 0 deletions

299
14_LangGraph概述.ipynb Normal file
View File

@@ -0,0 +1,299 @@
{
"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
}