☰
Agent长期记忆架构设计:从记忆分层到向量混合检索与遗忘机制
2026/10/26 18:47:13 网站建设 项目流程

LLM 的上下文窗口再大,关掉会话就“失忆”。这是当前 Agent 落地时最常见的痛点。很多团队把“上下文窗口”当成“记忆”来用,结果对话一长就开始漏信息、重复提问,甚至把上一轮的错误决策带进下一轮。真正能撑起复杂任务的 Agent,需要一套独立于模型上下文之外的记忆系统:有写入、有检索、有更新、有遗忘。

这次我们来完整拆一遍 Agent 长期记忆架构。文章会先讲清短时记忆与长期记忆的边界,再给出一套可落地的记忆分层模型,然后逐步展开记忆写入、混合检索、遗忘机制的实现思路,最后给出一个可以照着改的工程模块设计和接口示例。内容偏系统设计,也包括可以直接抄的代码骨架。

1. Agent 记忆架构核心思路速览

先给一张总览表,后面所有章节都围绕这张表展开。

设计项推荐方案
记忆分层工作记忆 / 情景记忆 / 语义记忆 / 技能记忆
短时记忆存储会话上下文、任务栈、Redis 缓存
长期记忆存储关系型数据库 + 向量索引,或专用向量数据库
写入触发用户显式表达、任务完成、事件发生、定时回顾
检索链路向量召回 + 关键词召回 + 时间过滤 + 重排序
遗忘策略时间衰减、重要性评分、容量上限、显式删除
接入方式记忆服务 API,或接入 LangGraph 等框架的 memory 节点
合规要求最小必要存储、支持用户删除、敏感信息脱敏

这套结构解决的核心问题是:Agent 不再只有“上下文窗口里的临时文本”,而是拥有一个跨会话、可检索、可管理的事实库。短期记忆负责“当前任务跑得顺”,长期记忆负责“这个用户是谁、之前做过什么、结论是什么”。

2. 为什么 Agent 需要独立于大模型之外的长期记忆

大模型本身是没有状态的。你调用一次接口,传入完整的对话历史,模型才能“知道”前面聊了什么。这也是为什么很多人把上下文窗口当成 Agent 的记忆:因为从表现上看,只要把历史消息全部拼进 prompt,Agent 好像就记得住。

但这种方式有四个硬伤。

第一,成本随轮数膨胀。每一轮对话都把全部历史发给模型,token 消耗持续增长。第二,窗口有上限,超出之后只能截断。截断会把关键结论丢掉,而且往往是对话中期的信息先丢。第三,无法区分“值得记的事”和“临时的一句话”。用户在某轮随口说“我比较喜欢简洁的回复”,这句话如果不在窗口里,下一轮就没了;如果把所有话都留着,又会污染 prompt。第四,不同任务之间无法共享记忆。用户上一个 Agent 里确认过的偏好,下一个 Agent 完全不知道。

所以长期记忆的定位应该是:把对话中真正有长期价值的信息抽取出来,存到记忆系统里;等到下一次需要时,通过检索把相关的记忆片段重新放回 prompt。也就是“唤醒”而不是“全量携带”。这也正是 LangChain、LangGraph 等 Agent 框架开始强调长期记忆能力的原因——模型本身负责推理,外部记忆模块负责记住,两者各司其职。

3. 短时记忆与长期记忆的区分

很多入门设计会漏掉一个重要问题:什么样的信息算短时记忆,什么样的信息必须进长期记忆?区分标准不能只看“时间长短”,还要看信息是否具备跨任务复用价值。

短时记忆的特征是:

  • 只在当前任务内有效,例如用户正在填写的表单内容、中间推理步骤、临时文件路径;
  • 容量小,生命周期短,任务结束即失效;
  • 复用的价值低,绝大多数中间状态不需要进入长期库。

长期记忆的特征是:

  • 可以跨会话、跨任务使用,例如用户偏好、项目背景、已确认的业务规则;
  • 时效性可能很长,也可能有有效期,例如“用户当前正在使用免费套餐”;
  • 从原始对话中抽取出来之后,仍然需要继续维护,包括冲突处理和过期淘汰。

下面用一张表做对比:

维度短时记忆长期记忆
生命周期会话内或任务内跨会话、跨任务
存储位置内存、Redis、会话文件数据库、向量索引
数据形态原始消息、任务状态、临时变量结构化事实、摘要、用户画像
写入方式直接追加抽取、去重、冲突合并
检索需求无,直接读取需要检索,只取相关片段
遗忘方式会话结束即清理需要显式遗忘策略

