制全景解析:從分類到工程落地)
大模型越來越“聰明”但一個關(guān)鍵短板始終繞不過去記性不好。對話一長就忘前文換個會話就忘記用戶偏好甚至剛聊完的內(nèi)容再問就“失憶”。這背后涉及的正是大模型記憶機(jī)制問題。近期清華大學(xué)唐杰團(tuán)隊對大模型記憶展開系統(tǒng)性梳理嘗試構(gòu)建一份“記憶全景圖”。本文會從概念分類、生命周期、工程落地和常見誤區(qū)幾個維度把這塊內(nèi)容拆開講清楚同時會結(jié)合實際開發(fā)場景給出可參考的實現(xiàn)思路。1. 為什么大模型記憶成了研究焦點先聊一個常見場景你正在用某個 AI 助手做項目規(guī)劃前面已經(jīng)告訴它“團(tuán)隊 5 人、預(yù)算 30 萬、周期三個月”但聊到后面它突然問“你們團(tuán)隊多少人”。這種體驗很糟糕根源就是大模型缺少穩(wěn)定的記憶能力。如果往前倒幾年大模型主要靠上下文窗口來“記住”信息。你給它多少 token它就只能看多少 token窗口之外的內(nèi)容一概不認(rèn)。隨著 Agent、多輪對話、個性化推薦等應(yīng)用爆發(fā)這種“窗口即記憶”的方式已經(jīng)很難滿足需求。原因很簡單上下文窗口有長度限制不可能無限塞內(nèi)容。每次請求都重新編碼全部歷史成本高、時延大。重要信息混雜在無關(guān)內(nèi)容里模型難以有效提取。Agent 場景中多個任務(wù)之間需要共享狀態(tài)和知識單純靠上下文窗口無法勝任。所以越來越多的研究者和工程師開始把目光投向記憶機(jī)制。唐杰團(tuán)隊這次梳理的大模型記憶全景本質(zhì)上是在回答三個問題大模型的記憶到底有哪些類型不同類型記憶分別用什么技術(shù)實現(xiàn)記憶在生命周期中如何存儲、更新和遺忘下面我們從概念出發(fā)逐步展開。2. 大模型記憶全景一張分類地圖要理解大模型記憶首先得建立分類體系。不同論文、不同框架對記憶的叫法不完全一致但大致可以從兩個維度切分記憶的載體和記憶的時效。2.1 按載體劃分參數(shù)記憶與非參數(shù)記憶參數(shù)記憶指的是把知識直接編碼進(jìn)模型權(quán)重里。模型在預(yù)訓(xùn)練階段見過大量語料這些語料中的事實、常識、語言模式被壓縮到參數(shù)中。比如你問“中國的首都是哪里”模型能答出來靠的就是參數(shù)記憶。參數(shù)記憶的特點是靜態(tài)存儲模型訓(xùn)練完成后基本固定。更新成本高重新訓(xùn)練或微調(diào)需要大量算力。不可解釋我們無法直接查看某個知識存在哪個參數(shù)里。非參數(shù)記憶則存儲在模型外部通常以文本、向量、數(shù)據(jù)庫等形式存在。模型在推理時通過檢索、讀取等方式獲取相關(guān)信息再組織成回答。典型的實現(xiàn)就是 RAG檢索增強(qiáng)生成和各類外部記憶庫。非參數(shù)記憶的特點是動態(tài)更新增刪改查相對靈活??山忉屝詮?qiáng)可以追溯答案來源。依賴檢索質(zhì)量和上下文組織方式。2.2 按時效劃分短期記憶、長期記憶與工作記憶這種劃分在認(rèn)知科學(xué)中很常見大模型記憶也借鑒了這套框架。短期記憶一般指當(dāng)前會話上下文也就是上下文窗口內(nèi)的內(nèi)容。模型能“看到”的對話歷史、用戶輸入、工具返回結(jié)果都屬于短期記憶。工作記憶指模型在執(zhí)行當(dāng)前任務(wù)時臨時持有的信息比如在推理過程中需要記住中間結(jié)果、狀態(tài)變量、子目標(biāo)等。它比短期記憶更強(qiáng)調(diào)“正在被操作”的信息。長期記憶指跨會話、跨任務(wù)持久化存儲的信息。比如用戶的長期偏好、歷史交互記錄、領(lǐng)域知識庫、項目背景資料等。長期記憶通常存放在外部存儲中需要的時候再加載進(jìn)來。唐杰團(tuán)隊在綜述中會把這套框架進(jìn)一步細(xì)化形成類似“感知記憶—工作記憶—長期記憶”的分層結(jié)構(gòu)。這種分層最大的價值在于它告訴我們大模型記憶不是單一技術(shù)可以解決的問題而是一套組合方案。2.3 不同記憶層級的核心作用為了更直觀地理解下面用一張表格總結(jié)各記憶層級的特點記憶類型載體時效典型技術(shù)典型場景參數(shù)記憶模型權(quán)重靜態(tài)預(yù)訓(xùn)練、微調(diào)常識問答、知識問答短期記憶上下文窗口會話級Prompt 拼接、窗口管理多輪對話、代碼補(bǔ)全工作記憶上下文狀態(tài)任務(wù)級ReAct、狀態(tài)機(jī)、緩存復(fù)雜推理、Agent 決策長期記憶外部存儲持久化向量庫、知識圖譜、數(shù)據(jù)庫個性化推薦、用戶畫像可以看到每種記憶都有自己擅長的戰(zhàn)場。參數(shù)記憶負(fù)責(zé)“通識”短期記憶負(fù)責(zé)“當(dāng)前”長期記憶負(fù)責(zé)“持續(xù)”。真正好用的 AI 應(yīng)用往往是這幾種記憶協(xié)同工作的結(jié)果。3. 記憶的生命周期從寫入到遺忘有了分類接下來要關(guān)注動態(tài)過程。記憶不是一次性寫入就完事了它有一個完整的生命周期編碼、存儲、檢索、更新、遺忘。3.1 編碼如何把信息變成記憶編碼階段解決的是“信息怎么存”的問題。不同類型的記憶編碼方式完全不同。參數(shù)記憶的編碼依賴預(yù)訓(xùn)練和微調(diào)本質(zhì)上是把海量文本中的統(tǒng)計規(guī)律壓縮到參數(shù)里這個過程成本極高不適合頻繁更新。短期記憶的編碼相對簡單就是把對話歷史、用戶輸入按順序拼接進(jìn)上下文窗口。需要注意 token 數(shù)量控制超出窗口上限就得做截斷或壓縮。長期記憶的編碼則要考慮結(jié)構(gòu)化和向量化。對于文本類信息最常用的方式是對原始文本做清洗和切分。使用 Embedding 模型把文本塊轉(zhuǎn)成向量。將向量和元數(shù)據(jù)一起存入向量數(shù)據(jù)庫。舉個例子假設(shè)我們要記錄用戶的偏好“喜歡簡潔風(fēng)格的代碼注釋”可以先把它轉(zhuǎn)成向量存儲結(jié)構(gòu)大致如下{ id: pref_001, content: 用戶偏好簡潔風(fēng)格的代碼注釋, embedding: [0.0123, -0.0456, ...], timestamp: 2025-06-01T10:30:00Z, source: user_chat }3.2 存儲記憶放在哪里存儲層決定記憶的持久性和擴(kuò)展性。不同場景適合不同的存儲方案向量數(shù)據(jù)庫適合語義檢索典型選型有 Milvus、Chroma、Qdrant、Weaviate 等。鍵值存儲適合存取結(jié)構(gòu)化狀態(tài)比如 Redis。關(guān)系數(shù)據(jù)庫適合存儲用戶畫像、交互記錄等結(jié)構(gòu)化數(shù)據(jù)。知識圖譜適合存儲實體關(guān)系和復(fù)雜邏輯知識。實際工程中經(jīng)常是多種存儲混用。向量庫負(fù)責(zé)語義召回關(guān)系庫負(fù)責(zé)結(jié)構(gòu)化查詢Redis 負(fù)責(zé)高頻臨時狀態(tài)。3.3 檢索如何找到有用的記憶存儲本身沒有價值能被準(zhǔn)確檢索出來才有價值。檢索質(zhì)量直接影響模型輸出質(zhì)量。常見的檢索策略包括向量相似度檢索把當(dāng)前問題轉(zhuǎn)成向量在向量庫中找最相似的記憶。關(guān)鍵詞檢索基于 BM25 等傳統(tǒng)算法適合精確匹配場景?;旌蠙z索向量檢索和關(guān)鍵詞檢索結(jié)合先召回再重排。結(jié)構(gòu)化查詢按用戶 ID、時間范圍等條件過濾。一個常見的誤區(qū)是把所有歷史都塞進(jìn)上下文這樣既浪費 token又可能引入噪聲。更好的做法是只檢索與當(dāng)前問題相關(guān)的記憶片段控制數(shù)量和質(zhì)量。3.4 更新與遺忘記憶不是只增不改記憶需要更新因為用戶偏好會變知識會過時。如果一個用戶以前喜歡長文報告后來改成喜歡簡潔結(jié)論系統(tǒng)還一直推送冗長內(nèi)容體驗就很差。記憶更新的難點在于如何判斷舊記憶需要被替換。常用策略有根據(jù)時間衰減過期記憶降低權(quán)重。根據(jù)顯式反饋用戶明確表示“我不喜歡 A 了以后用 B”直接覆蓋舊記憶。根據(jù)一致性沖突新記憶與舊記憶矛盾時以新記憶為準(zhǔn)并記錄沖突日志。遺忘機(jī)制同樣重要。無限制地存儲所有記憶會帶來存儲成本、檢索噪聲和隱私風(fēng)險。定期清理低質(zhì)量、過期、敏感的記憶是長期記憶系統(tǒng)必須考慮的問題。4. 從研究到工程Agent 記憶如何落地理論框架梳理清楚后我們來聊聊工程實現(xiàn)。這部分對開發(fā)者最有參考價值我會結(jié)合 LangChain、LangGraph 等主流工具給出可落地的思路。4.1 LangChain 的對話記憶模塊LangChain 提供了多種 Conversation Memory 類分別適用于不同場景ConversationBufferMemory保留全部歷史消息。ConversationBufferWindowMemory只保留最近 K 輪消息。ConversationSummaryMemory用摘要代替完整歷史。ConversationSummaryBufferMemory綜合摘要和原始消息超過閾值后轉(zhuǎn)摘要。VectorStoreRetrieverMemory基于向量庫的記憶存取。來看一個簡單的示例使用ConversationBufferWindowMemory控制上下文規(guī)模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) # 構(gòu)建對話鏈 conversation ConversationChain( llmllm, memorymemory, verboseTrue ) # 連續(xù)對話 print(conversation.predict(input你好我叫張三是一名后端工程師)) print(conversation.predict(input請記住我的職業(yè))) print(conversation.predict(input我叫什么名字做什么工作))在這個例子中模型只能記住最近兩輪內(nèi)容。優(yōu)點是 token 消耗可控缺點是超過窗口范圍的早期信息會被丟棄。4.2 LangGraph 的持久化狀態(tài)記憶如果說 LangChain 的 Memory 類解決的是“會話內(nèi)歷史”LangGraph 則把記憶提升到了“跨線程、跨會話”的層次。LangGraph 的核心思路是通過StateGraph管理狀態(tài)狀態(tài)可以持久化到外部存儲也可以從外部恢復(fù)。結(jié)合CheckpointerAgent 可以在多次交互之間保持狀態(tài)。來看一個簡化示例思路是使用 SQLite 或內(nèi)存 Checkpointer 保存對話狀態(tài)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) # 第一次調(diào)用寫入狀態(tài) config {configurable: {thread_id: user_001}} result app.invoke( {messages: [第一次對話], user_profile: {name: 張三, role: 后端工程師}}, configconfig ) print(result) # 第二次調(diào)用狀態(tài)自動恢復(fù) result2 app.invoke( {messages: [第二次對話]}, configconfig ) print(result2)解釋一下關(guān)鍵點thread_id相當(dāng)于記憶的命名空間同一個線程 ID 之間狀態(tài)共享。user_profile可以看作長期記憶的結(jié)構(gòu)化載體。Checkpointer 負(fù)責(zé)狀態(tài)持久化LangGraph 會自行處理恢復(fù)邏輯。在生產(chǎn)環(huán)境中可以將InMemorySaver換成SqliteSaver或PostgresSaver實現(xiàn)真正的跨服務(wù)持久化。4.3 長期記憶的向量檢索實現(xiàn)下面給出一個更貼近生產(chǎn)環(huán)境的長時記憶方案用戶信息先向量化再通過檢索召回。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 開發(fā)后端服務(wù)) save_memory(u_1001, 用戶希望代碼注釋保持簡潔) res recall_memory(u_1001, 這個用戶喜歡什么技術(shù)棧) print(res)在這個實現(xiàn)中記憶以向量形式存儲在 Chroma 中每次寫入時帶上了用戶 ID 元數(shù)據(jù)檢索時先按用戶過濾再做向量相似度匹配兼顧了精確性和語義靈活性。5. 記憶增強(qiáng)與幻覺抑制討論大模型記憶繞不開一個重要話題幻覺。很多幻覺問題本質(zhì)上源于記憶缺失或記憶錯誤。5.1 記憶缺失導(dǎo)致幻覺當(dāng)模型不知道某個事實但又必須回答時它可能會“編造”一個看似合理的答案。比如被問到某個小眾 API 的用法訓(xùn)練數(shù)據(jù)里沒有覆蓋模型就可能給出不存在的參數(shù)名。這時候如果有可靠的外部記憶文檔庫、知識庫提供依據(jù)幻覺概率會明顯下降。5.2 記憶沖突導(dǎo)致幻覺另一種情況是記憶之間相互矛盾。比如上下文里用戶已經(jīng)說過“我不用 Java”但長期記憶中還存著“用戶是 Java 工程師”。檢索時兩條信息都出現(xiàn)在上下文里模型可能產(chǎn)生混亂。解決沖突的策略包括給記憶打上時間戳優(yōu)先采用新記憶。設(shè)計記憶覆蓋機(jī)制檢測到?jīng)_突時更新舊記憶。在 Prompt 中明確記憶優(yōu)先級比如“用戶當(dāng)前陳述優(yōu)先于歷史記錄”。5.3 如何讓模型“自知之明”一個實用的做法是讓模型在不確定時主動承認(rèn)“我不知道”而不是強(qiáng)行作答。這需要在 Prompt 環(huán)節(jié)做好約束。同時在記憶系統(tǒng)中記錄“未知問題集”當(dāng)模型多次回答不出同一類問題時把該問題加入知識補(bǔ)充隊列后續(xù)通過 RAG 等方式補(bǔ)充資料。如果檢索到的記憶與當(dāng)前問題無關(guān)請直接回答“缺乏相關(guān)信息無法準(zhǔn)確回答”不要自行推測。這種機(jī)制相當(dāng)于給模型增加了一層“記憶邊界判斷”能有效降低無效幻覺。6. 大模型記憶系統(tǒng)的常見問題與排查思路在理解和實現(xiàn)大模型記憶時開發(fā)者常會遇到一系列問題。下面整理一張排查表問題現(xiàn)象常見原因解決思路多輪對話中模型丟失早期信息短期記憶窗口太小增大窗口或使用摘要記憶模型回答與用戶歷史偏好矛盾長期記憶檢索不準(zhǔn)確優(yōu)化 Embedding 模型增加結(jié)構(gòu)化過濾記憶寫入后檢索不到向量索引未刷新或元數(shù)據(jù)過濾錯誤檢查索引狀態(tài)調(diào)試查詢條件上下文越來越長響應(yīng)變慢歷史消息無限制累積添加 token 閾值使用摘要壓縮用戶更換偏好后仍沿用舊記憶記憶更新機(jī)制缺失加入沖突檢測和時間衰減策略向量檢索結(jié)果相關(guān)性差文本切分粒度不合理調(diào)整切分長度和重疊區(qū)域隱私數(shù)據(jù)被錯誤召回缺少權(quán)限過濾在元數(shù)據(jù)中加入權(quán)限標(biāo)簽檢索時強(qiáng)制過濾在實際項目中我建議先做小規(guī)模原型驗證重點評估記憶寫入質(zhì)量和檢索準(zhǔn)確率這兩個指標(biāo)不要一上來就追求復(fù)雜架構(gòu)。7. 最佳實踐構(gòu)建可靠的大模型記憶系統(tǒng)從研究到落地記憶系統(tǒng)設(shè)計有一些通用原則。這里分享幾條工程經(jīng)驗供大家參考。7.1 分層記憶架構(gòu)不要把記憶全放在一個籃子里。推薦采用三層架構(gòu)會話層維護(hù)當(dāng)前對話上下文使用窗口或摘要控制長度。用戶層存儲用戶長期偏好、個人資料和歷史行為。領(lǐng)域?qū)哟鎯F(tuán)隊知識庫、產(chǎn)品文檔、項目規(guī)范等。每一層獨立存儲按需加載。這樣可以避免無關(guān)信息污染上下文。7.2 記憶寫入質(zhì)量控制記憶不是錄得越多越好。低質(zhì)量記憶會干擾檢索。建議在寫入前做質(zhì)量過濾去除口語化噪聲和無意義消息。提取關(guān)鍵信息而不是保存整段對話。對重要信息標(biāo)記優(yōu)先級提高召回權(quán)重。7.3 檢索結(jié)果的多樣性控制檢索時不要只看 top1建議召回 top3 到 top5讓模型自行判斷哪條信息更有用。也可以加入重排序環(huán)節(jié)用更精細(xì)的模型對候選記憶排序。7.4 隱私與權(quán)限邊界記憶系統(tǒng)通常涉及用戶隱私數(shù)據(jù)必須重視權(quán)限控制。至少做到記憶數(shù)據(jù)加密存儲。按用戶 ID 隔離記憶空間。檢索時強(qiáng)制帶權(quán)限過濾條件。提供記憶刪除入口尊重用戶“被遺忘權(quán)”。7.5 可觀測性設(shè)計記憶系統(tǒng)一旦出問題排查成本很高。建議為每條記憶寫入日志記錄來源、時間、寫入模型、檢索命中情況。出現(xiàn)問題時可以快速定位是寫入失敗、檢索失敗還是模型理解失敗。8. 值得關(guān)注的后續(xù)方向唐杰團(tuán)隊梳理的大模型記憶全景給后續(xù)研究提供了比較清晰的坐標(biāo)系。從當(dāng)前趨勢看有幾個方向值得繼續(xù)關(guān)注原生長上下文與記憶協(xié)同。模型上下文窗口不斷變大但“長”不等于“記得住”。如何在大窗口中高效定位關(guān)鍵信息仍然是待解決問題。未來可能出現(xiàn)上下文管理器和記憶管理器協(xié)同工作的架構(gòu)。記憶壓縮與抽象。不是所有信息都值得原樣保存。未來記憶系統(tǒng)可能會像人腦一樣把具體事件抽象成高層次的規(guī)律和偏好丟棄細(xì)節(jié)保留本質(zhì)。多模態(tài)記憶?,F(xiàn)在的記憶大多圍繞文本展開但隨著多模態(tài)大模型普及圖片、音頻、視頻信息也需要納入記憶體系這對存儲和檢索都提出了更高要求。記憶評估基準(zhǔn)。目前業(yè)界缺乏統(tǒng)一的大模型記憶評測標(biāo)準(zhǔn)。不同團(tuán)隊各做各的很難橫向?qū)Ρ?。唐杰團(tuán)隊的綜述為建立評估體系提供了理論框架后續(xù)可能會推動相關(guān) benchmark 的建設(shè)。對于開發(fā)者來說我的建議是不要等到記憶體系成熟再上車?,F(xiàn)階段完全可以從簡單方案開始比如一個向量庫加一個抽象接口先把核心鏈路跑通再逐步加入更新、遺忘、沖突處理等機(jī)制。9. 結(jié)語大模型記憶正在從一個模糊的概念逐步發(fā)展成一套有分類、有生命周期、有工程實現(xiàn)的技術(shù)體系。清華唐杰團(tuán)隊這次的記憶全景梳理最大價值在于給研究者、開發(fā)者和產(chǎn)品經(jīng)理提供了一張統(tǒng)一的地圖——有了地圖才不會迷路。對于正在做 AI 應(yīng)用開發(fā)的工程師希望本文關(guān)于記憶分類、生命周期、LangChain/LangGraph 實踐和問題排查的部分能幫你更快地搭建出“記得住、找得到、用得上”的記憶系統(tǒng)。如果你正準(zhǔn)備改造自己的 Agent 應(yīng)用建議從“記憶寫入—檢索—更新”這條主線入手先跑通最小閉環(huán)再逐步增強(qiáng)。記住一個原則記憶系統(tǒng)的目標(biāo)不是存下所有信息而是讓模型在正確的時刻找到正確的信息。祝大家都能造出“記性好、忘性少”的智能應(yīng)用。有好的思路和踩坑經(jīng)驗歡迎在評論區(qū)交流。