AI 应用里的 Memory 应该怎么设计?不要把聊天记录等同于记忆
上一篇文章讨论了 Repository。Repository 解决的是 AI 应用中的数据访问问题。会话、消息、任务、文档、工具调用记录、模型调用记录都需要有清晰的数据访问边界。但数据被存下来之后还有一个更进一步的问题哪些数据应该被 AI 当成记忆哪些数据只是普通历史记录哪些内容可以在未来任务中被召回哪些内容必须过期、删除或禁止保存这些问题就进入了 Memory 的范围。很多人会把 Memory 简单理解成聊天记录。但在真正的 AI 应用里Memory 不是聊天记录的同义词。聊天记录只是可能成为 Memory 的原始材料之一。Memory 更关注的是什么信息值得长期保存。什么信息应该在什么时候被召回。什么信息不能被保存。什么信息需要用户确认。什么信息过期后必须清理。如果没有这些边界Memory 很容易从一个增强体验的能力变成一个隐私和安全风险。一、为什么 AI 应用需要 Memory没有 Memory 的 AI 应用通常是短视的。每一次请求都是一次新的开始。用户之前说过什么系统不知道。用户偏好是什么系统不知道。某个任务之前执行到哪一步系统不知道。历史上哪些方案有效系统也不知道。这会导致几个问题用户需要反复解释背景。Agent 不能延续长期任务。系统无法积累经验。个性化能力很弱。多轮协作容易丢上下文。例如一个代码助手如果每次都不知道项目结构、技术栈、用户偏好和历史决策它只能做临时回答。再比如一个知识库助手如果每次都不知道用户常问的问题、已经确认过的业务规则和历史检索结果它也很难真正变得有用。Memory 的价值就是让 AI 应用在可控范围内拥有延续性。不是让模型记住所有东西。而是让系统有选择地保存、组织和使用重要上下文。二、Memory 不是聊天记录聊天记录是原始历史。Memory 是经过筛选和组织后的可复用上下文。这两者不能混为一谈。例如下面是一段聊天记录用户我最近在写一个 Python AI 应用脚手架。 助手你可以先设计 CLI、配置系统和 LLM 抽象层。 用户我更希望项目结构简单一点先不要引入太重的框架。这些内容都可以保存为消息记录。但真正值得成为 Memory 的可能是用户正在开发一个 Python AI 应用脚手架。 用户偏好简单、轻量、不过度引入重框架的项目结构。前者是聊天日志。后者是可复用记忆。如果每次都把完整聊天记录塞回 Prompt会有几个问题Token 成本越来越高。无关内容越来越多。过期信息会干扰当前任务。敏感信息可能被反复带入上下文。模型很难判断哪些内容真的重要。所以 Memory 不能只是历史消息堆叠。它需要筛选、压缩、分类和召回策略。三、短期记忆解决当前任务短期记忆主要服务当前会话或当前任务。它通常不需要长期保存。例如当前用户问题。本轮对话上下文。当前 Workflow 的中间状态。当前 Agent 的执行步骤。当前 Tool 的返回结果。当前任务的临时变量。短期记忆可以存在内存里也可以存在任务上下文对象里。例如classShortTermMemory:def__init__(self):self.messages[]self.variables{}self.tool_results[]defadd_message(self,role:str,content:str):self.messages.append({role:role,content:content})defset_variable(self,key:str,value):self.variables[key]value短期记忆的特点是生命周期短。任务结束后可以清理。会话关闭后可以清理。它强调的是当前推理过程的连续性。不是长期个性化。四、长期记忆解决未来复用长期记忆服务未来任务。它保存的是相对稳定、可复用、有价值的信息。例如用户偏好。项目技术栈。长期任务目标。已确认的业务规则。重要历史决策。可复用的执行经验。长期记忆不能随便写入。因为它会影响未来很多次回答。如果错误信息进入长期记忆后面会反复污染结果。例如用户习惯使用 FastAPI。 当前项目默认数据库是 SQLite。 用户希望文章保持 14 个章节结构。 用户不希望正文里出现某些固定字样。这些内容如果被确认过就可能适合成为长期记忆。但下面这些内容不适合长期保存一次性验证码。 临时调试日志。 用户随手输入的测试内容。 未经确认的模型推断。 过期的任务状态。 敏感密钥或密码。长期记忆的关键不是多。而是准确、稳定、可控。五、向量记忆适合语义召回有些记忆不适合只靠关键词查找。例如用户过去做过的项目、历史方案、文档片段、问题解决记录。这些内容可能需要语义检索。这时可以使用向量记忆。基本流程是记忆内容 ↓ 生成 embedding ↓ 写入向量存储 ↓ 根据当前问题检索相关记忆 ↓ 拼接到上下文向量记忆适合处理历史任务经验。项目知识片段。用户长期偏好说明。复杂问题解决过程。文档摘要和结论。但向量记忆也有风险。因为语义相似不等于一定相关。检索出来的记忆可能过期。也可能和当前任务冲突。所以向量记忆不能直接无脑塞进 Prompt。还需要过滤、打分、去重和时间判断。六、Memory 和 RAG 有什么区别Memory 和 RAG 很容易被混在一起。因为它们都可能使用向量检索。但二者关注点不同。RAG 更偏知识检索。Memory 更偏上下文延续。可以这样理解RAG从外部知识库中找资料。 Memory从用户、任务和历史交互中找上下文。例如用户问某个政策条款系统从知识库中检索政策文档。这是 RAG。用户之前说过自己只关心 Python 方案系统在后续回答里优先给 Python 示例。这是 Memory。当然两者可以结合。例如一个企业知识库助手既需要 RAG 检索公司文档也需要 Memory 记住用户部门、常用系统和历史任务偏好。但工程设计上最好不要把它们混成一个模块。RAG 管知识。Memory 管上下文。边界清楚系统才容易维护。七、什么内容适合进入 MemoryMemory 不是越多越好。适合进入 Memory 的信息通常有几个特点。第一它相对稳定。例如用户长期偏好、项目技术栈、业务规则。第二它未来可复用。例如历史决策、常用工作方式、已验证方案。第三它对后续回答有帮助。例如用户不喜欢复杂框架后续方案就应该优先轻量。第四它风险可控。不涉及敏感密钥、一次性凭证、私人隐私或不应保存的信息。可以保存的例子用户正在维护一个 AI Scaffold 系列文章。 文章风格偏工程化不希望过度营销。 项目默认以 Python 为主。 用户希望每篇文章都保留清晰章节结构。这些记忆可以帮助系统后续更好地协作。但它们也应该支持查看、修改和删除。八、什么内容不应该进入 Memory不适合进入 Memory 的内容更重要。因为 Memory 一旦保存错误或敏感内容影响会持续存在。不应该保存的内容包括API Key。密码。Token。验证码。身份证号等敏感身份信息。支付信息。临时错误日志。一次性命令输出。未经确认的模型猜测。明显过期的状态。例如用户可能喜欢某个框架。 用户应该正在做某个项目。 用户也许不想使用某种数据库。这种未经确认的推断不应该直接写入长期记忆。更好的做法是先询问或等待用户明确表达。Memory 系统要有一个基本原则宁可少记也不要乱记。尤其不要把敏感信息变成长期上下文。九、Memory 需要生命周期Memory 不是永久保存的垃圾桶。它需要生命周期管理。常见生命周期包括session仅当前会话有效。 task仅当前任务有效。 project当前项目内有效。 user长期用户偏好。 global系统级公共规则。不同生命周期对应不同存储策略。例如短期任务状态可以任务结束后清理。项目技术栈可以在项目范围内保留。用户偏好可以长期保留但要支持用户删除。系统级规则一般来自配置不应该由模型随意写入。Memory 还应该支持过期时间。例如classMemoryItem:content:strscope:strcreated_at:strexpires_at:str|Nonesource:str有了生命周期Memory 才不会无限膨胀。也不会让过期信息长期影响结果。十、Memory 写入要有策略Memory 写入不能完全交给模型自由决定。模型可以提出候选记忆。但系统应该有策略层做判断。例如用户明确表达偏好 - 可以作为候选记忆。 内容包含敏感字段 - 拒绝保存。 内容只是临时状态 - 不进入长期记忆。 内容和已有记忆冲突 - 标记待确认。 内容来自模型推断 - 默认不保存。可以设计一个 Memory PolicyclassMemoryPolicy:defshould_save(self,memory_candidate:dict)-bool:...defshould_retrieve(self,memory_item:dict,context:dict)-bool:...defshould_expire(self,memory_item:dict)-bool:...Memory Policy 是记忆系统的安全阀。没有策略层Memory 很容易变成随手写入的数据库。十一、Memory 召回也要有边界保存记忆只是第一步。更难的是在合适的时候召回合适的记忆。如果每次都召回所有记忆Prompt 会变得臃肿。如果召回不相关记忆模型回答会被干扰。如果召回敏感记忆还可能造成隐私问题。一个合理的召回流程可以是当前任务 ↓ 判断需要哪些 scope ↓ 按关键词或向量检索候选记忆 ↓ 按相关性、时间、权限过滤 ↓ 去重和压缩 ↓ 拼接到 Prompt例如当前任务只是一次普通问答就不一定需要召回项目级长期记忆。当前任务是修改某个项目代码才需要召回项目技术栈、目录结构和历史决策。召回的关键不是多。而是准。十二、Memory 和 Repository 的关系上一篇文章讲了 Repository。Repository 负责数据访问。Memory 负责记忆语义。两者关系可以这样理解Memory Service ↓ Memory Repository ↓ Database / Vector StoreRepository 不决定什么应该成为记忆。它只负责存取。Memory Service 或 Memory Policy 才决定是否保存。保存到哪里。什么时间过期。当前任务是否召回。召回后如何压缩。如果把这些逻辑都写进 Repository数据访问层就会变得太重。如果完全不使用 RepositoryMemory 的存储逻辑又会散落在 Agent 和 Workflow 里。所以更合理的做法是Repository 管存储。Memory 管语义和策略。Agent 使用 Memory 提供的上下文。十三、Memory 在 AI Scaffold 里的位置在 AI Scaffold 中Memory 可以作为独立模块。项目结构可以这样设计app/ ├── agents/ │ └── assistant_agent.py ├── workflows/ │ └── research_workflow.py ├── memory/ │ ├── __init__.py │ ├── short_term.py │ ├── long_term.py │ ├── vector_memory.py │ ├── memory_service.py │ ├── policy.py │ └── retriever.py ├── repositories/ │ └── memory_repository.py ├── models/ │ └── memory_item.py └── config/ └── settings.py其中short_term.py管当前会话或任务上下文。long_term.py管长期用户偏好和项目记忆。vector_memory.py管向量化和语义召回。memory_service.py对外提供统一接口。policy.py负责保存、召回、过期和敏感信息判断。retriever.py负责检索候选记忆。Agent 不直接操作数据库。Workflow 不直接拼接所有历史记录。它们通过 Memory Service 获取当前任务需要的上下文。这样 Memory 就不会变成一堆散落在业务代码里的临时逻辑。十四、总结Memory 是 AI 应用从一次性问答走向长期协作的重要能力。但 Memory 不是简单保存聊天记录。它需要区分短期记忆、长期记忆和向量记忆。也需要和 RAG、Repository、Agent、Workflow 保持清晰边界。一个合理的 Memory 设计至少应该做到不把聊天记录直接等同于记忆。区分短期上下文和长期偏好。支持向量召回但不滥用向量召回。明确什么内容可以保存。明确什么内容不能保存。支持生命周期、过期和删除。支持用户查看和修正重要记忆。不保存 API Key、密码、验证码等敏感信息。不把未经确认的模型推断写入长期记忆。通过 Repository 管理存储通过 Policy 管理策略。让 Agent 使用 Memory而不是让 Agent 随意写 Memory。对于 AI Scaffold 来说Memory 层不是为了让系统记住所有事情。而是为了让系统在可控、安全、可解释的范围内延续上下文。真正有价值的记忆不是越多越好。而是该记的能记住不该记的坚决不记过期的及时忘掉。下一篇文章可以继续讨论日志与可观测性AI 应用上线后如何追踪模型调用、Tool 调用、Token 成本、错误链路和用户反馈才能真正排查线上问题。
