前置知识:必看!零基础入门必备(超详细)
在开始学习 LangGraph 构建 Agent 之前,你不需要有任何 Python 高级编程基础,也不需要懂什么是"智能体",但必须掌握以下最基础的前置知识------我会像老师教新手一样,一步步讲明白,确保你能跟着操作、完全理解。
一、必备基础环境(必装!一步都不能少)
我们所有的代码都需要在「Python 环境」中运行,就像玩游戏需要先装游戏客户端一样,Python 就是我们的"代码客户端"。
1. 安装 Python(Windows 系统,最简易步骤)
-
打开 Python 官方下载地址:https://www.python.org/downloads/,找到"Download Python 3.10.x"(3.10 版本最稳定,兼容所有后续需要的库,不要装最新版,避免兼容性问题);
-
下载完成后,双击安装包,一定要勾选界面最下方的"Add Python 3.10 to PATH"(这一步是关键,勾选后才能在电脑任意地方运行 Python);
-
点击"Install Now",等待安装完成(全程下一步即可,无需修改其他设置);
-
验证是否安装成功:按下键盘"Win+R",输入"cmd"打开命令提示符,输入"python --version",如果显示"Python 3.10.x",说明安装成功;如果提示"不是内部或外部命令",就是没勾选"Add Python to PATH",需要重新安装并勾选。
2. 安装代码编辑器(推荐 VS Code,免费又简单)
Python 是"客户端",代码编辑器就是我们"写代码的本子",推荐 VS Code(比记事本好用,能高亮代码、提示错误):
-
下载地址:https://code.visualstudio.com/,点击"Download for Windows",下载后双击安装(全程下一步);
-
安装完成后,打开 VS Code,点击左侧"扩展"(图标是四个方块),搜索"Python",安装第一个(作者是 Microsoft,蓝色图标);
-
新建代码文件:点击左上角"文件"→"新建文件",保存时选择"保存类型"为"Python 文件(.py)",比如保存为"test.py"(保存路径建议简单,比如桌面,方便后续找到)。
3. 安装必备依赖库(核心!代码能运行的关键)
我们写的代码需要"借助别人写好的工具"才能运行,这些工具就是"依赖库",就像玩游戏需要装插件一样。安装方法很简单:
-
打开 VS Code,点击顶部"终端"→"新建终端",此时底部会出现一个黑色的命令窗口(和之前的命令提示符一样);
-
在终端中输入以下命令,复制粘贴后按回车,等待安装完成(每输一条装一个,装完一条再装下一条,不要一次性复制所有命令): ① pip install langchain (核心框架,所有大模型、工具调用的基础) ② pip install langgraph (本章核心,构建 Agent 的工具) ③ pip install langchain-community (集成各种大模型、工具的扩展库) ④ pip install langgraph-supervisor (多 Agent 协同需要的库) ⑤ pip install python-dotenv (加载配置、密钥的工具,后续会用到) ⑥ pip install langmem (记忆管理相关库)
-
验证是否安装成功:在终端输入"pip list",会显示所有已安装的库,如果上面6个库都在列表中,说明安装成功;如果提示"pip 不是内部或外部命令",和之前 Python 安装问题一样,重新安装 Python 并勾选"Add to PATH"。
二、核心概念铺垫
在看代码之前,先搞懂几个关键名词,后续所有内容都围绕这些名词展开,不会再反复解释,一定要记住!
1. 大模型(LLM)
就是我们平时说的"AI",比如 ChatGPT、通义千问、文心一言。它能听懂我们的问题、生成回答,我们的代码就是"调用"这个 AI,让它帮我们干活。本章用的是「阿里云百炼的通义千问」(免费、易申请,适合)。
2. API 密钥(API Key)
相当于我们"调用大模型的身份证"------大模型是别人提供的服务,我们要使用它,必须出示这个"身份证",证明我们是合法用户,不是非法调用。
获取方法(通义千问,免费):
-
打开阿里云百炼官网:https://bailian.aliyun.com/,注册/登录阿里云账号(用淘宝、支付宝账号就能登录);
-
登录后,点击顶部"控制台",找到"API 密钥管理",点击"创建 API 密钥",会生成"Access Key ID"和"Access Key Secret"(也就是我们需要的 API Key);
-
注意:API Key 不要泄露给别人,泄露后别人可能会用你的账号调用大模型,产生费用(免费额度足够学习,不用担心)。
3. LangChain
一个"大模型工具包"------别人已经写好的大量代码,帮我们简化"调用大模型、使用工具"的流程。比如我们想调用通义千问,不用自己写复杂的代码,LangChain 已经帮我们封装好了接口,我们只需要简单几行代码就能调用。
4. LangGraph
基于 LangChain 的"进阶工具包"------专门用来构建"智能体(Agent)",能让大模型不仅能聊天,还能自主调用工具、记住聊天历史、接受人工监督,相当于给大模型"加了大脑和手脚"。
5. Agent(智能体)
简单说,就是"能自主干活的 AI"。比如我们让它"查今天的日期",它会自己判断"需要调用查日期的工具",调用完成后,再把结果告诉我们,全程不用我们干预------就像一个不用你催、能自己完成任务的员工。
6. Tools(工具)
Agent 用来"干活的工具",比如"查日期""查天气""预订酒店""计算除法",这些都是工具。我们需要先定义好工具,Agent 才能调用它们。
7. 会话记忆(Memory)
就是 Agent 能"记住之前的聊天内容"。比如你先问"长沙天气怎么样",再问"北京呢",Agent 能记住你上一句问的是天气,不用你再重复说"北京天气怎么样"------就像我们和人聊天,对方能记住你之前说的话。
第一章:什么是 Agent?(彻底懂)
很多人听说过"Agent 智能体",但不知道它到底是什么,其实没有复杂的定义,我们用"员工"的例子,一下子就能懂:
一个好的员工,应该具备两个特点:① 能力强,能独立完成任务,不用老板天天盯着、干预细节(比如让他打印文件,他能自己找打印机、操作,不用老板教每一步);② 听话,关键节点会请示老板(比如打印重要文件前,会问老板"确认要打印吗",老板说可以再执行)。
Agent 就是这样的"AI 员工":
-
自主能力:能独立完成"调用大模型聊天、调用工具干活、记住聊天历史"等任务,不用我们写复杂的流程代码;
-
可控能力:关键步骤(比如预订酒店、删除数据)能停下来,等我们确认后再继续,避免出错。
具体到 LangGraph 中,Agent 必须具备以下基础能力(后续我们会一步步给它加上这些能力):
-
能访问大模型(能听懂我们的问题、生成回答);
-
能调用外部工具(能查日期、查天气等);
-
能保存聊天记忆(能记住之前的对话);
-
能接受人工监督(关键步骤能中断,等我们确认)。
第二章:使用 LangGraph 构建 Agent 智能体(从基础到进阶)
本章核心:从"只能聊天的基础 Agent"开始,一步步给它加上"工具调用""记忆管理""人工监督"能力,最终实现一个功能完整、安全可控的 Agent,为后续多 Agent 协同打下基础。
重要提醒:所有代码都要在 VS Code 中编写,保存为 .py 文件,然后点击代码右上角的"运行"按钮(绿色三角),就能看到运行结果;每段代码我都会加详细注释,讲清"每一行代码是什么意思""运行流程是什么""会输出什么结果",跟着抄代码、看注释,就能完全懂。
第一节:搭建基础聊天 Agent(只能聊天,不能干活)
第一步:先实现"调用通义千问聊天",这是最基础的功能,相当于给 Agent 先"装上嘴巴和耳朵",能听懂我们的话、能回答我们的问题。
1. 前置准备:创建配置文件(保存 API Key,避免泄露)
我们不直接把 API Key 写在代码里(容易泄露),而是创建一个配置文件,专门保存密钥,然后用代码读取------这是规范的写法,也能轻松操作。
-
在 VS Code 中,新建一个文件,保存为"config.py"(和我们写代码的文件放在同一个文件夹,比如桌面);
-
在"config.py"中写入以下代码(替换成你自己的阿里云百炼 API Key):
python
# config.py 文件:专门保存 API 密钥,避免直接写在业务代码中
def load_key(key_name):
"""
读取 API 密钥的函数(不用懂函数细节,知道怎么用就行)
参数 key_name:要读取的密钥名称(比如 "BAILIAN_API_KEY")
返回值:对应的密钥值
"""
# 替换成你自己的阿里云百炼 API Key(Access Key Secret)
if key_name == "BAILIAN_API_KEY":
return "你的阿里云百炼 API Key 在这里"
# 后续如果有其他密钥,也可以在这里添加
else:
return None
说明:函数 load_key 的作用就是"根据密钥名称,返回对应的密钥值",比如我们调用 load_key("BAILIAN_API_KEY"),它就会返回我们写的 API Key,这样我们的业务代码里就不用出现密钥了。
2. 基础代码:调用通义千问聊天(LangChain 方式)
先通过 LangChain 调用通义千问,看看基础的聊天效果,再用 LangGraph 封装成 Agent------先懂基础,再学进阶。
python
# 第一步:导入需要的工具(就像我们做饭前,先把锅碗瓢盆拿出来)
# 从 config.py 文件中导入 load_key 函数,用来读取 API Key
from config import load_key
# 从 langchain_community 中导入 ChatTongyi(通义千问的聊天接口)
from langchain_community.chat_models import ChatTongyi
# 第二步:构建通义千问大模型客户端(相当于"打开 AI 的聊天窗口")
llm = ChatTongyi(
model="qwen-plus", # 模型名称,qwen-plus 是通义千问的基础版,免费额度足够用
api_key=load_key("BAILIAN_API_KEY"), # 调用 load_key 函数,读取 API Key(不用自己写密钥)
)
# 第三步:调用大模型,发送问题,获取回答(相当于"给 AI 发消息,等它回复")
# invoke() 方法:发送单次消息,等待 AI 完整回复后再返回
response = llm.invoke("你是谁?能帮我解决什么问题?")
# 第四步:打印 AI 的回复(相当于"把 AI 的回答显示出来")
print("AI 的回复:")
print(response.content)
3. 代码运行流程+中间结果详解
-
运行流程:导入工具 → 初始化大模型(用 API Key 登录) → 发送问题 → 接收回复 → 打印回复;
-
中间结果(运行代码后,会在终端看到以下内容,复制过来供你参考): AI 的回复: 你好!我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我能够帮助你解决各种各样的问题,包括但不限于: - 信息查询:我可以为你提供各种领域的知识和信息,比如科学、技术、文化、历史等。 - 写作辅助:无论是写故事、公文、邮件还是剧本,我都可以提供帮助。 - 逻辑推理:如果你有复杂的逻辑问题或需要分析的情况,我可以尝试帮你理清思路。 - 编程支持:我可以理解并生成多种编程语言的代码,帮助你解决编程中的问题。 - 多语言交流:我支持多种语言,可以帮助你进行跨语言的沟通和翻译。 - 日常对话:如果你想聊天或者分享想法,我也很乐意陪伴你。 如果你有任何具体的需求或问题,随时告诉我,我会尽力提供帮助!
-
关键说明: ① llm 是我们创建的"大模型客户端",后续所有和 AI 聊天、调用工具,都要通过它; ② invoke() 方法是"单次同步调用",就是我们发一条消息,等 AI 完整回复后,我们才能继续操作; ③ response 是 AI 的回复对象,response.content 才是 AI 回复的具体文字(其他属性是元数据,比如 Token 消耗,暂时不用管)。

