LangChain Agent 入门实战:从报错到跑通带记忆的交互式智能体(初学者保姆级教程)

LangChain Agent 入门实战:从报错到跑通带记忆的交互式智能体(初学者保姆级教程)

作者:风吹夏回
适合人群:零基础接触 LangChain Agent 的初学者,全程附可运行代码 + 踩坑解决方案

写在前面

大家好,我是风吹夏回。今天正式开始学习 LangChain 中的 Agent 智能体,从最开始的配置报错、无输出,一步步踩坑调试,最终跑通了带记忆能力的交互式对话 Agent

这篇文章完全以初学者视角记录整个学习过程,所有代码都经过实测可直接运行,同时把我踩过的坑全部标注了出来,大家跟着抄代码就能复现效果,不用再走弯路。

本次学习使用的技术栈:

  • 大模型:火山方舟豆包doubao-seed-2.0-lite
  • 框架:LangChain + LangGraph
  • 运行环境:Python 虚拟环境 + Windows 系统

一、前置准备:环境与依赖

先把基础环境搭好,建议全程用虚拟环境,避免依赖冲突。

1. 安装核心依赖包

pipinstalllangchain langchain-openai langchain-core langgraph python-dotenv

2. 配置 .env 文件

在项目根目录新建.env文件,填入你的模型配置:

# 你的火山方舟API密钥 DEEPSEEK_API_KEY=ark-你的密钥 # 注意!必须是标准大模型接口,不能用coding接口 DEEPSEEK_BASE_URL=https://ark.cn-beijing.volces.com/api/v3

⚠️ 第一个坑预警:火山方舟的api/coding/v3是代码专属接口,不支持工具调用(Function Calling),一定要用/api/v3标准路径,否则Agent会没有任何输出。


二、第一阶段:第一个Agent的诞生

最开始我直接照着教程写,一运行就报错,先带大家把坑踩完,再跑通最简版本。

踩坑1:TavilySearch 密钥缺失报错

最开始的代码里加了 Tavily 搜索工具,运行直接报 Pydantic 校验错误:

ValidationError: Did not find tavily_api_key, please add an environment variable `TAVILY_API_KEY`

原因:Tavily 是第三方联网搜索工具,必须单独注册申请密钥。
初学者解决方案:先不用第三方工具,用自定义的本地工具先把 Agent 主流程跑通,获得正反馈最重要。

最简可运行 Agent 完整代码

我们先实现一个「天气查询工具」,让 Agent 自主判断什么时候调用它。

fromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromdotenvimportload_dotenv,find_dotenvimportos# 加载环境变量dotenv_path=find_dotenv()load_dotenv(dotenv_path,override=True)api_key=os.getenv("DEEPSEEK_API_KEY")base_url=os.getenv("DEEPSEEK_BASE_URL")# 1. 初始化大模型llm=ChatOpenAI(model="doubao-seed-2.0-lite",api_key=api_key,base_url=base_url,temperature=0.7,)# 2. 定义自定义工具:天气查询@tooldefget_weather(city:str)->str:"""查询指定城市的实时天气情况,输入为城市名称,如北京、上海"""returnf"{city}今日天气:晴转多云,24-31℃,东南风2级"# 工具列表tools=[get_weather]# 3. 创建 Agentagent=create_agent(model=llm,tools=tools,system_prompt="你是一个智能助手,请根据用户的需求调用合适的工具来帮助他们。",)if__name__=="__main__":print("开始测试Agent...")# 一次性调用,查看完整执行链路result=agent.invoke({"messages":[{"role":"user","content":"北京今天天气怎么样?"}]})print("\n=== 完整执行链路 ===")formsginresult["messages"]:print(f"[{msg.type}]:{msg.content}")ifhasattr(msg,"tool_calls")andmsg.tool_calls:print(f" 工具调用:{msg.tool_calls}")

运行后你会看到