如果把这个边界搞混,会出现很典型的问题。把临时信息写进长期库,长期记忆会被噪声淹没,检索时永远命中一堆无关记录;把长期信息全部留在短时上下文里,token 成本暴涨,而且会话结束之后这些信息就永久丢失。所以分层设计不是理论洁癖,是实际工程必须做的第一步。

4. 记忆分层:工作区、情景区、语义区、技能区

我建议把 Agent 记忆分成四层。每一层解决一类问题,存储介质、写入触发条件和维护策略都不同。

4.1 工作记忆层(L0)

工作记忆层对应短时记忆,存的是当前正在执行的会话状态和任务状态。包括用户最新输入、Agent 的推理中间结果、待处理队列、工具调用记录等。

实现上不需要复杂数据库,通常用内存对象或 Redis 就行,每个会话一个键。要注意的是必须设置生命周期,例如会话闲置 30 分钟后清理,或者任务完成后压缩。

工作记忆层虽然技术含量不高,但它是整个记忆系统的入口。很多长期记忆的抽取工作,就是从这里拿到原始素材的。

4.2 情景记忆层(L1)

情景记忆层存的是跨会话但没有经过太多抽象的事件记录。例如“用户在 3 月 10 日要求生成一份月度报表”“用户在上一次对话中提到了项目 A 的截止时间是月底”。这些记录是“发生过的事实”,保留原始语义。

情景记忆通常会被转成长期记忆之后再做清理,而不是一直无限堆积。它的价值在于:当 Agent 需要回答“我的项目甲方之前提过什么要求”这种问题时,情景记忆是最终的事实来源。

存储建议使用普通数据库表,每条记录包含时间、事件摘要、关联实体、重要性分数和过期时间。

4.3 语义记忆层(L2)

语义记忆层是长期记忆的核心,存的是经过抽取和抽象之后的稳定事实。例如“用户偏好简洁回复”“用户负责的项目叫 x 项目”“团队使用 PostgreSQL”。这些事实不再依赖某一次对话,而是像用户画像一样长期存在。

语义记忆的写入需要经过 LLM 抽取和冲突处理。比如用户上一轮说“我讨厌长邮件”,下一轮说“重要客户可以发长邮件”,这两条信息需要合并而不是覆盖,因为后者是对前者的补充。

语义记忆的存储一般用关系型数据库加向量索引,或者直接用向量数据库。检索时既要支持按实体属性精确匹配,也要支持按语义相似度召回。

4.4 技能记忆层(L3)

技能记忆层存的是“怎么做”的经验。例如某个工具调用流程在什么条件下有效、某个常见任务的处理步骤、哪些 workflow 在上一次执行时成功了。

这一层和 Agent 的 skill/plugin 机制可以结合。它可以不存自然语言描述,而是存可执行的模板或工作流引用。技能记忆的意义在于,Agent 在遇到重复任务时可以直接复用成功路径,而不是每次重新探索。

四层记忆之间不是孤立的。典型流程是:工作记忆中的对话内容被抽取出事件,进入情景记忆;情景记忆经过摘要和去重,升级为语义记忆;多次成功的任务路径沉淀为技能记忆。这样记忆就有了“从原始到抽象,从临时到稳定”的完整生命周期。

5. 记忆写入:什么时候记、记什么、怎么去重

长期记忆架构里,最容易被忽略的是写入策略。没有好的写入策略,检索做得再漂亮也没用,因为库里装满了噪声。

5.1 写入触发时机

不建议把每一轮对话都写进长期记忆。比较合理的触发点有四个:

  • 用户显式表达偏好。例如“以后都用中文回复”“我不喜欢看超过 500 字的总结”。
  • 任务完成时抽取关键结论。例如“本次任务生成了 3 份周报,存档位置是 xxx”。
  • 跨会话关键事件发生。例如用户创建了一个新项目、修改了截止时间。
  • 定时回顾。每隔一定轮数,对近期工作记忆做一次摘要,把有价值信息抽取出来。

5.2 记忆条目数据结构

一条长期记忆应该至少包含下面这些字段:

{ "memory_id": "mem_xxx", "type": "semantic", "subject": "user", "predicate": "prefers_language", "object": "chinese", "importance": 0.9, "created_at": "2025-01-01T10:00:00Z", "last_accessed_at": "2025-01-01T10:00:00Z", "expires_at": null, "source_session": "session_xxx", "content_embedding": [] }

