让 Agent 记住对话、压缩历史、接受人工审核最终成为可靠的智能助手。上篇我们学会了 Agent 的概念、工具定义和 MCP 协议接入。但目前的 Agent 每次调用都是独立的——它不记得上一轮对话说了什么。同时长对话会导致消息列表无限膨胀Token 消耗剧增。本篇将解决这些问题通过Checkpointer实现记忆通过中间件实现历史压缩和人工审核并总结最佳实践与常见问题。四、记忆管理让 Agent 记住过去4.1 失忆问题默认情况下Agent 每次invoke都是一次独立的“感知→推理→行动”过程上一次的对话内容不会自动带入下一次。python# 第1次调用 agent.invoke({messages: [{role: user, content: 我叫张三}]}) # Agent: 你好张三 # 第2次调用默认无记忆 agent.invoke({messages: [{role: user, content: 我叫什么名字}]}) # Agent: 抱歉我不知道你叫什么名字。 ← 失忆了4.2 Checkpointer 机制LangChain 通过Checkpointer实现记忆。每次调用结束后自动保存本次对话的所有消息下次调用时自动加载历史消息拼接到新输入前面。使用方式只需两步pythonfrom langgraph.checkpoint.memory import InMemorySaver # 1. 创建 checkpointer checkpointer InMemorySaver() # 2. 创建 Agent 时传入 agent create_agent( modelllm, toolstools, checkpointercheckpointer, # ← 就这一行 )4.3 Thread ID多会话隔离一个 Agent 通常服务多个用户需要为每个用户维护独立的会话历史。通过thread_id区分python# 张三的对话thread_id user_zhangsan agent.invoke( {messages: [{role: user, content: 我叫张三}]}, config{configurable: {thread_id: user_zhangsan}} ) # 李四的对话thread_id user_lisi完全独立 agent.invoke( {messages: [{role: user, content: 我叫李四}]}, config{configurable: {thread_id: user_lisi}} )相同thread_id的调用共享历史不同thread_id互不干扰。4.4 完整示例pythonimport datetime from langchain.agents import create_agent from langchain.chat_models import init_chat_model from langgraph.checkpoint.memory import InMemorySaver llm init_chat_model(modelgpt-4o-mini, model_provideropenai) checkpointer InMemorySaver() agent create_agent(modelllm, tools[], checkpointercheckpointer) # 第1次调用 for chunk in agent.stream( {messages: [{role: user, content: 今天北京天气怎么样}]}, config{configurable: {thread_id: abc123}} ): print(chunk, end\n\n) # 第2次调用相同 thread_id → 有记忆 for chunk in agent.stream( {messages: [{role: user, content: 我刚才问你什么了}]}, config{configurable: {thread_id: abc123}} ): print(chunk, end\n\n) # Agent 会回答你刚才问了北京今天的天气 # 第3次调用不同 thread_id → 无记忆 for chunk in agent.stream( {messages: [{role: user, content: 我刚才问你什么了}]}, config{configurable: {thread_id: xyz789}} ): print(chunk, end\n\n) # Agent 会回答这是我们第一次对话你还没有问过任何问题4.5 记忆的代价随着对话轮次增加保存的消息列表越来越长第 1 轮2 条消息第 10 轮20 条消息第 100 轮200 条消息每次调用都要把所有历史消息发给 LLM导致Token 消耗剧增甚至可能超出上下文窗口限制。解决方案就是下一节的中间件。五、中间件在关键节点“拦截”处理5.1 中间件概念中间件是一种插入 Agent 执行流程中的“拦截器”可以在以下位置介入介入位置时机典型用途before_model消息发给 LLM 之前压缩历史、注入额外上下文after_modelLLM 返回结果之后记录日志、过滤敏感内容wrap_tool工具执行前后人工审核、权限控制使用方式创建中间件实例通过middleware参数传入create_agent。pythonagent create_agent( modelllm, toolstools, middleware[middleware_a, middleware_b], # 列表按顺序执行 )5.2 消息压缩中间件SummarizationMiddleware解决长对话中消息无限增长的问题。当消息量超过阈值时自动用 LLM 将旧消息压缩成一段摘要。pythonfrom langchain.agents.middleware import SummarizationMiddleware from langchain_openai import ChatOpenAI summary_middleware SummarizationMiddleware( modelChatOpenAI(modelgpt-4o-mini), trigger(messages, 100), # 消息数量达到100条时触发压缩 )压缩效果示意压缩前100 条消息[用户你好AI你好用户天气AI晴天...用户最新问题]压缩后2 条消息[系统以下是摘要用户询问了天气、订单状态...用户最新问题]trigger支持三种策略触发策略写法含义按消息数量(messages, 100)消息数达 100 条时压缩按 Token 比例(fraction, 0.5)Token 数达上下文窗口 50% 时压缩按 Token 绝对值(tokens, 3000)Token 数达 3000 时压缩5.3 人工审核中间件HumanInTheLoopMiddleware某些高风险操作转账、删除数据、发送邮件即使 LLM 决定执行也需人工确认后再真正执行。pythonfrom langchain.agents.middleware import HumanInTheLoopMiddleware hitl_middleware HumanInTheLoopMiddleware( interrupt_on{ transfer_money: True, # 转账 → 需要审核 delete_record: True, # 删除 → 需要审核 get_weather: False, # 查天气 → 不需要审核 } )执行流程Agent 决定调用transfer_money中间件拦截暂停执行返回“等待审核”状态人工通过界面查看并做出“批准”或“拒绝”决定将决定作为Command(resume...)传回Agent 继续执行或放弃。完整示例代码见文档 5.3 节实际开发中需结合前端交互来实现审核界面。5.4 中间件叠加使用多个中间件可以同时使用按列表顺序依次执行。例如pythonagent create_agent( modelllm, toolstools, middleware[summary_middleware, hitl_middleware], )六、Agent 最佳实践6.1 工具设计五原则原则为什么重要正面示例反面示例单一职责LLM 更容易理解功能明确的工具get_weather、get_forecast各做一件事handle_all一个工具做太多事描述清晰LLM 完全依赖描述决定何时用、怎么用“获取指定城市今天的实时天气”“查天气”参数具体减少 LLM 猜测参数格式的可能date: str Field(description格式YYYY-MM-DD)date: str无格式说明错误友好LLM 可根据错误信息调整策略返回“城市‘北精’无法识别是否指‘北京’”抛出KeyError: 北精幂等安全避免重试时产生副作用get_user(id123)多次调用结果相同create_order()多次调用会创建多个订单经验法则如果一个工具的 docstring 超过 3 句话才能说清功能说明它承担了太多职责应该拆分。6.2 系统提示词优化好的系统提示词应包含角色定位、工作流程、约束条件、输出格式。好示例text你是一个专业的数据分析助手。 工作流程 1. 理解用户分析需求 2. 使用 search 工具获取数据 3. 使用 calculate 工具进行计算 4. 用简洁语言呈现结果 注意事项 - 计算结果保留2位小数 - 如果数据不足主动告知用户 - 不要编造数据差示例“你是一个AI助手帮助用户解决问题。”太模糊6.3 调试三层次层次方法适用场景第一层开启日志logging.basicConfig(levellogging.DEBUG)快速定位调用参数第二层LangSmith设置环境变量启用追踪可视化完整执行轨迹第三层流式输出用stream替代invoke观察每一步中间过程经验大多数 Agent 问题根源可归为三类工具描述不够清晰 → LLM 选错工具系统提示词引导不足 → 执行顺序混乱工具返回值格式不规范 → LLM 无法解读结果6.4 性能优化问题优化方法效果响应慢只加载当前任务必需的工具减少 LLM 决策时间Token 消耗高使用SummarizationMiddleware压缩历史消息工具调用次数多优化工具返回值一次返回完整信息减少循环轮次吞吐量不足使用ainvoke异步调用支持并发处理七、课程总结与常见问题7.1 知识回顾章节核心问题学到了什么Agent 介绍Agent 是什么和 Chain 的区别Agent LLM 自主决策 工具调用工具定义怎么让 Agent“做事”tool定义create_agent组装MCP 接入怎么接入外部工具MCP 协议统一接入对 LLM 透明记忆管理怎么让 Agent 记住对话Checkpointer thread_id 实现多会话记忆中间件怎么压缩历史、人工审核SummarizationMiddleware、HumanInTheLoopMiddleware7.2 常见问题 QAQ1Chain 和 Agent 如何选择任务流程确定时用 Chain简单可靠任务需要动态判断时用 Agent灵活但复杂。两者可以结合——Agent 内部的某些子任务可以用 Chain 实现。Q2RAG 和 Agent 可以结合吗可以而且非常常见。典型做法是把 RAG 检索封装成一个工具Agent 在需要时自主调用它。例如将向量数据库检索包装为query_knowledge_base工具Agent 就可以在回答专业问题时自动检索相关知识。Q3如何优化 Agent 的响应速度四个方向只加载必需的工具减少 LLM 决策开销用SummarizationMiddleware压缩长对话减少 Token使用异步调用ainvoke支持并发优化工具返回值格式减少循环轮次Q4什么时候需要 LangGraph当你需要多个 Agent 协作、复杂的条件分支和循环逻辑或比create_agent更精细的流程控制时就需要 LangGraph。它是 Agent 的进阶编排工具。7.3 下一步建议动手实践选择一个实际场景如个人知识库问答、自动化数据分析用本课知识构建一个 Agent。深入 LangGraph学习状态图、条件边、多 Agent 协作构建更复杂的工作流。关注 AI 生态MCP 社区正在快速发展关注社区动态可以快速扩展 Agent 的能力。
企业数字化 ERP 产品动态
相关推荐
手动改能降低AI率吗?我踩3天坑攒的实测结论 上周帮运营组改他们用大模型生成的618活动复盘稿,熬了俩小时改完提交公司合规系统,直接被打回。 当时我第一反应就是:手动改能降低AI率吗?之前网上搜的野路子怎么一个都没用?一开始我用的是网上流传最广的操作… · 2026/9/28 23:06:11
Gerrit 批量评审与合入依赖链的全自动实践 在日常基于 Gerrit 的代码协作中,经常会遇到**一系列存在父子依赖关系的提交(Patch Set)**需要依次评审与合入。例如:基于同一个功能分支,本地拆分成多个逻辑独立的 commit 依次 push 到 Gerrit,这些 Chang… · 2026/8/29 13:05:20
欧盟要求谷歌开放安卓,谷歌与苹果应对 DMA 规则差异明显 欧盟要求谷歌开放安卓系统今日,欧盟要求谷歌让其人工智能竞争对手更便捷地接入安卓(Android)系统。安卓作为一款开源操作系统,驱动着全球数十亿台设备的运行。这一要求虽看似让谷歌吃了败仗,毕竟多年来谷歌一直在抵制此… · 2026/9/21 4:58:48
电工证全部答案怎么找?考前押题帮你过线不白交钱 电工证全部答案怎么找?考前押题帮你过线不白交钱 怕考不过白交培训费?别急,这里有一套实操经验分享,手把手教你搞定电工证全部答案,特别是考前押题技巧,保你顺利拿证,不走弯路。 电工证到底值不值?证书真实价值与执业范围… · 2026/11/14 12:06:14
找人办电工证违法?内部消息告诉你真相 找人办电工证违法?内部消息告诉你真相 之前考的证在外省能不能转过来?这个话题在建筑工地、工厂、劳务公司里讨论得越来越多。特别是像安阳这样的劳务班组负责人,经常要面对工人证件是否合法、能否异地使用的问题。最近很多同行私下问,… · 2026/11/14 12:06:14
潇潇雨歇,电工证复审别耽误,潍坊哪里复审电工证值不值得考 潇潇雨歇,电工证复审别耽误,潍坊哪里复审电工证值不值得考 你是不是正盯着招聘启事上的“持证上岗”几个字发愁?手上没有电工证,连面试机会都拿不到。潍坊哪里复审电工证?这事儿别拖了,不然真要耽误你找工作。电工证在各行各业都吃得开,值不值得考?答… · 2026/11/14 12:06:14
查电工证是否合格证丢了怎么补办 外省电工证怎么查是否合格?网上查询方法全在这了 之前考的证在外省能不能转过来?这是很多电工朋友在跨省工作或转岗时最关心的问题之一。我之前在洛阳从事公路工程设备维修时,就遇到过一位老电工,他把证考在了河南郑州,后来调岗到南阳,结果发现证书不能… · 2026/11/14 12:06:14
西安哪里能报考电工证多久拿证?别被中介坑了 西安哪里能报考电工证多久拿证?别被中介坑了 不知道去哪报名怕被中介坑?西安哪里能报考电工证?多久拿证?这些问题其实很多人都遇到过,尤其是刚入行的特种作业人员,面对一堆证书和培训机构,真不知道从哪里下手。别急,这篇文章帮你理清楚流程,避坑指南… · 2026/11/14 12:05:14
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/13 22:30:50
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/13 5:40:45
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/12 23:27:43
有初级电工证怎么工作 2026河南最新政策怎么应对 有初级电工证怎么工作 2026河南最新政策怎么应对 之前考的证在外省能不能转过来?这个问题我每天被问上百次。2026年河南最新政策对证书跨省转移有了明确说明,特别是南阳市的从业者,需要特别关注。… · 2026/11/14 0:00:31
电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 证书过期了不知道怎么复审延期?很多人遇到这种情况,要么是工作太忙没时间处理,要么是不知道具体流程,导致证书失效,影响工作和项目进展。其实复审并不难,关键是要找准官方报名入口,掌… · 2026/11/14 0:00:31
为什么要低压电工证实操考试考什么 为什么低压电工证值不值得考?别再被中介骗了 你是不是也经常看到网上有人在问“低压电工证到底值不值得考”?或者在找报名点时,担心被中间人骗钱?这些问题,我懂,我也经历过。作为一名在应急管理行业摸爬滚打多年的从业者,我深知低压电工证不仅是一个从… · 2026/11/14 0:00:31
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:12:21
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:11:51
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 22:31:30