4. LangGraph 封装聊天 Agent(核心步骤)
LangGraph 可以快速将上面的大模型,封装成一个"Agent"------虽然现在还不能调用工具,但已经具备了 Agent 的基础结构,后续加功能会很方便。
python
# 第一步:导入需要的工具
from config import load_key
from langchain_community.chat_models import ChatTongyi
# 从 langgraph.prebuilt 中导入 create_react_agent(快速创建 Agent 的工具)
from langgraph.prebuilt import create_react_agent
# 第二步:初始化通义千问大模型(和之前一样,只是多了 streaming=True,支持流式输出)
llm1 = ChatTongyi(
model="qwen-plus",
api_key=load_key("BAILIAN_API_KEY"),
streaming=True, # 开启流式输出(就是"打字机效果",AI 逐字回复,不是等完整回复再显示)
)
# 第三步:用 LangGraph 快速创建 Agent(核心代码)
agent = create_react_agent(
model=llm1, # 传入我们初始化好的大模型
tools=[], # 暂时不添加任何工具(所以现在只能聊天,不能干活)
prompt="You are a helpful assistant", # 给 Agent 设定角色:"你是一个乐于助人的助手"
)
# 第四步:调用 Agent,发送问题(和之前调用大模型的方式略有不同)
# Agent 要求传入"结构化消息",格式是 {"messages": [{"role": "user", "content": "问题内容"}]}
# role 表示"角色",user 是我们用户,content 是我们的问题
response = agent.invoke({"messages": [{"role": "user", "content": "你是谁?能帮我解决什么问题?"}]})
# 第五步:打印 Agent 的回复(Agent 的回复是一个字典,我们需要提取里面的消息)
print("Agent 的回复:")
# response["messages"] 是一个列表,里面包含"用户消息"和"AI 消息"
# 我们取最后一个元素(AI 消息),然后打印它的 content(回复内容)
print(response["messages"][-1].content)
5. 代码运行流程+中间结果详解
-
运行流程:导入工具 → 初始化大模型(开启流式) → 创建 Agent(无工具) → 发送结构化消息 → 提取并打印 AI 回复;
-
中间结果(运行后会看到): Agent 的回复: 你好!我是通义千问,阿里巴巴集团旗下的超大规模语言模型。我可以帮助你解决各种问题,包括但不限于: 1. 回答问题:无论是学术问题、生活常识、技术问题还是趣味知识,我都可以提供详细的解答。 2. 创作文字:我可以帮你写故事、公文、邮件、剧本等各类文本。 3. 逻辑推理:我可以进行复杂的逻辑推理和数学计算,帮助你解决难题。 4. 编程:支持多种编程语言,可以帮助你编写代码、调试程序或解释编程概念。 5. 多语言支持:除了中文,我还支持英文、德语、法语、西班牙语等多种语言,满足国际交流需求。 6. 表达观点:可以就某一话题发表见解,参与讨论。 7. 玩游戏:如猜谜语、成语接龙等互动游戏。 如果你有任何需要帮助的地方,随时告诉我!我会尽力为你提供支持和帮助。
-
关键说明: ① create_react_agent 是 LangGraph 提供的"快速创建 Agent"工具,不用我们自己写复杂的 Agent 结构; ② tools=[ ] 表示"当前 Agent 没有任何工具",所以只能聊天,不能做其他操作; ③ Agent 的 invoke() 方法要求传入"结构化消息",这是 Agent 的标准格式,后续添加工具、记忆后,格式不变; ④ response 是一个字典,里面的 "messages" 列表包含了整个对话的历史(用户消息+AI 消息),取最后一个元素就是 AI 的最新回复。