subject/predicate/object 结构适合表示“主谓宾”三元组,既方便精确查询,也方便做冲突检测。importance 是重要性分数,遗忘机制会用到。expires_at 是过期时间,适合临时性事实。

这个结构是示例,实际可以根据业务调整。但建议至少保留类型、实体、属性、值、重要性、时间戳这几个核心字段。

5.3 写入去重与冲突合并

写入前先做相似度检查。如果新记忆的向量和已有记忆的相似度超过阈值,就不要直接插入,而是做合并。例如“用户喜欢简洁回复”和“用户喜欢简短回复”语义高度相似,就应该保留一条,或者把两者合并成“用户喜欢简洁、简短的回复”。

合并规则建议按重要性优先:新值重要性更高时更新旧值,否则保留旧值并补充说明。要避免“每次写入都新增一条”,这样长期记忆会快速膨胀,检索时返回一堆重复内容。

代码层面,写入流程可以抽象成这样一个函数:

def remember( memory_store, embedding_model, item: MemoryItem, duplicate_threshold: float = 0.85, ): if not item.content: return query_vec = embedding_model.embed(item.content) item.content_embedding = query_vec # 先查重,再决定新增还是合并 candidates = memory_store.search_similar( vec=query_vec, top_k=5, threshold=duplicate_threshold ) for cand in candidates: if is_semantic_similar(item, cand): memory_store.merge(item, cand) return memory_store.insert(item)

这个查重逻辑非常重要。实际运行时,你可以在同一个任务里快速验证:连续写入两条语义相近的记忆,观察最终库里是否只保留了一条(或者变成一条合并后的记录)。

6. 记忆检索:向量 + 关键词多路召回 + 重排序

长期记忆如果只有写入没有检索,就是一个死库。检索的目标是:给定当前用户问题,从记忆库中找出最相关、最有用的记忆片段,组装到 prompt 里。整个检索流程我分成五步。

6.1 查询改写

用户的问题通常是口语化的,例如“帮我把上次给财务的方案找出来”。直接拿这句话做向量检索,语义能命中一部分,但精确命中“财务方案”这种实体关键词会较弱。所以第一步是查询改写,用 LLM 把用户问题转换成适合检索的形式,例如:

  • 原始问题:帮我把上次给财务的方案找出来
  • 检索 query:财务 方案 上次 时间
  • 检索意图:查找用户和财务相关的历史方案

这一步可以简单调用一次 LLM,也可以根据意图模板生成。查询改写不是必须的,但在命中率不足时优先检查这里。

6.2 多路召回:向量检索 + 关键词检索

单靠向量检索不够。向量检索适合语义相似,但不擅长精确匹配人名、编号、专有名词。比如用户问“项目X的负责人是谁”,如果记忆里存的是“项目X由张三负责”,向量检索能命中;但如果存的是“张三 项目X 负责人”,关键字权重较高时,BM25 召回会更准。

所以建议做双路召回:

  • 向量召回:embedding 模型编码 query,在向量索引中取 top_k;
  • 关键词召回:使用 BM25 或全文索引,按词频和逆文档频率召回包含关键实体的记忆。

热搜里提到的“向量混合检索加 bm25 多路召回”就是在讲这种方案。两面召回之后合并、去重,再进入重排序阶段。

一个简化版的双路召回伪代码如下:

def search_memories(memory_store, query: str, top_k: int = 10): query_vec = embedding_model.embed(query) vector_hits = memory_store.vector_search(query_vec, top_k=top_k) keyword_hits = memory_store.bm25_search(query, top_k=top_k) # 合并候选集,按来源去重 candidates = merge_by_memory_id(vector_hits, keyword_hits) return rerank(candidates, query, query_vec, top_k=top_k)

6.3 时间过滤与重要性加权

召回之后的候选集不能直接进 prompt。需要做一轮过滤:已经过期的记忆直接丢弃;距离过期时间很短的记忆降权;重要性分数低的记忆只有在没有其他候选时才返回。

这里引入一个简单的评分公式:

score = semantic_score * alpha + keyword_score * beta + importance * gamma - time_decay * delta

其中 alpha、beta、gamma、delta 是权重,time_decay 是距离创建时间或最后访问时间的衰减函数。具体数值要在你自己的数据集上调,先固定一个可用版本,再看命中率调整。

6.4 重排序(Rerank)

