大模型越来越“聪明”但一个关键短板始终绕不过去记性不好。对话一长就忘前文换个会话就忘记用户偏好甚至刚聊完的内容再问就“失忆”。这背后涉及的正是大模型记忆机制问题。近期清华大学唐杰团队对大模型记忆展开系统性梳理尝试构建一份“记忆全景图”。本文会从概念分类、生命周期、工程落地和常见误区几个维度把这块内容拆开讲清楚同时会结合实际开发场景给出可参考的实现思路。1. 为什么大模型记忆成了研究焦点先聊一个常见场景你正在用某个 AI 助手做项目规划前面已经告诉它“团队 5 人、预算 30 万、周期三个月”但聊到后面它突然问“你们团队多少人”。这种体验很糟糕根源就是大模型缺少稳定的记忆能力。如果往前倒几年大模型主要靠上下文窗口来“记住”信息。你给它多少 token它就只能看多少 token窗口之外的内容一概不认。随着 Agent、多轮对话、个性化推荐等应用爆发这种“窗口即记忆”的方式已经很难满足需求。原因很简单上下文窗口有长度限制不可能无限塞内容。每次请求都重新编码全部历史成本高、时延大。重要信息混杂在无关内容里模型难以有效提取。Agent 场景中多个任务之间需要共享状态和知识单纯靠上下文窗口无法胜任。所以越来越多的研究者和工程师开始把目光投向记忆机制。唐杰团队这次梳理的大模型记忆全景本质上是在回答三个问题大模型的记忆到底有哪些类型不同类型记忆分别用什么技术实现记忆在生命周期中如何存储、更新和遗忘下面我们从概念出发逐步展开。2. 大模型记忆全景一张分类地图要理解大模型记忆首先得建立分类体系。不同论文、不同框架对记忆的叫法不完全一致但大致可以从两个维度切分记忆的载体和记忆的时效。2.1 按载体划分参数记忆与非参数记忆参数记忆指的是把知识直接编码进模型权重里。模型在预训练阶段见过大量语料这些语料中的事实、常识、语言模式被压缩到参数中。比如你问“中国的首都是哪里”模型能答出来靠的就是参数记忆。参数记忆的特点是静态存储模型训练完成后基本固定。更新成本高重新训练或微调需要大量算力。不可解释我们无法直接查看某个知识存在哪个参数里。非参数记忆则存储在模型外部通常以文本、向量、数据库等形式存在。模型在推理时通过检索、读取等方式获取相关信息再组织成回答。典型的实现就是 RAG检索增强生成和各类外部记忆库。非参数记忆的特点是动态更新增删改查相对灵活。可解释性强可以追溯答案来源。依赖检索质量和上下文组织方式。2.2 按时效划分短期记忆、长期记忆与工作记忆这种划分在认知科学中很常见大模型记忆也借鉴了这套框架。短期记忆一般指当前会话上下文也就是上下文窗口内的内容。模型能“看到”的对话历史、用户输入、工具返回结果都属于短期记忆。工作记忆指模型在执行当前任务时临时持有的信息比如在推理过程中需要记住中间结果、状态变量、子目标等。它比短期记忆更强调“正在被操作”的信息。长期记忆指跨会话、跨任务持久化存储的信息。比如用户的长期偏好、历史交互记录、领域知识库、项目背景资料等。长期记忆通常存放在外部存储中需要的时候再加载进来。唐杰团队在综述中会把这套框架进一步细化形成类似“感知记忆—工作记忆—长期记忆”的分层结构。这种分层最大的价值在于它告诉我们大模型记忆不是单一技术可以解决的问题而是一套组合方案。2.3 不同记忆层级的核心作用为了更直观地理解下面用一张表格总结各记忆层级的特点记忆类型载体时效典型技术典型场景参数记忆模型权重静态预训练、微调常识问答、知识问答短期记忆上下文窗口会话级Prompt 拼接、窗口管理多轮对话、代码补全工作记忆上下文状态任务级ReAct、状态机、缓存复杂推理、Agent 决策长期记忆外部存储持久化向量库、知识图谱、数据库个性化推荐、用户画像可以看到每种记忆都有自己擅长的战场。参数记忆负责“通识”短期记忆负责“当前”长期记忆负责“持续”。真正好用的 AI 应用往往是这几种记忆协同工作的结果。3. 记忆的生命周期从写入到遗忘有了分类接下来要关注动态过程。记忆不是一次性写入就完事了它有一个完整的生命周期编码、存储、检索、更新、遗忘。3.1 编码如何把信息变成记忆编码阶段解决的是“信息怎么存”的问题。不同类型的记忆编码方式完全不同。参数记忆的编码依赖预训练和微调本质上是把海量文本中的统计规律压缩到参数里这个过程成本极高不适合频繁更新。短期记忆的编码相对简单就是把对话历史、用户输入按顺序拼接进上下文窗口。需要注意 token 数量控制超出窗口上限就得做截断或压缩。长期记忆的编码则要考虑结构化和向量化。对于文本类信息最常用的方式是对原始文本做清洗和切分。使用 Embedding 模型把文本块转成向量。将向量和元数据一起存入向量数据库。举个例子假设我们要记录用户的偏好“喜欢简洁风格的代码注释”可以先把它转成向量存储结构大致如下{ id: pref_001, content: 用户偏好简洁风格的代码注释, embedding: [0.0123, -0.0456, ...], timestamp: 2025-06-01T10:30:00Z, source: user_chat }3.2 存储记忆放在哪里存储层决定记忆的持久性和扩展性。不同场景适合不同的存储方案向量数据库适合语义检索典型选型有 Milvus、Chroma、Qdrant、Weaviate 等。键值存储适合存取结构化状态比如 Redis。关系数据库适合存储用户画像、交互记录等结构化数据。知识图谱适合存储实体关系和复杂逻辑知识。实际工程中经常是多种存储混用。向量库负责语义召回关系库负责结构化查询Redis 负责高频临时状态。3.3 检索如何找到有用的记忆存储本身没有价值能被准确检索出来才有价值。检索质量直接影响模型输出质量。常见的检索策略包括向量相似度检索把当前问题转成向量在向量库中找最相似的记忆。关键词检索基于 BM25 等传统算法适合精确匹配场景。混合检索向量检索和关键词检索结合先召回再重排。结构化查询按用户 ID、时间范围等条件过滤。一个常见的误区是把所有历史都塞进上下文这样既浪费 token又可能引入噪声。更好的做法是只检索与当前问题相关的记忆片段控制数量和质量。3.4 更新与遗忘记忆不是只增不改记忆需要更新因为用户偏好会变知识会过时。如果一个用户以前喜欢长文报告后来改成喜欢简洁结论系统还一直推送冗长内容体验就很差。记忆更新的难点在于如何判断旧记忆需要被替换。常用策略有根据时间衰减过期记忆降低权重。根据显式反馈用户明确表示“我不喜欢 A 了以后用 B”直接覆盖旧记忆。根据一致性冲突新记忆与旧记忆矛盾时以新记忆为准并记录冲突日志。遗忘机制同样重要。无限制地存储所有记忆会带来存储成本、检索噪声和隐私风险。定期清理低质量、过期、敏感的记忆是长期记忆系统必须考虑的问题。4. 从研究到工程Agent 记忆如何落地理论框架梳理清楚后我们来聊聊工程实现。这部分对开发者最有参考价值我会结合 LangChain、LangGraph 等主流工具给出可落地的思路。4.1 LangChain 的对话记忆模块LangChain 提供了多种 Conversation Memory 类分别适用于不同场景ConversationBufferMemory保留全部历史消息。ConversationBufferWindowMemory只保留最近 K 轮消息。ConversationSummaryMemory用摘要代替完整历史。ConversationSummaryBufferMemory综合摘要和原始消息超过阈值后转摘要。VectorStoreRetrieverMemory基于向量库的记忆存取。来看一个简单的示例使用ConversationBufferWindowMemory控制上下文规模from langchain.memory import ConversationBufferWindowMemory from langchain.chains import ConversationChain from langchain_ollama import ChatOllama # 初始化大模型这里以本地 Ollama 为例 llm ChatOllama(modelqwen2.5:7b, temperature0.7) # 窗口记忆最多保留最近 2 轮对话 memory ConversationBufferWindowMemory(k2, return_messagesTrue) # 构建对话链 conversation ConversationChain( llmllm, memorymemory, verboseTrue ) # 连续对话 print(conversation.predict(input你好我叫张三是一名后端工程师)) print(conversation.predict(input请记住我的职业)) print(conversation.predict(input我叫什么名字做什么工作))在这个例子中模型只能记住最近两轮内容。优点是 token 消耗可控缺点是超过窗口范围的早期信息会被丢弃。4.2 LangGraph 的持久化状态记忆如果说 LangChain 的 Memory 类解决的是“会话内历史”LangGraph 则把记忆提升到了“跨线程、跨会话”的层次。LangGraph 的核心思路是通过StateGraph管理状态状态可以持久化到外部存储也可以从外部恢复。结合CheckpointerAgent 可以在多次交互之间保持状态。来看一个简化示例思路是使用 SQLite 或内存 Checkpointer 保存对话状态from langgraph.graph import StateGraph, START, END from langgraph.checkpoint.memory import InMemorySaver from typing import TypedDict, Annotated class AgentState(TypedDict): messages: Annotated[list, lambda a, b: a b] user_profile: dict # 定义一个简单的工作流 def process_message(state: AgentState): # 模拟从长期记忆读取用户画像 profile state.get(user_profile, {}) # 模拟处理逻辑 new_message 已记录 profile.get(name, 未知用户) return {messages: [new_message]} # 使用 InMemorySaver 作为 Checkpointer saver InMemorySaver() graph StateGraph(AgentState) graph.add_node(process, process_message) graph.add_edge(START, process) graph.add_edge(process, END) app graph.compile(checkpointersaver) # 第一次调用写入状态 config {configurable: {thread_id: user_001}} result app.invoke( {messages: [第一次对话], user_profile: {name: 张三, role: 后端工程师}}, configconfig ) print(result) # 第二次调用状态自动恢复 result2 app.invoke( {messages: [第二次对话]}, configconfig ) print(result2)解释一下关键点thread_id相当于记忆的命名空间同一个线程 ID 之间状态共享。user_profile可以看作长期记忆的结构化载体。Checkpointer 负责状态持久化LangGraph 会自行处理恢复逻辑。在生产环境中可以将InMemorySaver换成SqliteSaver或PostgresSaver实现真正的跨服务持久化。4.3 长期记忆的向量检索实现下面给出一个更贴近生产环境的长时记忆方案用户信息先向量化再通过检索召回。import chromadb from chromadb.utils import embedding_functions # 初始化 Chroma 客户端 client chromadb.PersistentClient(path./memory_store) collection client.get_or_create_collection( nameuser_preferences, embedding_functionembedding_functions.DefaultEmbeddingFunction() ) # 写入记忆 def save_memory(user_id, content): collection.add( ids[f{user_id}_{hash(content)}], documents[content], metadatas[{user_id: user_id, timestamp: 2025-06-01}] ) # 检索记忆 def recall_memory(user_id, query, top_k3): results collection.query( query_texts[query], n_resultstop_k, where{user_id: user_id} ) return results[documents][0] # 示例 save_memory(u_1001, 用户偏好使用 Python 和 FastAPI 开发后端服务) save_memory(u_1001, 用户希望代码注释保持简洁) res recall_memory(u_1001, 这个用户喜欢什么技术栈) print(res)在这个实现中记忆以向量形式存储在 Chroma 中每次写入时带上了用户 ID 元数据检索时先按用户过滤再做向量相似度匹配兼顾了精确性和语义灵活性。5. 记忆增强与幻觉抑制讨论大模型记忆绕不开一个重要话题幻觉。很多幻觉问题本质上源于记忆缺失或记忆错误。5.1 记忆缺失导致幻觉当模型不知道某个事实但又必须回答时它可能会“编造”一个看似合理的答案。比如被问到某个小众 API 的用法训练数据里没有覆盖模型就可能给出不存在的参数名。这时候如果有可靠的外部记忆文档库、知识库提供依据幻觉概率会明显下降。5.2 记忆冲突导致幻觉另一种情况是记忆之间相互矛盾。比如上下文里用户已经说过“我不用 Java”但长期记忆中还存着“用户是 Java 工程师”。检索时两条信息都出现在上下文里模型可能产生混乱。解决冲突的策略包括给记忆打上时间戳优先采用新记忆。设计记忆覆盖机制检测到冲突时更新旧记忆。在 Prompt 中明确记忆优先级比如“用户当前陈述优先于历史记录”。5.3 如何让模型“自知之明”一个实用的做法是让模型在不确定时主动承认“我不知道”而不是强行作答。这需要在 Prompt 环节做好约束。同时在记忆系统中记录“未知问题集”当模型多次回答不出同一类问题时把该问题加入知识补充队列后续通过 RAG 等方式补充资料。如果检索到的记忆与当前问题无关请直接回答“缺乏相关信息无法准确回答”不要自行推测。这种机制相当于给模型增加了一层“记忆边界判断”能有效降低无效幻觉。6. 大模型记忆系统的常见问题与排查思路在理解和实现大模型记忆时开发者常会遇到一系列问题。下面整理一张排查表问题现象常见原因解决思路多轮对话中模型丢失早期信息短期记忆窗口太小增大窗口或使用摘要记忆模型回答与用户历史偏好矛盾长期记忆检索不准确优化 Embedding 模型增加结构化过滤记忆写入后检索不到向量索引未刷新或元数据过滤错误检查索引状态调试查询条件上下文越来越长响应变慢历史消息无限制累积添加 token 阈值使用摘要压缩用户更换偏好后仍沿用旧记忆记忆更新机制缺失加入冲突检测和时间衰减策略向量检索结果相关性差文本切分粒度不合理调整切分长度和重叠区域隐私数据被错误召回缺少权限过滤在元数据中加入权限标签检索时强制过滤在实际项目中我建议先做小规模原型验证重点评估记忆写入质量和检索准确率这两个指标不要一上来就追求复杂架构。7. 最佳实践构建可靠的大模型记忆系统从研究到落地记忆系统设计有一些通用原则。这里分享几条工程经验供大家参考。7.1 分层记忆架构不要把记忆全放在一个篮子里。推荐采用三层架构会话层维护当前对话上下文使用窗口或摘要控制长度。用户层存储用户长期偏好、个人资料和历史行为。领域层存储团队知识库、产品文档、项目规范等。每一层独立存储按需加载。这样可以避免无关信息污染上下文。7.2 记忆写入质量控制记忆不是录得越多越好。低质量记忆会干扰检索。建议在写入前做质量过滤去除口语化噪声和无意义消息。提取关键信息而不是保存整段对话。对重要信息标记优先级提高召回权重。7.3 检索结果的多样性控制检索时不要只看 top1建议召回 top3 到 top5让模型自行判断哪条信息更有用。也可以加入重排序环节用更精细的模型对候选记忆排序。7.4 隐私与权限边界记忆系统通常涉及用户隐私数据必须重视权限控制。至少做到记忆数据加密存储。按用户 ID 隔离记忆空间。检索时强制带权限过滤条件。提供记忆删除入口尊重用户“被遗忘权”。7.5 可观测性设计记忆系统一旦出问题排查成本很高。建议为每条记忆写入日志记录来源、时间、写入模型、检索命中情况。出现问题时可以快速定位是写入失败、检索失败还是模型理解失败。8. 值得关注的后续方向唐杰团队梳理的大模型记忆全景给后续研究提供了比较清晰的坐标系。从当前趋势看有几个方向值得继续关注原生长上下文与记忆协同。模型上下文窗口不断变大但“长”不等于“记得住”。如何在大窗口中高效定位关键信息仍然是待解决问题。未来可能出现上下文管理器和记忆管理器协同工作的架构。记忆压缩与抽象。不是所有信息都值得原样保存。未来记忆系统可能会像人脑一样把具体事件抽象成高层次的规律和偏好丢弃细节保留本质。多模态记忆。现在的记忆大多围绕文本展开但随着多模态大模型普及图片、音频、视频信息也需要纳入记忆体系这对存储和检索都提出了更高要求。记忆评估基准。目前业界缺乏统一的大模型记忆评测标准。不同团队各做各的很难横向对比。唐杰团队的综述为建立评估体系提供了理论框架后续可能会推动相关 benchmark 的建设。对于开发者来说我的建议是不要等到记忆体系成熟再上车。现阶段完全可以从简单方案开始比如一个向量库加一个抽象接口先把核心链路跑通再逐步加入更新、遗忘、冲突处理等机制。9. 结语大模型记忆正在从一个模糊的概念逐步发展成一套有分类、有生命周期、有工程实现的技术体系。清华唐杰团队这次的记忆全景梳理最大价值在于给研究者、开发者和产品经理提供了一张统一的地图——有了地图才不会迷路。对于正在做 AI 应用开发的工程师希望本文关于记忆分类、生命周期、LangChain/LangGraph 实践和问题排查的部分能帮你更快地搭建出“记得住、找得到、用得上”的记忆系统。如果你正准备改造自己的 Agent 应用建议从“记忆写入—检索—更新”这条主线入手先跑通最小闭环再逐步增强。记住一个原则记忆系统的目标不是存下所有信息而是让模型在正确的时刻找到正确的信息。祝大家都能造出“记性好、忘性少”的智能应用。有好的思路和踩坑经验欢迎在评论区交流。