当前位置: 首页 > news >正文

AI Agent 应用实战(4):设计记忆与上下文管理

上一篇建立了可停止、可恢复的单 Agent 循环。本篇处理循环变长后的核心矛盾:历史不能无限塞进模型,但关键事实又不能丢。目标不是“记得越多越好”,而是在正确作用域内保存可追溯、可撤销的信息。

一、痛点:从“能演示”走向“可托管”

上下文是本次推理的工作集,记忆是可被检索的持久数据,两者不能混用。建议分三层:步骤记忆保存单轮工具结果;会话记忆保存当前任务已确认事实;长期记忆只保存经过授权、未来确实有用且带来源的事实。原始事件追加保存,摘要只是可重建的派生视图。

真正可迁移的做法,是先写任务契约再选模型:输入从哪里来,成功产物是什么,哪些动作禁止自动执行,最多允许多少步、多少时间和多少费用,失败后由谁接管。契约一旦写进代码和测试,模型升级只是实现替换,不会悄悄改变业务责任边界。

二、原理:把概率判断放进确定性边界

每条记忆应包含主体、内容、来源、创建时间、有效期和敏感级别。写入前先去重和冲突检测,读取时同时按主体权限、时间有效性与任务相关性过滤。用户纠正信息时不要偷偷覆盖旧值,而应把旧记录标为 superseded,并保留纠正链,方便解释答案为何变化。

模型输出、工具数据和记忆内容都按不可信输入处理。每个边界都执行校验、授权、裁剪和审计;所有状态变化都有明确原因。这样做看似增加一些代码,却把“偶尔答错”拆成可定位的规划错误、参数错误、工具错误或策略错误,团队才能针对性改进。

三、实现:用独立程序跑通最小闭环

下面用 SQLite 实现一个极小的事实仓库。它只保存明确事实,并通过 owner 隔离用户;同一 key 的新版本不会删除旧版本。示例展示写入、纠正和读取当前值,迁移到向量库时也应保留这些元数据约束。

importsqlite3fromdatetimeimportdatetime,timezone db=sqlite3.connect(":memory:")db.execute("""CREATE TABLE memory ( owner TEXT, key TEXT, value TEXT, source TEXT, created_at TEXT, superseded INTEGER DEFAULT 0 )""")defremember(owner:str,key:str,value:str,source:str)->None:db.execute("UPDATE memory SET superseded=1 WHERE owner=? AND key=? AND superseded=0",(owner,key))now=datetime.now(timezone.utc).isoformat()db.execute("INSERT INTO memory VALUES (?, ?, ?, ?, ?, 0)",(owner,key,value,source,now))db.commit()remember("user-7","timezone","UTC","user_claim")remember("user-7","timezone","Asia/Shanghai","user_correction")row=db.execute("SELECT value, source FROM memory WHERE owner=? AND key=? AND superseded=0",("user-7","timezone"),).fetchone()count=db.execute("SELECT COUNT(*) FROM memory WHERE owner=? AND key=?",("user-7","timezone")).fetchone()[0]print(f"current_timezone={row[0]}")print(f"version_count={count}")print(f"latest_source={row[1]}")

运行输出:

current_timezone=Asia/Shanghai version_count=2 latest_source=user_correction

送入模型前,应先构造上下文预算。系统规则和当前用户请求优先级最高;任务事实其次;历史对话只保留与当前决策有关的片段。摘要必须标注它不是原始证据,重要数字仍从源记录提取。这样能避免多轮压缩后,条件、否定词和责任主体逐渐漂移。

第二个程序补上生产中最容易遗漏的控制点。它与前一个示例完全独立,可单独保存运行,不依赖本系列其他文件;示例数据是内存假实现,因此不会访问真实账户或产生外部副作用。

fromdataclassesimportdataclass@dataclass(frozen=True)classSegment:name:strtokens:intpriority:intsegments=[Segment("system_rules",120,100),Segment("current_request",90,90),Segment("verified_facts",160,80),Segment("old_chitchat",110,10),]budget=400used=0forsegmentinsorted(segments,key=lambdaitem:item.priority,reverse=True):ifused+segment.tokens>budget:print(f"skipped={segment.name}reason=budget")continueused+=segment.tokensprint(f"included={segment.name}tokens={segment.tokens}")print(f"total_tokens={used}")

运行输出:

included=system_rules tokens=120 included=current_request tokens=90 included=verified_facts tokens=160 skipped=old_chitchat reason=budget total_tokens=370

落地时应把示例中的内存状态替换为事务型存储,把打印日志替换为结构化事件,但不要改变契约。事件至少包含 run_id、步骤、输入摘要、策略结果、耗时、错误类别和版本;密钥、完整个人信息及未经脱敏的提示不得进入日志。