多路召回召回的数量可以放大,比如 top 50,然后重排序后再取 top 5。重排序可以使用专门的 rerank 模型,也可以直接用 LLM 对候选记忆打分。对小规模应用,用 LLM 打分成本可控;大规模应用建议用 lightweight rerank 模型,避免每次检索都调用大模型。

重排序的目标不是“找到语义最像的那条”,而是“找到当前任务最需要的那条”。例如用户问“这个项目什么时候截止”,记忆库里有一条“项目截止时间是月底”,还有一条“用户是项目负责人”,前者应该排得更靠前,尽管后者的实体关联更强。

6.5 组装上下文

检索到的记忆要以紧凑文本的形式插入到 system prompt 中,而不是把完整原始对话塞回去。建议给每条记忆加一个元信息前缀,例如:

【记忆-语义】用户偏好:使用简洁中文回复(重要度0.9,记录于2025-01-01) 【记忆-情景】上次对话:用户要求生成了3份周报,存放在 /reports/weekly/

这样可以告诉模型“这些是历史记忆”,避免模型混淆记忆和当前对话。同时控制召回条数,例如默认返回 5~8 条,每条记忆控制在一两句话,整体记忆 prompt 保持在几百 token 以内。

7. 遗忘机制:不让记忆变成包袱

长期记忆系统如果没有遗忘机制,早晚会失控。遗忘不是删除,而是对记忆进行“降权、归档、最后删除”的生命周期管理。遗忘机制要解决几个问题:存储无限膨胀、过时信息产生误导、用户隐私数据存留过久。

7.1 遗忘的三个层次

  • 软失效:把记忆标记为“不活跃”或“低置信度”,检索时降低权重,但不物理删除。适合暂不确定是否还有用的记忆。
  • 归档:把长期不访问的记忆移到冷存储,如从热向量索引迁到离线表。保留记录但不再参与实时检索。
  • 硬删除:物理删除记忆记录及其向量索引。适用于过期隐私数据、用户主动要求删除的数据、重复错误数据。

7.2 遗忘评分策略

给每条记忆维护一个遗忘分,定期扫描并处理低分记忆。遗忘分可以由这几个因素决定:

  • 重要性(importance):越低越容易被遗忘;
  • 最后访问时间(last_accessed_at):越久越容易被遗忘;
  • 访问频率:高频访问的记忆要优先保留;
  • 是否过期(expires_at):过期记忆直接进入删除或归档流程。

一个简单的遗忘评分函数可以这样实现:

import math from datetime import datetime, timezone def forget_score(item, now=None): now = now or datetime.now(timezone.utc) age_hours = (now - item.last_accessed_at).total_seconds() / 3600.0 # 时间衰减:age 越大,score 越小;半衰期设为 7 天 half_life = 24.0 * 7 time_factor = math.pow(0.5, age_hours / half_life) # 综合分数,importance 越高越不容易被遗忘 return item.importance * time_factor * (1.0 + item.access_count * 0.1)

这里的半衰期 7 天是示例参数,真实业务需要按用户习惯和记忆类型调整。语义记忆的半衰期应该比情景记忆长,用户画像比临时任务结论长。

7.3 定期整理与摘要合并

遗忘机制不能只被动等待记录过期,还要定期主动整理。例如每周对情景记忆做一次摘要,将多条相似事件合并成一条语义记忆,然后删除原始事件记录。这样既能压缩存储,又能提升检索质量。

整理任务可以做成一个后台定时任务,例如每天凌晨运行:

  • 扫描低遗忘分记忆,标记归档或删除;
  • 对相似记忆做聚类合并;
  • 对过期记忆执行硬删除;
  • 更新用户记忆画像摘要。

注意一点:用户主动要求删除的记忆,必须真实删除,不能只做“降权”。尤其是涉及个人信息的数据,除了删除主记录,还要同步删除向量索引、缓存和归档副本。这是合规底线。

8. 工程实现:记忆模块的落地骨架

下面给出一套可以照着改的工程骨架。这里不绑定具体框架,核心接口是通用的:写入、检索、遗忘、整理。

8.1 存储选型参考

不同规模的项目选型差异很大,给一个保守参考:

规模短时记忆长期记忆
单机小项目内存字典 + pickle/JSON 落地SQLite + 文件向量索引
团队中等项目Redis + JSONPostgreSQL + pgvector
大规模服务Redis Cluster + 会话缓存PostgreSQL + pgvector / Milvus 等向量库

选择存储时先不要追求“最先进的向量数据库”。用 PostgreSQL 自带 pgvector,或者 SQLite 加向量扩展,就足够启动一个真实项目。把记忆 schema 设计好,后面迁移到专用向量库并不难。

