AI 智能体 Memory 记忆模块

AI 智能体 Memory 记忆模块大家好 我是双越 wangEditor 作者 前百度 滴滴 资深前端工程师 慕课网金牌讲师 PMP 前端面试派 作者 我正致力于两个项目的开发和升级 感兴趣的可以私信我 加入项目小组 划水 AI Node 全栈 AIGC 知识库 包括 AI 写作 多人协同编辑 复杂业务 真实上线 智语 AI Agent 智能体项目 一个智能面试官 可以优化简历 模拟面试 解答题目等 本文介绍 AI

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



大家好,我是双越。wangEditor 作者,前百度 滴滴 资深前端工程师,慕课网金牌讲师,PMP,前端面试派 作者。

我正致力于两个项目的开发和升级,感兴趣的可以私信我,加入项目小组。

  • 划水AI Node 全栈 AIGC 知识库,包括 AI 写作、多人协同编辑。复杂业务,真实上线。
  • 智语 AI Agent 智能体项目。一个智能面试官,可以优化简历、模拟面试、解答题目等。

本文介绍 AI 智能体 Memory 记忆模块的架构和流程。

LLM 本身是无状态的,每次调用都是全新的。Agent 要维持连贯对话、记住用户偏好、跨会话积累知识,就必须在外部管理记忆。记忆模块本质上是在回答一个问题: "哪些信息应该被放进下一次 LLM 调用的 context 里?"

注意,memory 不是 data ,不是数据库里存储的所有聊天记录。这俩概念一定要区分开。

短期记忆就是当前 session 会话(不会垮 session)的对话历史,直接拼进 prompt 的 messages 数组里。

核心挑战是 Context Window 有限,通常 8k~128k tokens,必须管理。一般有几种方法:

  • sliding window 滑动窗口,即每次都保留最后 x 条数据,这样容易丢失早期信息
  • Token 精确裁剪,按照模型限制的 token 数量裁切,这样也会丢失早期信息
  • Summarization 摘要压缩,当对话太长时,不是粗暴丢弃,而是把老消息压缩成摘要保留语义。这是更智能的做法:
class SummaryMemory { constructor(client, summaryThreshold = 10) { this.client = client; // Anthropic client this.summaryThreshold = summaryThreshold; this.summary = ""; // 历史摘要 this.recentMessages = []; // 近期完整消息 } async add(role, content) { this.recentMessages.push({ role, content }); if (this.recentMessages.length >= this.summaryThreshold) { await this._compress(); } } async _compress() { const historyText = this.recentMessages .map((m) => `${m.role}: ${m.content}`) .join(" "); const prompt = this.summary ? `已有摘要:${this.summary} 新增对话: ${historyText} 请更新并合并为一段新摘要,保留关键信息。` : `请将以下对话压缩为简洁摘要,保留关键事实和用户意图: ${historyText}`; const res = await this.client.messages.create({ model: "claude-opus-4-6", max_tokens: 500, messages: [{ role: "user", content: prompt }], }); this.summary = res.content[0].text; this.recentMessages = []; // 清空,等待新消息积累 } getMessages() `, }); messages.push({ role: "assistant", content: "好的,我已了解之前的对话背景。", }); } return [...messages, ...this.recentMessages]; } } 

长期记忆跨越会话存在,需要持久化存储。分两个层次:用户画像(结构化)和语义记忆(向量化)。

把用户的偏好、基本信息等结构化数据存 DB,用 PostgreSQL / MongoDB 均可。每次对话开始时读取注入 system prompt:

GPT plus 代充 只需 145// 用 PostgreSQL / MongoDB 均可,这里示意结构 class UserProfileMemory { constructor(db) { this.db = db; } async updateProfile(userId, newFacts) { // newFacts 来自 LLM 对对话的信息抽取 await this.db.collection("profiles").updateOne( { userId }, }, { upsert: true } ); } async getSystemPrompt(userId) { const profile = await this.db.collection("profiles").findOne({ userId }); if (!profile) return ""; return ` 用户基本信息: - 姓名:${profile.name || "未知"} - 职业:${profile.occupation || "未知"} - 偏好语言:${profile.preferredLang || "中文"} - 已知背景:${profile.background || "无"} `.trim(); } // 让 LLM 从对话中自动抽取用户信息 async extractAndSave(userId, conversation, client) { const res = await client.messages.create({ model: "claude-opus-4-6", max_tokens: 300, messages: [{ role: "user", content: `从以下对话中抽取用户的个人信息和偏好,以 JSON 格式返回(只返回 JSON): 对话:${conversation} 可抽取字段:name, occupation, background, preferredLang, interests 等` }] }); try { const facts = JSON.parse(res.content[0].text); await this.updateProfile(userId, facts); } catch (e) { console.log("抽取失败,跳过"); } } } 

这是长期记忆的核心。把历史对话、知识片段 embedding 成向量存储,对话时用当前 query 做相似度检索,把最相关的记忆片段注入 context。

写入:文本 → Embedding API → 向量 → 存入 VectorDB(附带原文metadata) 读取:当前query → Embedding → 相似度搜索 → 取 Top-K 原文 → 注入 prompt 

这里需要存储的可不是所有的对话记录,而是值得被记住的信息,这个概念就很模糊,而且不知道怎么判断哪些值得被记忆。

在实际执行时,会在每轮对话结束时,让 LLM 总结本轮对话的概述,然后记录在 Vector DB ,算是这一轮的语义记忆。这是一个比较好实现的解决方案。

GPT plus 代充 只需 145每轮对话结束  ↓ 直接存(或先压缩成摘要再存) ↓ 检索时用相似度阈值过滤 ↓ 只有真正相关的才会被召回 

另外,如何识别一轮对话结束?并不是浏览器关闭了就是对话结束,浏览器不关闭对话也可能自动技术(用户长久无响应)。实际更常用的触发时机有两种:

方式一:Redis TTL 过期时触发 会话 30 分钟无活动自动过期,在 key 过期的回调里执行总结和存储。Redis 有 keyspace notification 机制可以监听过期事件。缺点是需要额外配置,稍微复杂一点。

方式二:每隔 N 轮自动触发(更常用) 不依赖退出事件,每累积 10 轮对话就自动总结一次存入 Vector DB,滚动进行。

10 轮结束 → 总结前 10 轮 → 存 Vector DB 第 20 轮结束 → 总结 11-20 轮 → 存 Vector DB ... 

这样即使用户直接关掉页面,已经发生的对话也不会丢失,最多丢最近不足 N 轮的部分。

在生产中,两者结合使用:

GPT plus 代充 只需 145每次对话请求 │ ├─ 1. 读取用户画像 → 注入 system prompt 头部 ├─ 2. 向量召回相关历史记忆 → 注入 system prompt 中部 ├─ 3. 取近期对话窗口 → 作为 messages 数组 │ └─ 调用 LLM → 返回结果 │ ├─ 存入向量DB(长期记忆写入) └─ 更新对话窗口(短期记忆更新) 

组装示例

async function buildContext(userId, currentMessage) `) .join(" "); const system = [profile, recalledText].filter(Boolean).join(" "); return { system, messages: recentMsgs }; } 

LLM 永远是无状态的,它"记得你"这个感觉,完全是每次请求前你在外部把记忆拼进 payload 造成的。流程图里的 ③ 构建 Context 就是这个核心步骤。

读取是并行的,写入是异步的。三路读取用 Promise.all 同时发起,压缩到 ~30ms;写回不阻塞用户响应,在 setImmediate 或消息队列里处理。

Redis 的 TTL 是短期记忆的"自然死亡"机制,每次用户发消息都 RESET TTL,30 分钟无活动自动销毁,不需要写任何清理代码。

摘要压缩是有损的,它牺牲细节换取空间,所以重要的信息(用户偏好、关键事实)应该在写回时单独抽取存进 PostgreSQL,而不是只靠摘要保留。

image.png

根据流程图提取的时序图:

image.png

以上就是 Agent 记忆模块的基础知识和流程,有其他问题欢迎继续留言补充~

小讯
上一篇 2026-03-21 12:53
下一篇 2026-03-21 12:51

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/240194.html