6. Agent 流式输出(打字机效果,更直观)
之前的回复是"等 AI 完整写完再显示",流式输出是"AI 写一个字,就显示一个字",和我们平时聊天的打字机效果一样,更贴近真实对话。
python
# 延续上面的代码,直接调用 agent.stream() 方法实现流式输出
# stream_mode="messages":表示流式输出 AI 的回复(逐字显示)
for chunk in agent.stream(
{"messages": [{"role": "user", "content": "你是谁?能帮我解决什么问题?"}]},
stream_mode="messages"
):
# chunk 是"每一小块回复",我们需要提取里面的 AI 消息内容
# 因为流式输出的结构和 invoke() 不同,我们需要判断 chunk 里的内容
if "agent" in chunk and "messages" in chunk["agent"]:
ai_message = chunk["agent"]["messages"][0]
print(ai_message.content, end="") # end="" 表示不换行,实现逐字显示

7. stream_mode 四种模式详解(必懂,后续会用到)
stream_mode 是流式输出的"模式选择",不同模式对应不同的输出效果,我们用表格清晰区分,后续根据需求选择:
| 模式名称 | 作用 | 适用场景 |
|---|---|---|
| updates | 流式输出"工具调用的每一步",比如 Agent 调用工具前、调用工具后、生成回复前,都会输出中间步骤 | 调试 Agent(看 Agent 是怎么调用工具的) |
| messages | 流式输出 AI 回复的每一个字,就是打字机效果 | 日常聊天,让回复更直观 |
| values | 不流式输出,一次性返回所有完整内容(和 invoke() 效果一样) | 不需要打字机效果,只想快速获取完整回复 |
| custom | 自定义流式输出,比如在工具调用时,自己添加一些日志、提示信息 | 定制化需求(暂时用不到,后续进阶再学) |
说明:后续我们添加工具后,会用到 updates 模式,查看 Agent 调用工具的全过程。
第二节:给 Agent 增加 Tools 工具调用机制(让 Agent 能干活)
现在 Agent 只能聊天,不能做实际的事情(比如查日期、查天气)。这一节我们给它"装上手"------添加 Tools 工具,让它能自主调用工具完成任务。
1. 先搞懂:工具调用的完整流程(能听懂)
在没有 LangGraph 之前,我们用 LangChain 调用工具,需要自己写完整的流程(很麻烦),流程如下:
-
我们自己写一个工具(比如"查日期"的函数);
-
我们把"问题"和"工具的描述"一起发给大模型;
-
大模型判断:这个问题需要调用工具吗?(比如"今天几号"需要调用查日期工具,"你好"不需要);
-
如果需要调用,大模型返回"工具调用指令"(比如"调用 get_current_date 工具");
-
我们自己写代码,解析这个指令,调用对应的工具,获取工具返回的结果;
-
我们再把"工具结果"发给大模型,让大模型生成最终的回答;
-
大模型返回最终回答,我们再展示给用户。
而 LangGraph 的优势的是:它会自动帮我们完成上面所有流程,我们只需要"定义工具",然后把工具交给 Agent,剩下的事情(判断是否调用、调用工具、处理结果)都由 Agent 自己完成,不用我们写复杂的流程代码。
2. 示例1:极简工具------获取当前日期(普通函数定义)
先定义一个最简单的工具:获取今天的日期,然后交给 Agent,看看 Agent 怎么自主调用它。
python
# 第一步:导入需要的工具
from config import load_key
from langchain_community.chat_models import ChatTongyi
from langgraph.prebuilt import create_react_agent
import datetime # 导入 datetime 库,用来获取当前日期(Python 自带,不用额外安装)
# 第二步:定义工具函数(核心!这就是 Agent 能调用的"工具")
def get_current_date():
"""
工具函数:获取今天的日期
注释说明:这个注释很重要,大模型会通过这个注释,知道这个工具是用来做什么的
返回值:今天的日期,格式是"年-月-日"(比如 2026-04-30)
"""
# datetime.datetime.today():获取当前时间
# strftime("%Y-%m-%d"):把时间格式化成"年-月-日"的字符串
return datetime.datetime.today().strftime("%Y-%m-%d")
# 第三步:初始化大模型(和之前一样)
llm = ChatTongyi(
model="qwen-plus",
api_key=load_key("BAILIAN_API_KEY"),
)
# 第四步:创建 Agent,传入工具(关键!把我们定义的工具交给 Agent)
agent = create_react_agent(
model=llm,
tools=[get_current_date], # 把工具函数放进列表,交给 Agent
prompt="You are a helpful assistant",
)
# 第五步:调用 Agent,发送需要用工具的问题
response = agent.invoke({"messages": [{"role": "user", "content": "今天是几月几号"}]})
# 第六步:打印完整的响应(看看 Agent 调用工具的全过程)
print("Agent 完整响应(包含工具调用过程):")
print(response)
print("\n") # 换行,让输出更清晰
# 打印最终的回答(提取 AI 最后的回复)
print("Agent 最终回答:")
print(response["messages"][-1].content)
3. 代码运行流程+中间结果详解
-
运行流程:导入工具 → 定义查日期工具 → 初始化大模型 → 创建 Agent(传入工具) → 发送问题 → Agent 自主调用工具 → 生成最终回答 → 打印结果;
-
中间结果(运行后会看到,重点看工具调用过程): Agent 完整响应(包含工具调用过程): { "messages": [ HumanMessage(content='今天是几月几号', additional_kwargs={}, response_metadata={}, id='xxx'), AIMessage(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'xxx', 'type': 'function', 'function': {'name': 'get_current_date', 'arguments': '{}'}}]}, response_metadata={}, id='xxx', tool_calls=[{'name': 'get_current_date', 'args': {}, 'id': 'xxx', 'type': 'tool_call'}]), ToolMessage(content='2026-05-01', name='get_current_date', id='xxx', tool_call_id='xxx'), AIMessage(content='今天是2026年5月1日。', additional_kwargs={}, response_metadata={}, id='xxx') ] } Agent 最终回答: 今天是2026年5月1日。
-
关键说明(重点!必须懂): ① 工具函数的注释(def get_current_date() 下面的 """...""")非常重要------大模型不知道这个工具是干嘛的,只能通过注释来理解,注释写得越清楚,Agent 越容易判断什么时候调用它; ② 响应中的 4 条消息,对应 Agent 调用工具的 4 个步骤: - HumanMessage:我们用户的问题(今天是几月几号); - AIMessage(带 tool_calls):Agent 判断需要调用工具,返回工具调用指令(调用 get_current_date,无参数); - ToolMessage:工具调用的结果(2026-05-01,就是 get_current_date 函数返回的值); - AIMessage(最后一条):Agent 结合工具结果,生成最终的自然语言回答; ③ 我们没有写任何"判断是否调用工具""解析工具指令"的代码,这些都是 Agent 自动完成的------这就是 LangGraph 的强大之处。