输出会清晰展示 Agent 的完整工作循环:

  1. user:用户提问
  2. ai:模型推理,决定调用get_weather工具,参数为北京
  3. tool:工具执行,返回天气结果
  4. ai:模型根据工具结果,生成自然语言最终回答

这就是 Agent 最核心的「感知→推理→行动→回复」循环,全程没有我们手动控制流程,完全是模型自主决策。


三、第二阶段:给Agent加上记忆

跑通基础版后你会发现:每次调用都是“失忆”的,上一轮说过的话下一轮就忘了。这显然不符合真实使用场景,接下来我们给 Agent 加上记忆能力。

核心概念

  • Checkpointer:记忆存储器,自动保存每一轮的对话消息
  • Thread ID:会话标识,同一个ID对应同一份记忆,不同ID完全隔离,用来区分不同用户

带记忆的 Agent 完整代码

只需要在之前的代码上新增3行核心代码即可:

fromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromdotenvimportload_dotenv,find_dotenvimportos# 新增:导入内存存储器fromlanggraph.checkpoint.memoryimportInMemorySaver dotenv_path=find_dotenv()load_dotenv(dotenv_path,override=True)api_key=os.getenv("DEEPSEEK_API_KEY")base_url=os.getenv("DEEPSEEK_BASE_URL")llm=ChatOpenAI(model="doubao-seed-2.0-lite",api_key=api_key,base_url=base_url,temperature=0.7,)@tooldefget_weather(city:str)->str:"""查询指定城市的实时天气情况,输入为城市名称,如北京、上海"""returnf"{city}今日天气:晴转多云,24-31℃,东南风2级"tools=[get_weather]# 新增:创建记忆存储器checkpointer=InMemorySaver()agent=create_agent(model=llm,tools=tools,system_prompt="你是一个智能助手,请根据用户的需求调用合适的工具来帮助他们。",# 新增:传入记忆存储器checkpointer=checkpointer,)if__name__=="__main__":# 同一个 thread_id 代表同一场对话config={"configurable":{"thread_id":"user_001"}}print("="*50)print("第1轮对话")print("="*50)result1=agent.invoke({"messages":[{"role":"user","content":"你好,我叫小明,在北京"}]},config=config)print("AI回复:",result1["messages"][-1].content)print("\n"+"="*50)print("第2轮对话(相同thread_id,有记忆)")print("="*50)result2=agent.invoke({"messages":[{"role":"user","content":"我叫什么名字?我所在的城市今天天气怎么样?"}]},config=config)print("AI回复:",result2["messages"][-1].content)print("\n"+"="*50)print("第3轮对话(换thread_id,无记忆)")print("="*50)result3=agent.invoke({"messages":[{"role":"user","content":"我叫什么名字?"}]},config={"configurable":{"thread_id":"user_002"}})print("AI回复:",result3["messages"][-1].content)

效果验证

  • 第2轮:Agent能准确说出你的名字,并且自动调用天气工具查询北京天气 → 记忆生效
  • 第3轮:更换 Thread ID 后,Agent表示不知道你的名字 → 会话完全隔离

💡 小提示:InMemorySaver是内存存储,程序重启后记忆会清空,适合开发调试。生产环境可以换成SqliteSaverRedisSaver做持久化存储。


四、第三阶段:升级交互式对话

到这里功能都跑通了,但每次都要改代码输入问题太麻烦。我们把它改造成实时聊天模式,像跟微信聊天一样和 Agent 对话,体验感直接拉满。

交互式对话完整代码

输入退出exit即可结束程序,全程保留记忆,还能看到 Agent 的思考和工具调用过程。