8.2 核心接口设计

class MemoryStore: def insert(self, item: MemoryItem) -> str: ... def search_similar(self, vec, top_k, threshold) -> list: ... def search_keyword(self, query, top_k) -> list: ... def update(self, memory_id: str, updates: dict) -> None: ... def delete(self, memory_id: str) -> None: ... def bump_access(self, memory_id: str) -> None: ... def get_expired(self, now) -> list: ...

8.3 一个简单的写入实现

这里用 SQLite 做示例,方便大家快速跑通。实际生产可以用 PostgreSQL + pgvector,接口保持一致。

import sqlite3 import json class SqliteMemoryStore(MemoryStore): def __init__(self, db_path: str): self.conn = sqlite3.connect(db_path) self.conn.execute(""" CREATE TABLE IF NOT EXISTS memories ( memory_id TEXT PRIMARY KEY, type TEXT, content TEXT, importance REAL, created_at TEXT, last_accessed_at TEXT, expires_at TEXT, access_count INTEGER DEFAULT 0, embedding TEXT ) """) self.conn.commit() def insert(self, item: MemoryItem) -> str: cur = self.conn.execute( """ INSERT INTO memories (memory_id, type, content, importance, created_at, last_accessed_at, expires_at, access_count, embedding) VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?) """, ( item.memory_id, item.type, item.content, item.importance, item.created_at, item.last_accessed_at, item.expires_at, json.dumps(item.content_embedding), ), ) self.conn.commit() return item.memory_id

搜索需要把 embedding 存成 JSON 还是用专门向量列,取决于你选的存储方案。生产环境建议直接使用数据库原生向量索引,避免每次全量扫描。

8.4 与 Agent 框架的接入方式

LangGraph 这类框架已经把“长期记忆”放进了官方能力体系里,但核心思路是一样的:你需要注册一个 memory store,在每次对话轮次前后触发写入和检索。典型的接入点是:

  • 在对话开始时,读取当前用户的历史记忆,组装到 system prompt;
  • 在对话结束时,抽取本次对话的长期记忆,写入记忆库;
  • 在工具调用失败或多次重复问题时,主动检索记忆补充上下文。

不要把这个模块做成不可替换的“大胶水”。记忆模块应该只依赖两个输入:当前对话历史和用户标识。这样无论是接入 LangGraph、自研 Agent,还是未来换成另一个框架,都只需要改接入层,不需要重写记忆逻辑。

9. 记忆服务 API 与批量任务

当记忆模块从 Agent 进程里抽离出来,它就是一个独立的记忆服务。这样做的好处是:多个 Agent 可以共享一套记忆,前端可以独立查看和删除记忆,批量整理任务也可以在服务端统一执行。

9.1 接口设计示例

下面给出一组示例接口,字段和路径请按实际项目调整。这里只是为了说明接口形态:

方法路径作用
POST/memories写入一条记忆
POST/memories/search检索记忆
POST/memories/forget遗忘/删除记忆
GET/memories/{user_id}查看某个用户的记忆列表
POST/memories/consolidate触发一次整理任务

搜索接口请求体示例:

{ "user_id": "user_123", "query": "财务方案", "top_k": 5, "include_expired": false }

9.2 Python 调用示例

记忆服务启动后,Agent 侧可以通过 HTTP 调用。

import requests url = "http://127.0.0.1:8000/memories/search" payload = { "user_id": "user_123", "query": "财务方案", "top_k": 5, "include_expired": False, } resp = requests.post(url, json=payload, timeout=5) if resp.status_code == 200: memories = resp.json()["items"] for mem in memories: print(mem["content"], mem["importance"])

9.3 批量任务设计

批量任务通常有两类。一类是批量写入,例如从历史对话日志中回填记忆。这种任务要求写入接口支持批量和幂等,否则重复回填会产生大量重复记忆。另一类是批量整理,例如每晚对全部用户的记忆执行遗忘扫描和摘要合并。

批量整理任务要特别关注两个问题:

  • 失败重试:整理任务涉及删除和合并,中途失败容易造成数据不一致。建议每一步操作先记录操作日志,再执行变更;
  • 全量扫描成本:随着记忆量增加,每天全量扫描所有记忆会越来越慢。可以按用户分组,每天只处理一部分,或者按“最近有活跃记录的用户”优先处理。