4. 示例2:标准工具------除法计算(@tool 装饰器定义,支持异常处理)
除了普通函数,我们还可以用 LangChain 提供的 @tool 装饰器来定义工具,这种方式更规范,支持自定义工具名称、参数说明,还能处理工具调用时的错误(比如除数为0、除数为1的错误)。
python
# 第一步:导入需要的工具
from config import load_key
from langchain_community.chat_models import ChatTongyi
from langgraph.prebuilt import create_react_agent, ToolNode # 新增 ToolNode,用于处理工具异常
from langchain_core.tools import tool # 导入 @tool 装饰器,用于标准工具定义
# 第二步:用 @tool 装饰器定义工具(标准写法)
@tool("devide_tool", return_direct=True) # ① name="devide_tool":工具名称;② return_direct=True:直接返回工具结果,不经过大模型二次总结
def devide(a: int, b: int) -> float:
"""
工具函数:计算两个整数的除法。
Args: # 参数说明,告诉大模型这个工具需要传入什么参数
a (int): 除数(比如 10)
b (int): 被除数(比如 5)
Returns: # 返回值说明
float: 两个数的商(比如 10/5=2.0)
"""
# 自定义错误:如果被除数 b 等于 1,抛出错误(演示异常处理)
if b == 1:
raise ValueError("除数不能为1") # 抛出 ValueError 错误
# 正常计算除法,返回结果
return a / b
# 第三步:测试工具(可选,可以先看看工具单独调用的效果)
print("工具名称:", devide.name) # 打印工具名称(devide_tool)
print("工具描述:", devide.description) # 打印工具描述(就是函数上面的注释)
print("工具参数:", devide.args) # 打印工具参数(a 和 b,都是整数)
print("测试工具调用:10除以5 =", devide(10, 5)) # 调用工具,输出 2.0
print("\n")
# 第四步:定义工具调用错误处理函数(关键!工具出错时,Agent 不会崩溃,会返回友好提示)
def handle_tool_error(error: Exception) -> str:
"""
工具调用错误处理函数:当工具执行出错时,返回友好的提示信息
参数 error:工具调用时抛出的错误
返回值:友好的错误提示字符串
"""
# 判断错误类型,如果是 ValueError(我们自定义的"除数不能为1")
if isinstance(error, ValueError):
return "除数为1没有意义,请重新输入一个除数和被除数。"
# 如果是 ZeroDivisionError(除数为0的错误,Python 自带的错误)
elif isinstance(error, ZeroDivisionError):
return "除数不能为0,请重新输入一个除数和被除数。"
# 其他未知错误,返回通用提示
return f"工具调用错误:{error}"
# 第五步:用 ToolNode 封装工具和错误处理器(把工具和错误处理绑定在一起)
tool_node = ToolNode(
[devide], # 传入我们定义的工具(可以传入多个工具,放在列表里)
handle_tool_errors=handle_tool_error # 传入错误处理函数
)
# 第六步:初始化大模型,创建 Agent(传入封装好的 tool_node)
llm = ChatTongyi(
model="qwen-plus",
api_key=load_key("BAILIAN_API_KEY"),
)
agent_with_error_handler = create_react_agent(
model=llm,
tools=tool_node # 传入封装好的工具节点(包含工具和错误处理)
)
# 第七步:测试 Agent 调用工具(分3种情况测试,可以分别运行看看效果)
print("测试1:正常调用(10除以5):")
result1 = agent_with_error_handler.invoke({"messages": [{"role": "user", "content": "10除以5等于多少?"}]})
print("结果:", result1["messages"][-1].content)
print("\n")
print("测试2:错误调用(10除以1,触发自定义错误):")
result2 = agent_with_error_handler.invoke({"messages": [{"role": "user", "content": "10除以1等于多少?"}]})
print("结果:", result2["messages"][-1].content)
print("\n")
print("测试3:错误调用(10除以0,触发除数为0错误):")
result3 = agent_with_error_handler.invoke({"messages": [{"role": "user", "content": "10除以0等于多少?"}]})
print("结果:", result3["messages"][-1].content)
5. 代码运行流程+中间结果详解
-
运行流程:导入工具 → 用 @tool 定义除法工具 → 测试工具 → 定义错误处理函数 → 用 ToolNode 封装工具和错误处理 → 初始化大模型 → 创建 Agent → 测试3种调用场景;
-
中间结果(运行后会看到): 工具名称: devide_tool 工具描述: 计算两个整数的除法。 Args: a (int): 除数 b (int): 被除数 工具参数: {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}} 测试工具调用:10除以5 = 2.0 测试1:正常调用(10除以5): 结果: 2.0 测试2:错误调用(10除以1,触发自定义错误): 结果: 除数为1没有意义,请重新输入一个除数和被除数。 测试3:错误调用(10除以0,触发除数为0错误): 结果: 除数不能为0,请重新输入一个除数和被除数。
-
关键说明: ① @tool 装饰器的作用:自动给工具添加"名称、描述、参数说明",让大模型更清晰地了解工具的用法;return_direct=True 表示"工具执行完成后,直接返回结果,不用大模型再加工"(比如10除以5,直接返回2.0,不用大模型说"10除以5的结果是2.0"); ② ToolNode 的作用:将工具和错误处理函数绑定在一起,这样当工具调用出错时,Agent 会自动调用 handle_tool_error 函数,返回友好提示,而不是直接崩溃; ③ 3种测试场景的意义: - 正常调用:Agent 正确调用工具,返回计算结果; - 自定义错误(除数为1):工具抛出 ValueError,错误处理函数捕获,返回自定义提示; - 系统错误(除数为0):工具抛出 ZeroDivisionError,错误处理函数捕获,返回对应提示; ④ 可以尝试修改问题,比如"20除以4等于多少""5除以0等于多少",看看 Agent 的响应。

