在大模型应用中,通常如何实现长短期记忆机制?
大模型本身无跨请求持久状态——「记得住」全靠应用层把信息写进外部存储,再在下一次请求里检索或拼回 Prompt。本篇讲面试答法;Agent 三层落地见 [Agent 记忆分层实践](/docs/ai/Agent/Agent 记忆分层实践);概念见 Agent 核心概念与架构。
先定边界:记忆 ≠ RAG
| 记忆(Memory) | RAG | |
|---|---|---|
| 回答谁 | 这个用户 / 这次会话 / 当前任务 | 共享知识(手册、政策、文档库) |
| 典型内容 | 偏好、称呼、上轮结论、任务中间态 | 公司退货规则、API 文档、产品说明 |
| 隔离 | 按 user_id / session_id | 通常全员共享检索 |
| 真源 | 业务事实仍应查库,不靠「模型记得」 | 检索片段是知识真源 |
面试一句话:RAG 补「公知」;记忆补「私 State」——二者常并存,别混为一谈。
短期记忆:本轮 / 本会话
目标: 让模型看见「刚才说了什么、工具返回了什么、任务进行到哪」。
| 实现 | 做法 | 适用 |
|---|---|---|
| 全量对话历史 | 每轮把 messages[] 原样塞进 API | 轮次少、窗口够 |
| 滑动窗口 | 只保留最近 N 条或最近 K token | 最常见;超窗就裁 |
| 会话摘要(Summary Buffer) | 旧轮次 LLM 压成一段 summary,与最近消息并存 | 长对话、客服、Agent 多步 |
| Scratchpad / State | 任务变量、工具观察、规划中间结果单独存 state | Agent、工作流 |
| Checkpointer | 按 thread_id 持久化 state,刷新后续跑 | LangGraph 等编排框架 |
用户新消息
↓
从存储取出:最近 N 条消息 +(可选)本会话 summary + 当前 task state
↓
拼成 Prompt → 调 LLM → 更新 messages / summary / state
短期记忆口诀: 窗口管「现在必须看见的」;摘要管「被裁掉但不能全丢的」;state 管「任务进行到哪」。
长期记忆:跨会话 / 跨天
目标: 新开一个会话窗口,仍知道「他是谁、偏好什么、以前确认过什么」。
| 实现 | 做法 | 适用 |
|---|---|---|
| 结构化画像(Profile) | KV / 用户表存 prefs、facts | 称呼、语言、回答风格 |
| 向量 episodic 记忆 | 历史对话/事件 embedding 入库,按 query 检索 Top-K | 「上次你说过…」类回忆 |
| 摘要归档 | 会话结束时写一段 session summary 进长期库 | 低成本跨会话 |
| 业务库真源 | 订单、工单、会员等级直接查 DB | 事实类问题必走这条 |
| 框架 Store | LangGraph Store、Mem0、自研 memory service | 跨 thread 读写 |
长期写入要有门禁——不是每句话都落库:
- 只写稳定偏好(「叫我小王」「喜欢简短」)
- 一次性任务、工具原始 JSON、未确认推断不写
- 支持覆盖与遗忘(合规、改偏好)
- 租户隔离:按
user_id分库分 key
分层总览(推荐答法)
本轮 Prompt 上下文
├─ 短期:最近消息 + 工具观察 + task state(窗口 / checkpointer)
├─ 中期:本会话 summary(窗口裁掉部分的压缩)
└─ 长期:用户画像 +(可选)向量 episodic 检索
外部真源:DB / RAG —— 库存、政策、订单状态不以「记忆」为准
和 [Agent 记忆分层实践](/docs/ai/Agent/Agent 记忆分层实践) 的对应:
| 面试说法 | 实践篇名称 |
|---|---|
| 短期 / 工作记忆 | 工作记忆(窗口 + state) |
| 中期 | 会话摘要 |
| 长期 | 长期画像 |
| 事实 | 业务真源 |
典型组装流程
1. 加载长期:profile = get_user_profile(user_id)
2. 加载短期:messages, summary = load_thread(thread_id)
3. (可选)episodic 检索:memories = search_memory(user_id, query)
4. 拼 Prompt:
[系统] + [用户画像] + [相关长期记忆] + [会话摘要] + [最近消息] + [新用户输入]
5. LLM 回复
6. 更新短期:append messages;超窗则 summarize
7. 若有稳定新偏好 → 抽取后写长期(白名单字段)
Agent 场景还要把 tool observation 当短期记忆的一部分,但别无限追加——和消息一样受窗口或摘要约束。
常见坑
| 坑 | 表现 | 缓解 |
|---|---|---|
| 无限加长 context | 贵、慢、噪声、超窗截断 | 窗口 + 摘要 + 分层 |
| 把 RAG 当记忆 | 共享库检索解决不了「他叫我什么」 | 用户态 profile / episodic |
| 把记忆当真源 | 答错库存、订单状态 | 事实查业务库 |
| 无写入门禁 | 幻觉偏好被固化 | 白名单、确认、可删 |
| 跨用户泄漏 | A 的偏好出现在 B | user_id 隔离 + no-leak 评测 |
面试参考答法(60~90 秒)
大模型无内置持久记忆,长短记忆都是应用层设计。
短期靠会话 state:最近 N 轮对话、工具返回、任务中间变量放进上下文;对话长了用滑动窗口 + LLM 摘要,避免无限堆 token。Agent 里还会用 checkpointer 按 thread 续跑。
长期跨会话:结构化用户画像存 KV 或业务表;需要「回忆具体经历」时可把历史 embedding 进向量库按 query 检索。写入要有门禁,只落稳定偏好和已确认事实,业务事实仍查 DB,不靠模型「记得」。
和 RAG 分工:RAG 补共享知识,记忆补这个用户/这次任务的状态。多数产品三层就够——窗口、摘要、画像。
延伸阅读
| 篇 | 关系 |
|---|---|
| [Agent 记忆分层实践](/docs/ai/Agent/Agent 记忆分层实践) | 窗口 / 摘要 / 画像代码与评测 |
| [LangGraph 编排实践](/docs/ai/Agent/LangGraph 编排实践) | checkpointer 与 Store |
| RAG 与检索增强 | 与记忆的分工 |
面试速记
- 模型无状态: 记忆 = 外部存 + 下次拼回 Prompt;不是微调权重。
- 短期: 滑动窗口、会话 summary、Agent state / checkpointer。
- 长期: 结构化画像、向量 episodic、会话归档;写入白名单 + 可遗忘。
- ≠ RAG: 记忆是用户/会话私 State;RAG 是共享知识库。
- 事实走真源: 订单、库存、政策查库,不写进「记得」。