接口服务的稳定与否,直接决定了记忆模块能不能被其他系统复用。所以最好把写入去重、检索超时、遗忘删除这几个流程都在服务端固定下来,而不是每个调用方各写一遍。

10. 性能观察与常见问题排查

长期记忆系统上线后,不要只关心功能是否“看起来能跑”,要看几个关键指标。

10.1 关键指标

指标观察方式说明
写入耗时记录每次 remember 的 P95 耗时太高说明查重或 embedding 调用成为瓶颈
检索耗时记录 search 的 P95 耗时多路召回后如果超过几百毫秒,需要优化索引
记忆总量每天记录新增和删除数量持续增长说明遗忘策略没生效或查重没生效
命中率人工抽样判断检索返回值是否相关可以用“检索是否被 Agent 采用”做间接指标
embedding 调用量记录每日 embedding 接口调用次数写入和检索都依赖 embedding,费用需要关注

这些指标不需要一次性全做,但至少要记录日志。否则上线之后系统效果变差,很难定位是记忆写入的问题、检索的问题还是 prompt 组装的问题。

10.2 常见问题排查表

问题现象可能原因排查方式解决方案
检索结果和当前问题无关向量阈值设置过低,召回大量弱相关记忆检查候选记忆的相关性分数分布调高相似度阈值,增加关键词召回权重
记忆库快速增长写入去重失效查看是否有大量相似记忆同时存在加强写入前向量查重和合并逻辑
某些用户记忆过多没有按用户设置容量上限查看单个用户记忆数量按用户设置容量上限,超出触发遗忘
记忆 prompt 占用过大召回条数过多或单条记忆太长检查最终插入 prompt 的记忆内容长度降低 top_k,控制每条记忆长度
用户删除记忆后仍被检索到只删除主表,未清理向量索引或缓存检查删除逻辑覆盖范围同步删除向量索引、缓存和归档副本
检索延迟偏高embedding 调用慢或向量索引未优化分段测量查询改写/embedding/检索耗时对向量索引做量化和分片,必要时增加缓存

11. 最佳实践与合规边界

长期记忆看起来只是技术模块,但涉及用户数据,必须把合规和隐私问题放在一起设计。

第一,坚持最小必要存储。不要把所有原始对话全部入库,只存储抽取后对任务有复用价值的结构化事实。这样既能降低存储成本,也能减少隐私风险。

第二,敏感信息必须脱敏。用户姓名、电话、地址、身份证号、财务信息等,尽量不要以明文形式存进长期记忆。如果业务确实需要,要做加密存储和访问审计。

第三,支持用户自主查看和删除。Agent 应该允许用户查看“你还记得关于我的哪些信息”,并且允许一键删除全部记忆。这不仅是合规要求,也能提升用户信任。涉及人脸、声音、私有文档等敏感内容时,必须获得明确授权后才能写入记忆库。

第四,内存和数据库权限要隔离。记忆服务如果是对外的,需要做用户身份校验,防止一个用户检索到另一个用户的记忆。即使是内部服务,也建议按用户维度做隔离,避免误查询导致的数据泄露。

第五,介入人工审核。对重要事实和用户画像类记忆,可以在抽取后做低置信度标记,由人工或后台校验后再进入线上检索。不要完全信任 LLM 抽取结果,它在某些场景会幻觉出用户从未说过的信息。

12. 总结与下一步

这套 Agent 长期记忆架构最值得记住的三个设计点是:分层、混合检索、遗忘机制。分层的本质是让不同类型的记忆各归其位,避免把临时信息当成核心事实;混合检索解决的是“语义相似”和“精确匹配”不能互相替代的问题;遗忘机制则是让记忆系统长期可用的前提。

最先应该验证的功能是一个最小闭环:在一个会话里告诉 Agent 一条用户偏好,关闭会话,开启新会话后,问一个需要用到这条偏好的问题,看 Agent 能否通过长期记忆检索正确回答。这个闭环能跑通,架构就已经成立了一大半。

最容易踩的坑是把短时记忆直接当成长期记忆写入,导致记忆库快速膨胀,以及不做遗忘策略,导致越用越慢。这两个问题在系统初期很难发现,等记忆量上去了再改,成本会高很多。

下一步你可以继续扩展的方向:为记忆增加置信度评估和人工审核流程,将多用户的记忆做权限隔离,在不同业务场景里设置不同的记忆 TTL,以及把记忆检索结果做成可观测的日志,方便持续调优检索权重。等这些做扎实了,这个长期记忆模块就可以真正接到生产 Agent 里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询