fromlangchain.agentsimportcreate_agentfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromdotenvimportload_dotenv,find_dotenvimportosfromlanggraph.checkpoint.memoryimportInMemorySaver# 加载环境变量dotenv_path=find_dotenv()load_dotenv(dotenv_path,override=True)api_key=os.getenv("DEEPSEEK_API_KEY")base_url=os.getenv("DEEPSEEK_BASE_URL")# 初始化大模型llm=ChatOpenAI(model="doubao-seed-2.0-lite",api_key=api_key,base_url=base_url,temperature=0.7,)# 自定义工具@tooldefget_weather(city:str)->str:"""查询指定城市的实时天气情况,输入为城市名称,如北京、上海"""returnf"{city}今日天气:晴转多云,24-31℃,东南风2级"tools=[get_weather]# 记忆配置:固定会话ID,全程保留记忆checkpointer=InMemorySaver()config={"configurable":{"thread_id":"chat_session_001"}}# 创建 Agentagent=create_agent(model=llm,tools=tools,system_prompt="你是一个智能助手,请根据用户的需求调用合适的工具来帮助他们。",checkpointer=checkpointer,)# 交互式对话主程序if__name__=="__main__":print("="*60)print("🤖 Agent 交互式对话已启动")print("💡 输入问题即可对话,输入 退出/exit/quit 结束")print("="*60+"\n")whileTrue:# 获取用户输入user_input=input("👤 你:").strip()# 退出判断ifuser_input.lower()in["退出","exit","quit"]:print("\n👋 对话已结束,再见!")break# 空输入跳过ifnotuser_input:continueprint("-"*60)# 流式执行,展示完整过程forstep_index,stepinenumerate(agent.stream({"messages":[{"role":"user","content":user_input}]},config=config),start=1):# 兼容不同版本的返回结构messages=step.get("messages",[])ifnotmessages:forkeyinstep:ifisinstance(step[key],dict)and"messages"instep[key]:messages=step[key]["messages"]breakifnotmessages:continuelast_msg=messages[-1]# 模型决定调用工具iflast_msg.type=="ai"andlast_msg.tool_calls:print(f"🧠 [思考中] 决定调用工具:")fortool_callinlast_msg.tool_calls:print(f" └─ 工具:{tool_call['name']},参数:{tool_call['args']}")# 工具执行返回结果eliflast_msg.type=="tool":print(f"🔧 [工具执行] 返回结果:{last_msg.content}")# 最终回复eliflast_msg.type=="ai"andnotlast_msg.tool_calls:print(f"\n🤖 Agent:{last_msg.content}")print("-"*60+"\n")

推荐体验流程

大家可以按这个顺序测试,完整感受记忆 + 工具调用的能力:

  1. 第一轮输入:我叫小明,我在长沙
  2. 第二轮输入:我叫什么名字?
  3. 第三轮输入:我所在的城市今天天气怎么样?
  4. 第四轮输入:刚才我们聊了什么?

五、今天踩过的坑总结

作为初学者,这几个坑非常容易踩,特意整理出来帮大家避坑:

报错/问题原因解决方案
TavilySearch 报 value_error 缺少密钥没有配置 Tavily 的 API Key初学者先移除第三方工具,用自定义工具先跑通主流程
程序正常退出但没有任何输出用了 coding 专属接口,不支持工具调用把 base_url 改成标准路径/api/v3
记忆不生效调用时没传 config 和 thread_id每次 invoke/stream 都必须传入带 thread_id 的 config
流式输出什么都不打印返回结构和判断条件不匹配先打印原始 step 的键名,再适配结构

六、下一步学习规划

今天把 Agent 的核心基础都跑通了,接下来的学习路线:

  1. 消息压缩中间件:解决长对话 Token 膨胀的问题
  2. 人工审核中间件:给高风险操作加上人类确认环节
  3. MCP 协议:标准化接入第三方工具服务
  4. 综合项目:做一个完整的智能客服 Agent

后续我会继续更新学习笔记,把每一步的实战代码和踩坑记录都分享出来。


最后

作为初学者,学习 Agent 不用一开始就堆很多功能,先跑通最小 Demo,理解核心的「自主决策循环」,再一步步加能力,是最稳妥的学习方式。

如果这篇文章对你有帮助,欢迎点赞收藏~ 有问题也可以在评论区交流,我们一起进步!