第三节:给 Agent 增加消息记忆管理功能(让 Agent 能记住聊天内容)
现在 Agent 能聊天、能调用工具,但有一个问题:它记不住之前的聊天内容。比如你先问"长沙天气怎么样",再问"北京呢",它会不知道"北京呢"指的是"北京天气怎么样"------这一节我们给 Agent "装上记忆",让它能记住多轮对话。
LangGraph 将记忆分为两种:短期记忆 和长期记忆,就像我们人类的"短期记忆"(记最近几分钟的事)和"长期记忆"(记几天、几年的事),两者的作用和用法不同,我们分别讲解。
一、短期记忆(CheckPoint)------ 会话级记忆(记当前聊天的内容)
短期记忆是"当前会话的记忆",比如你和 Agent 聊的这一轮对话,它会记住你之前说的每一句话、调用的每一个工具------就像我们和朋友聊天,聊的过程中能记住对方上一句说的话。
特点:默认保存在电脑内存中,程序关闭后,记忆就消失了(比如你关闭 VS Code,再重新运行代码,Agent 就不记得之前的聊天内容了);内存有限,聊天内容太多时,需要清理。
1. 短期记忆实战:记住多轮对话(查天气案例)
python
# 第一步:导入需要的工具
from config import load_key
from langchain_community.chat_models import ChatTongyi
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import InMemorySaver # 导入短期记忆存储工具(InMemorySaver:内存存储)
# 第二步:定义工具(查天气工具,和之前的查日期工具类似)
def get_weather(city: str) -> str:
"""
工具函数:获取某个城市的天气
Args:
city (str): 城市名称(比如"长沙""北京")
Returns:
str: 城市的天气信息
"""
# 这里我们模拟天气返回(实际开发中,可以对接真实的天气API,暂时用模拟数据)
return f"城市:{city},天气一直都是晴天!"
# 第三步:初始化短期记忆存储(InMemorySaver,保存在内存中)
checkpointer = InMemorySaver() # 这个对象就是"短期记忆容器"
# 第四步:初始化大模型,创建 Agent(传入短期记忆 checkpointer)
llm = ChatTongyi(
model="qwen-plus",
api_key=load_key("BAILIAN_API_KEY"),
)
agent = create_react_agent(
model=llm,
tools=[get_weather], # 传入查天气工具
checkpointer=checkpointer # 传入短期记忆,开启记忆功能
)
# 第五步:定义会话配置(关键!用 thread_id 区分不同的对话)
# thread_id 相当于"聊天窗口ID",不同的 thread_id 对应不同的对话,记忆互不干扰
# 比如 thread_id="1" 是一个聊天窗口,thread_id="2" 是另一个聊天窗口,Agent 不会混淆
config = {
"configurable": {
"thread_id": "1" # 自定义会话ID,任意字符串都可以(比如"user1""chat1")
}
}
# 第六步:第一次调用 Agent(问长沙天气)
print("第一次对话:")
cs_response = agent.invoke(
{"messages": [{"role": "user", "content": "长沙天气怎么样?"}]},
config # 传入会话配置,让 Agent 记住这个会话的内容
)
# 打印第一次对话的结果
print("Agent 回复:", cs_response["messages"][-1].content)
print("\n")
# 第七步:第二次调用 Agent(问北京天气,不用重复说"北京天气怎么样",Agent 会记住上下文)
print("第二次对话:")
bj_response = agent.invoke(
{"messages": [{"role": "user", "content": "北京呢?"}]}, # 只说"北京呢",Agent 会联想到"北京天气"
config # 必须传入同一个 thread_id,才能复用之前的记忆
)
# 打印第二次对话的结果(包含完整的对话历史)
print("完整对话历史:")
for msg in bj_response["messages"]:
# 判断消息角色,区分用户和 Agent
if hasattr(msg, "role") and msg.role == "user":
print(f"用户:{msg.content}")
else:
print(f"Agent:{msg.content}")
print("\n")
print("Agent 最终回复:", bj_response["messages"][-1].content)
2. 代码运行流程+中间结果详解
-
运行流程:导入工具 → 定义查天气工具 → 初始化短期记忆 → 初始化大模型 → 创建 Agent(传入记忆) → 定义会话配置(thread_id) → 第一次对话(查长沙天气) → 第二次对话(查北京天气,复用记忆) → 打印结果;
-
中间结果(运行后会看到,重点看 Agent 如何记住上下文): 第一次对话: Agent 回复: 长沙的天气一直都是晴天! 第二次对话: 完整对话历史: 用户:长沙天气怎么样? Agent: Agent: 长沙的天气一直都是晴天! 用户:北京呢? Agent: Agent: 北京的天气也一直都是晴天! Agent 最终回复: 北京的天气也一直都是晴天!
-
关键说明(必懂): ① InMemorySaver 是 LangGraph 提供的"短期记忆存储工具",它把记忆保存在电脑内存中,程序关闭后就会消失(生产环境中,我们会用 Redis、数据库等方式保存,暂时用内存存储即可); ② thread_id 是"会话ID",必须传入同一个 thread_id,Agent 才能记住之前的对话------如果换一个 thread_id(比如改成"2"),Agent 就会当成新的对话,不记得之前的内容; ③ 第二次对话中,我们只说"北京呢",Agent 能记住上一句问的是"天气",所以会调用查天气工具查询北京的天气,这就是短期记忆的作用; ④ 完整对话历史中,有两个空的 Agent 消息,是 Agent 调用工具时的中间步骤(工具调用指令),可以忽略,重点看有内容的回复。