四、踩坑:失败路径决定系统上限

第一类坑是把模型自行推断写成长期事实,之后不断自我强化;第二类坑是跨租户检索,语义相似却没有权限过滤;第三类坑是只保留摘要,无法核对原文。记忆写入要区分 user_claim、tool_fact 与 model_inference,默认不持久化推断;删除请求还要能定位所有派生索引并同步清理。

还要防止把确定逻辑模型化。金额计算、权限判断、枚举路由和状态转移应使用普通代码;模型适合处理分类、抽取、歧义消解与证据综合。每减少一个无必要的模型决策点,就减少一处延迟、成本和不可复现性,同时让测试更容易覆盖。

五、验证:用轨迹和门槛验收

用四组测试验收:同一用户能取回有效事实;其他用户无法命中;过期与被替代记录不会进入上下文;删除后原表和索引都不可检索。再用固定问题比较裁剪前后的答案,确认关键约束未丢且 token 明显下降。下一篇的多 Agent 协作会继续复用带来源事实,而不是互传整段对话。

发布顺序固定为离线回放、影子流量、小比例灰度和有限自治。每阶段先定义通过线和回滚条件,再看结果;不能在看到分数后移动门槛。关键样本要保存初始状态、每步动作、观察、最终产物与终止原因,模型、提示和工具契约版本也必须一起记录。

多 Agent 之间只传结构化任务包和证据引用,能显著降低角色之间的上下文污染。

参考来源

  • SQLite Python
  • LangGraph Memory
  • OWASP LLM Prompt Injection

👍 觉得有用就点个赞 + 收藏,方便回头查阅;有疑问直接在评论区留言,我看到都会回。

🚀 本文属于《AI Agent 应用实战》系列,持续更新,关注不迷路。

📌 文章里的代码都能直接跑。想要可直接 clone 的完整工程 + 配套部署脚本 / 踩坑清单?评论一声或发邮件到cj2664@qq.com,我免费发你。
如果你正好在做类似系统、或有工程化难题想找人做,也欢迎邮件聊一句——我按实际情况评估,能落地的就接单或出方案。评论和邮件都能直接找到我,不用跳别的平台。

http://www.jsqmd.com/news/1364868/

相关文章:

  • SpringBoot+Vue社区医院全栈管理系统设计与实践
  • 论文降AI率实战:从90%到5%的四步法
  • 时序大模型:从数据规模、高效容量到任务泛化的务实解读
  • 世界杯直播零宕机 网络是怎么扛住的
  • Java面试实战:高频考点与深度解析
  • 深圳同城搬家实用科普指南 - 深圳家顺兴搬家
  • Claude Code插件市场使用与开发全指南
  • Flutter在OpenHarmony上的性能优化与动效实践
  • Python 数据可视化:Matplotlib 与 Seaborn 学习笔记
  • godot项目【宝石捕手】02~脚本初始化
  • League Akari:终极免费开源英雄联盟自动化助手,全面提升你的游戏体验
  • IwaraDownloadTool终极指南:一键下载Iwara视频的完整解决方案
  • C++20概念:编译期类型契约,提升泛型编程安全与表达力
  • 谷歌25%新代码由AI生成,会Prompt工程的程序员更吃香了
  • 状态压缩DP实战:从旅行商问题到最短超串算法详解
  • 2026年双碳目标适配的危废减量焚烧炉技术方案甄选指南 - geo交流
  • BetterGenshinImpact自动化工具:如何用智能AI解放你的原神游戏时间
  • ABAP开发中尾随空格问题的深度解析与解决方案
  • 千元预算搭建ROS2与Webots开发环境实战指南
  • 零基础转行数字化,如何挑选高含金量 AI 证书?
  • Linux系统安全加固实战:从内核到应用的全方位防护
  • ThinkPHP开发水族馆商品销售与经营管理系统实战
  • 2026年东营人防通风配套密闭盒生产厂家怎么选?这份优选指南请收好 - geo交流
  • 终结DLL地狱:Windows C++应用VC++运行库分发实战指南
  • 171、【Agent】【OpenCode】TuiThreadCmd(入口命令)
  • Python第三次作业解析:控制结构、函数与文件操作实战
  • 小奥录音更新:实时字幕500ms、说话人分离优化、导出pdf、加入安全认证等
  • ThinkPHP与Laravel双框架协同开发健康管理系统实践
  • 空洞骑士模组管理终极指南:Scarab让模组安装变得如此简单
  • MySQL视图、索引与事务核心原理与优化实战