3. 短期记忆优化:解决"聊天内容太多、内存不够"的问题
短期记忆保存在内存中,内存有限,如果和 Agent 聊了很多轮,对话历史太长,会导致内存占用过高,甚至出现程序卡顿、崩溃的情况。不用慌,我们有两种简单的优化方法,不用写复杂代码,直接套用即可。
-
中间结果(运行后会看到): 第一次运行程序(创建记忆): 已创建新的长期记忆存储! Agent 回复: 长沙的天气一直都是晴天! 第二次运行程序(加载记忆): 已加载之前的长期记忆! Agent 回复: 北京的天气也一直都是晴天! 长期记忆中的所有内容: 记忆1: 用户:长沙天气怎么样? Agent: Agent: 长沙的天气一直都是晴天! 记忆2: 用户:长沙天气怎么样? Agent: Agent: 长沙的天气一直都是晴天! 用户:北京呢? Agent: Agent: 北京的天气也一直都是晴天!
-
关键说明(必懂): ① 第一次运行程序时,会在当前文件夹下创建"agent_memory"文件夹,里面保存着长期记忆的文件;第二次运行时,会自动读取这个文件夹中的记忆,不用重新提问,Agent 就能记住之前的对话; ② 嵌入工具(TongyiEmbeddings)的作用:将聊天内容转换成"向量"(计算机能识别的格式),这样才能保存到 FAISS 中,后续查询时,能快速找到和当前问题相关的记忆; ③ save_memory_to_vectorstore 函数:将每次的聊天记录保存到长期记忆中;load_memory_from_vectorstore 函数:根据当前问题,从长期记忆中读取相关的内容,让 Agent 能关联之前的对话; ④ 长期记忆和短期记忆的区别:短期记忆记"当前会话的近期内容",长期记忆记"跨会话的所有内容",两者结合,Agent 的记忆功能会更完善。
第四节:给 Agent 增加人工监督功能(让 Agent 可控)
现在 Agent 能聊天、能调用工具、能记住内容,但还有一个隐患:Agent 会自主执行所有操作,比如如果我们给它添加了"删除文件""发送邮件"等危险工具,它可能会误操作,造成损失。这一节我们给 Agent 增加"人工监督"功能------让 Agent 在执行关键操作前,先停下来,等我们确认后再继续,确保 Agent 可控。
1. 人工监督核心逻辑(能听懂)
核心思路:给 Agent 设定"关键操作清单"(比如删除文件、调用付费工具、发送信息等),当 Agent 要调用这些关键工具时,不会直接执行,而是先向我们"请示",我们输入"确认",Agent 才会执行;输入"取消",Agent 就会停止操
作,返回提示。
LangGraph 提供了"HumanInTheLoop"(人工介入)工具,不用我们自己写复杂的请示逻辑,直接套用即可,也能轻松实现。
2. 实战:关键工具人工监督(删除文件工具为例)
我们以"删除文件"这个危险工具为例,实现人工监督------Agent 要删除文件时,必须先得到我们的确认,才能执行删除操作。
python
# 第一步:导入需要的工具(新增人工监督相关工具)
from config import load_key
from langchain_community.chat_models import ChatTongyi
from langgraph.prebuilt import create_react_agent, ToolNode
from langchain_core.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
# 新增:人工监督工具
from langgraph.prebuilt import HumanInTheLoop
# 第二步:定义关键工具(删除文件工具,危险操作,需要人工监督)
@tool("delete_file_tool", return_direct=True)
def delete_file(file_path: str) -> str:
"""
工具函数:删除指定路径的文件(危险操作,需要人工确认)
Args:
file_path (str): 文件路径(比如 "./test.txt")
Returns:
str: 删除成功或失败的提示
"""
import os
# 判断文件是否存在
if os.path.exists(file_path):
os.remove(file_path) # 删除文件
return f"文件 {file_path} 已成功删除!"
else:
return f"文件 {file_path} 不存在,删除失败!"
# 第三步:定义工具错误处理函数(和之前一致)
def handle_tool_error(error: Exception) -> str:
return f"工具调用错误:{error}"
# 第四步:封装工具和错误处理
tool_node = ToolNode(
[delete_file],
handle_tool_errors=handle_tool_error
)
# 第五步:初始化人工监督(核心步骤)
# 定义"需要人工确认的工具清单":只有 delete_file_tool 需要人工确认
human_in_the_loop = HumanInTheLoop(
tools=["delete_file_tool"], # 关键工具清单
prompt="请确认是否执行以下操作:{tool_call},输入「确认」执行,输入「取消」停止操作:" # 请示提示语
)
# 第六步:初始化大模型、短期记忆
llm = ChatTongyi(
model="qwen-plus",
api_key=load_key("BAILIAN_API_KEY"),
)
checkpointer = InMemorySaver()
# 第七步:创建 Agent(结合人工监督、工具、记忆)
agent = create_react_agent(
model=llm,
tools=tool_node,
checkpointer=checkpointer,
human_in_the_loop=human_in_the_loop # 传入人工监督对象
)
# 第八步:测试人工监督功能
config = {"configurable": {"thread_id": "1"}}
# 发送问题:让 Agent 删除当前文件夹下的 test.txt 文件(先手动创建这个文件,方便测试)
response = agent.invoke(
{"messages": [{"role": "user", "content": "删除当前文件夹下的 test.txt 文件"}]},
config
)
# 打印 Agent 的请示信息和最终结果
print("Agent 请示:", response["messages"][-1].content)
# 手动输入确认/取消(运行时,会在终端看到提示,输入后按回车)
user_confirm = input("请输入确认/取消:")
# 将人工确认结果传入 Agent,继续执行
if user_confirm == "确认":
# 确认执行,Agent 调用删除文件工具
final_response = agent.invoke(
{"messages": [{"role": "user", "content": user_confirm}]},
config
)
print("最终结果:", final_response["messages"][-1].content)
else:
# 取消执行,Agent 返回停止提示
final_response = agent.invoke(
{"messages": [{"role": "user", "content": user_confirm}]},
config
)
print("最终结果:", final_response["messages"][-1].content)
3. 代码运行流程+中间结果详解
-
运行流程:导入工具 → 定义危险工具(删除文件) → 封装工具和错误处理 → 初始化人工监督 → 初始化大模型和记忆 → 创建 Agent → 测试人工监督(请示→确认→执行);
-
中间结果(运行后会看到): Agent 请示: 请确认是否执行以下操作:调用 delete_file_tool 工具,参数为 {'file_path': './test.txt'},输入「确认」执行,输入「取消」停止操作: 请输入确认/取消:确认(手动输入) 最终结果: 文件 ./test.txt 已成功删除! 如果输入"取消",则最终结果: 已取消执行删除文件操作。
-
关键说明(必懂): ① HumanInTheLoop 是 LangGraph 提供的人工监督工具,只需传入"需要监督的工具清单",就能实现请示逻辑,不用自己写判断代码; ② prompt 参数是请示提示语,可以修改成自己习惯的表述,比如"是否执行删除操作?确认请输入Y,取消请输入N:"; ③ 只有清单中的工具(这里是 delete_file_tool)会触发人工监督,其他工具(比如之前的查天气、计算除法)会正常自主执行,不影响效率; ④ 测试时,先手动在当前文件夹下创建"test.txt"文件,否则会提示"文件不存在",影响测试效果。
4. 人工监督优化:批量确认(高效处理多个关键操作)
如果 Agent 要连续执行多个关键操作(比如删除多个文件),每次都请示一次,会很繁琐。我们可以设置"批量确认",让 Agent 一次性列出所有要执行的关键操作,我们一次确认即可,代码修改如下(修改 HumanInTheLoop 的 prompt):
python
# 初始化人工监督(批量确认版本)
human_in_the_loop = HumanInTheLoop(
tools=["delete_file_tool"],
# 批量确认提示语:列出所有要执行的操作,一次确认
prompt="以下是需要执行的关键操作,请批量确认:\n{tool_calls}\n输入「确认」执行所有操作,输入「取消」停止所有操作:"
)
# 测试批量操作:让 Agent 删除两个文件
response = agent.invoke(
{"messages": [{"role": "user", "content": "删除当前文件夹下的 test1.txt 和 test2.txt 文件"}]},
config
)
print("Agent 批量请示:", response["messages"][-1].content)
user_confirm = input("请输入确认/取消:")
# 后续执行逻辑和之前一致
中间结果:Agent 会一次性列出两个删除操作,我们输入"确认",就会连续删除两个文件,不用分别请示,提升效率。
第三章:完整功能 Agent 整合(实战,直接套用)
到这里,我们已经给 Agent 加上了"聊天、工具调用、短期+长期记忆、人工监督"所有核心功能。这一章我们将所有功能整合起来,实现一个完整的、可直接套用的 Agent,只需复制代码、替换 API Key 和工具,就能直接使用。
第一节:完整代码
python
# 完整功能 Agent:聊天+工具调用+短期+长期记忆+人工监督
# 只需替换 API Key 和工具,即可直接运行
# 第一步:导入所有需要的工具
from config import load_key
from langchain_community.chat_models import ChatTongyi
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import TongyiEmbeddings
from langgraph.prebuilt import create_react_agent, ToolNode, HumanInTheLoop, InMemorySaver
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage, AIMessage
import os
import datetime
# 第二步:定义工具(可根据需求修改/新增工具)
# 工具1:查日期(普通工具)
def get_current_date():
"""工具函数:获取今天的日期,格式:年-月-日"""
return datetime.datetime.today().strftime("%Y-%m-%d")
# 工具2:除法计算(标准工具,带异常处理)
@tool("devide_tool", return_direct=True)
def devide(a: int, b: int) -> float:
"""工具函数:计算两个整数的除法,a是除数,b是被除数"""
if b == 1:
raise ValueError("除数不能为1")
return a / b
# 工具3:删除文件(关键工具,需要人工监督)
@tool("delete_file_tool", return_direct=True)
def delete_file(file_path: str) -> str:
"""工具函数:删除指定路径的文件(危险操作,需要人工确认)"""
if os.path.exists(file_path):
os.remove(file_path)
return f"文件 {file_path} 已删除!"
else:
return f"文件 {file_path} 不存在!"
# 第三步:工具错误处理
def handle_tool_error(error: Exception) -> str:
if isinstance(error, ValueError):
return error.args[0]
elif isinstance(error, ZeroDivisionError):
return "除数不能为0!"
else:
return f"工具调用错误:{error}"
# 第四步:封装工具和错误处理
tool_node = ToolNode(
[get_current_date, devide, delete_file], # 所有工具放在列表中
handle_tool_errors=handle_tool_error
)
# 第五步:初始化人工监督(关键工具清单)
human_in_the_loop = HumanInTheLoop(
tools=["delete_file_tool"], # 只有删除文件需要人工确认
prompt="请确认是否执行以下操作:{tool_call}\n输入「确认」执行,「取消」停止:"
)
# 第六步:初始化长期记忆(FAISS 本地存储)
memory_path = "./agent_complete_memory"
embeddings = TongyiEmbeddings(
api_key=load_key("BAILIAN_API_KEY"),
model_name="text-embedding-v1"
)
# 读取/创建长期记忆
if os.path.exists(memory_path):
vector_store = FAISS.load_local(memory_path, embeddings, allow_dangerous_deserialization=True)
else:
vector_store = FAISS.from_texts([""], embeddings)
vector_store.save_local(memory_path)
# 长期记忆保存/读取函数(带去重)
def save_memory(messages):
memory_text = ""
for msg in messages:
if hasattr(msg, "role") and msg.role == "user":
memory_text += f"用户:{msg.content}\n"
else:
memory_text += f"AI:{msg.content}\n"
# 去重逻辑
existing_docs = vector_store.similarity_search(memory_text, k=1)
if not existing_docs or existing_docs[0].similarity < 0.9:
vector_store.add_texts([memory_text])
vector_store.save_local(memory_path)
def load_memory(query):
docs = vector_store.similarity_search(query, k=3)
memory_content = ""
for doc in docs:
memory_content += doc.page_content + "\n"
return memory_content
# 第七步:初始化短期记忆(限制长度为5轮)
checkpointer = InMemorySaver()
from langgraph.prebuilt import MessageHistory
message_history = MessageHistory(max_length=5)
# 第八步:初始化大模型,创建完整 Agent
llm = ChatTongyi(
model="qwen-plus",
api_key=load_key("BAILIAN_API_KEY"),
streaming=True # 开启流式输出(打字机效果)
)
agent = create_react_agent(
model=llm,
tools=tool_node,
checkpointer=checkpointer,
message_history=message_history,
human_in_the_loop=human_in_the_loop,
prompt=f"You are a helpful assistant. Use the following long-term memory to answer: {load_memory('{user_query}')}"
)
# 第九步:测试完整 Agent(多场景测试)
config = {"configurable": {"thread_id": "1"}}
# 测试1:查日期(自主执行,无需监督)
print("测试1:查日期")
response1 = agent.invoke({"messages": [{"role": "user", "content": "今天几号?"}]}, config)
print("Agent 回复:", response1["messages"][-1].content)
save_memory(response1["messages"])
print("\n")
# 测试2:除法计算(自主执行,带异常处理)
print("测试2:除法计算")
response2 = agent.invoke({"messages": [{"role": "user", "content": "15除以3等于多少?"}]}, config)
print("Agent 回复:", response2["messages"][-1].content)
save_memory(response2["messages"])
print("\n")
# 测试3:删除文件(需要人工监督)
print("测试3:删除文件")
response3 = agent.invoke({"messages": [{"role": "user", "content": "删除当前文件夹下的 test.txt 文件"}]}, config)
print("Agent 请示:", response3["messages"][-1].content)
user_confirm = input("请输入确认/取消:")
response3_final = agent.invoke({"messages": [{"role": "user", "content": user_confirm}]}, config)
print("最终结果:", response3_final["messages"][-1].content)
save_memory(response3_final["messages"])
print("\n")
# 测试4:多轮对话(记忆功能)
print("测试4:多轮对话(记忆)")
response4 = agent.invoke({"messages": [{"role": "user", "content": "我刚才问的日期是多少?"}]}, config)
print("Agent 回复:", response4["messages"][-1].content)
save_memory(response4["messages"])
# 测试5:关闭程序后重新运行,测试长期记忆(需手动重新运行程序,执行以下代码)
# print("测试5:长期记忆")
# response5 = agent.invoke({"messages": [{"role": "user", "content": "我刚才问的除法题答案是多少?"}]}, config)
# print("Agent 回复:", response5["messages"][-1].content)修改工具:根据自己的需求,新增/删除工具------新增工具时,要么用普通函数(带详细注释),要么用 @tool 装饰器(标准写法),然后添加到 tool_node 的工具列表中;
第二节:代码使用说明(必看)
-
替换 API Key:打开 config.py 文件,将"你的阿里云百炼 API Key 在这里"替换成自己的 API Key(获取方法见前置知识);
-
运行测试:先创建 config.py 文件,再复制上面的完整代码,保存为"agent_complete.py",点击运行即可,测试时记得手动创建 test.txt 文件(用于删除测试);
-
调整参数: ① 短期记忆长度:修改 message_history = MessageHistory(max_length=5) 中的 max_length,数字越大,记住的对话越多; ② 长期记忆去重:修改 save_memory 函数中的 similarity< 0.9,数值越接近1,去重越严格; ③ 人工监督工具:修改 human_in_the_loop 中的 tools 列表,添加需要监督的工具名称;
第四章:常见问题汇总(避坑指南)
- 常见问题: ① 运行报错"API Key 错误":检查 config.py 中的 API Key 是否正确,是否泄露; ② 长期记忆无法加载:检查 memory_path 路径是否正确,是否有读写权限; ③ 工具调用失败:检查工具函数的注释是否详细,参数是否正确(比如删除文件的路径是否正确)。
一、环境安装问题
- 问题1:安装 Python 后,输入"python --version"提示"不是内部或外部命令" 解决方法:重新安装 Python,一定要勾选"Add Python 3.10 to PATH",安装完成后重启 VS Code 和终端。
学习过程中,很容易遇到一些常见问题,这里汇总了高频问题和解决方法,不用上网查,直接对照解决即可。
-
问题3:安装依赖库时,提示"超时""下载失败" 解决方法:使用国内镜像源安装,将安装命令修改为:pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple 示例:pip install langgraph -i https://pypi.tuna.tsinghua.edu.cn/simple
-
问题2:安装依赖库时,提示"pip 不是内部或外部命令" 解决方法:和上面一样,重新安装 Python 并勾选"Add to PATH",或者手动配置环境变量(推荐重新安装,更简单)。
-
问题1:运行代码时,提示"API Key 无效" 解决方法:检查 config.py 中的 API Key 是否正确,是否有空格;登录阿里云百炼官网,确认 API Key 没有过期、没有被禁用。
二、代码运行问题
-
问题3:短期记忆不起作用,Agent 记不住上一轮对话 解决方法:确认创建 Agent 时,已经传入了 checkpointer(短期记忆)和 message_history(记忆长度限制);调用 Agent 时,必须传入同一个 thread_id,否则会当成新的会话。
-
问题2:Agent 不调用工具,直接返回回答 解决方法:检查工具函数的注释是否详细------大模型只能通过注释了解工具的作用,注释写得越清楚,Agent 越容易判断何时调用;另外,确保工具已经添加到 tool_node 的工具列表中。
-
问题5:人工监督不起作用,Agent 直接执行关键工具 解决方法:确认 HumanInTheLoop 已经传入 Agent,且 tools 列表中包含了需要监督的工具名称(工具名称必须和 @tool 装饰器中的 name 一致,比如"delete_file_tool")。
-
问题4:长期记忆无法保存/加载 解决方法:检查 memory_path 路径是否正确,确保当前文件夹有读写权限;确认 FAISS 和 TongyiEmbeddings 已经安装(pip list 查看是否有这两个库)。
-
问题1:短期记忆和长期记忆的区别,什么时候用哪个? 解答:短期记忆记"当前会话的近期内容",程序关闭后消失,适合单次会话中的多轮对话;长期记忆记"跨会话的内容",持久化存储,适合需要长期记住的信息(比如用户的偏好、历史操作)。
三、逻辑理解问题
-
问题3:Agent 的运行流程是什么? 解答:接收用户问题 → 读取短期+长期记忆 → 判断是否需要调用工具 → 如果是关键工具,请示人工确认 → 调用工具获取结果 → 结合记忆和工具结果,生成回答 → 保存记忆。
-
问题2:为什么工具函数的注释很重要? 解答:大模型不知道工具的具体功能,只能通过注释来理解------注释写得越详细(包括工具作用、参数、返回值),Agent 越能准确判断"什么时候需要调用这个工具",避免误调用或不调用。
掌握了基础的 Agent 构建后,可以逐步学习以下进阶内容,让 Agent 功能更强大,适配更多场景。
第五章:进阶方向
-
自定义工具:对接真实的 API(比如天气 API、新闻 API、邮件 API),让 Agent 能获取实时数据,实现更实用的功能;
-
多 Agent 协同:用 LangGraph Supervisor 实现多个 Agent 分工协作(比如一个 Agent 负责查询信息,一个 Agent 负责处理数据,一个 Agent 负责生成回答);
-
界面开发:用 Streamlit、Flask 等框架,给 Agent 做一个简单的网页界面,不用运行代码,直接在网页上和 Agent 交互;
-
记忆优化:用 Redis、MySQL 等数据库替代 FAISS,实现更高效的记忆存储和查询,适合大量数据场景;