Agentic AI:構(gòu)建長期記憶

如果你用過大型語言模型(LLMs),你就會知道它們是無狀態(tài)的。如果沒用過,可以把它們想象成沒有短期記憶的東西。
舉個例子,就像電影《記憶碎片》(Memento)里的主角,他總是需要靠便利貼上的信息來提醒自己發(fā)生了什么,拼湊出下一步該做什么。
要和LLMs對話,我們每次互動時都需要不斷提醒它們之前的對話內(nèi)容。
實現(xiàn)我們所說的“短期記憶”或狀態(tài)其實很簡單。我們只需要把之前的幾組問答對抓出來,包含在每次調(diào)用里就行。
但長期記憶完全是另一回事。
為了讓LLM能調(diào)取正確的事實、理解之前的對話并連接信息,我們需要構(gòu)建一些相當復雜的系統(tǒng)。

這篇文章會深入探討這個問題,而不是堆砌一堆術(shù)語,分析構(gòu)建一個高效系統(tǒng)需要什么,討論不同的架構(gòu)選擇,并看看有哪些開源和云服務供應商能幫上忙。
思考解決方案
讓我們先來梳理一下為LLMs構(gòu)建記憶的思路,以及要讓它高效需要些什么。
首先,我們需要LLM能調(diào)取舊消息,告訴我們之前說了什么。比如,我們可以問它:“你之前推薦我去斯德哥爾摩的那家餐廳叫什么名字?”這就是基本的信息提取。
如果你完全沒接觸過LLM系統(tǒng)的開發(fā),你可能首先會想到把所有對話直接塞進上下文窗口(context window),讓LLM自己去理解。
但這種策略會讓LLM很難分辨哪些信息重要、哪些不重要,可能會導致它“幻覺”(hallucinate)出答案。而且一旦對話量變大,你還得限制對話的長度。
你的第二個想法可能是存儲每條消息,連同摘要一起,然后用語義搜索(比如RAG里的檢索)在有查詢時提取信息。

這跟構(gòu)建標準的簡單檢索系統(tǒng)差不多。
但問題在于,如果只是簡單地存儲消息(不做任何額外處理),一旦規(guī)模擴大,你會遇到內(nèi)存膨脹、事實過時或矛盾、以及不斷需要清理的向量數(shù)據(jù)庫(vector database)的問題。
你可能還需要知道事情發(fā)生的時間,這樣才能問:“你什么時候跟我提過第一家餐廳?”這意味著你需要某種程度的時間推理(temporal reasoning)。
這可能會促使你加入帶有時間戳的元數(shù)據(jù)(metadata),甚至實現(xiàn)一個自我編輯系統(tǒng)(self-editing system),來更新和總結(jié)輸入內(nèi)容。
雖然更復雜,但一個自我編輯系統(tǒng)可以在需要時更新事實并使其失效。
如果你繼續(xù)深入思考,你可能還希望LLM能連接不同的事實(執(zhí)行多跳推理,multi-hop reasoning)并識別模式。
比如,你可以問:“我今年去了多少場音樂會?”或者“根據(jù)這些,你覺得我的音樂品味怎么樣?”這可能會讓你嘗試使用知識圖譜(knowledge graphs)。
組織解決方案
這個問題變得如此復雜,促使人們更好地組織它。大多數(shù)團隊似乎把長期記憶分成兩部分:小型事實(pocket-sized facts)和之前的對話的長期記憶(long-span memory)。

對于第一部分,小型事實,我們可以看看ChatGPT的記憶系統(tǒng)作為一個例子。
要構(gòu)建這種記憶,他們可能會用一個分類器(classifier)來判斷一條消息是否包含需要存儲的事實。

然后,他們會把事實分類到一個預定義的類別(比如個人資料、偏好或項目),如果這個事實和已有的事實類似就更新,否則就創(chuàng)建一個新的。
另一部分,長期記憶,意味著存儲所有消息并總結(jié)整個對話,以便之后可以參考。這在ChatGPT里也有,但和小型事實記憶一樣,你得手動啟用。
如果你自己來構(gòu)建這個,你需要決定保留多少細節(jié),同時注意之前提到的內(nèi)存膨脹和不斷增長的數(shù)據(jù)庫問題。
標準架構(gòu)解決方案
如果我們看看其他人在做什么,這里有兩個主要的架構(gòu)選擇:向量(vectors)和知識圖譜(knowledge graphs)。
我一開始提到了一種基于檢索的方法。這通常是大家開始時的首選。檢索使用向量存儲(vector store,通常還支持稀疏搜索,sparse search),這意味著它同時支持語義搜索和關(guān)鍵詞搜索。
檢索一開始很簡單:你把文檔嵌入(embed),然后根據(jù)用戶的問題來提取。
但正如我們之前說的,如果只是簡單地這樣做,每個輸入都是不可變的。這意味著即使事實變了,文本還是會留在那兒。
這里可能出現(xiàn)的問題包括提取到多個互相矛盾的事實,這會讓代理(agent)困惑。最壞的情況是,相關(guān)事實可能被埋在一堆檢索到的文本里。
代理也不知道某件事是什么時候說的,或者它指的是過去還是未來。
正如我們之前討論的,有辦法解決這些問題。
你可以搜索舊的記憶并更新它們,給元數(shù)據(jù)加上時間戳,定期總結(jié)對話來幫助LLM理解提取到的細節(jié)的上下文。
但用向量,你還會面臨數(shù)據(jù)庫不斷增長的問題。最終,你得清理舊數(shù)據(jù)或壓縮它們,這可能會讓你丟掉有用的細節(jié)。
如果我們看看知識圖譜(KGs),它們把信息表示成實體(節(jié)點,nodes)和它們之間的關(guān)系(邊,edges)的網(wǎng)絡(luò),而不是像向量那樣的非結(jié)構(gòu)化文本。

KGs不會直接覆蓋數(shù)據(jù),而是可以給舊事實加一個“失效日期”(invalid_at date),這樣你還能追溯它的歷史。它們通過圖遍歷(graph traversals)來提取信息,讓你可以跨多個跳躍追蹤關(guān)系。
不過正如我們提到的,用向量也可以通過提取舊事實并更新來做到類似的事。
但因為KGs能跳躍到連接的節(jié)點并以更結(jié)構(gòu)化的方式保持事實更新,它們在多跳推理(multi-hop reasoning)上往往表現(xiàn)更好。
不過KGs也有自己的挑戰(zhàn)。隨著規(guī)模擴大,基礎(chǔ)設(shè)施會變得更復雜,你可能在深層遍歷時注意到更高的延遲,因為系統(tǒng)需要找很遠的信息。
維護成本也可能很高。
總之,不管是用向量還是KG為基礎(chǔ)的解決方案,人們通常會選擇更新記憶而不是不斷添加新的,加入我們之前看到的“小型事實”的特定分類功能。
他們還經(jīng)常用LLMs來在存儲消息前總結(jié)和提取信息。
回到最初的目標(同時擁有小型記憶和長期記憶),你可以混合使用RAG和KG的方法來達到目的。
當前供應商解決方案(即插即用)
我會介紹幾種不同的獨立解決方案,幫助你設(shè)置記憶,分析它們的工作方式、使用的架構(gòu),以及它們的框架成熟度如何。

長期記憶供應商 —— 我總是把資源收集在這個倉庫里 | 圖片由作者提供
構(gòu)建高級LLM應用還是很新的東西,所以這些解決方案大多在過去一兩年才發(fā)布。
剛開始時,了解這些框架的構(gòu)建方式會很有幫助,能讓你知道自己可能需要什么。
正如之前提到的,它們大多分為KG優(yōu)先或向量優(yōu)先兩類。

記憶供應商功能 —— 我總是把資源收集在這個倉庫里 | 圖片由作者提供
先看看Zep(或Graphiti),一個基于KG的解決方案,他們用LLMs來提取、添加、使失效和更新節(jié)點(實體)和邊(帶時間戳的關(guān)系)。

當你提問時,它會執(zhí)行語義和關(guān)鍵詞搜索來找到相關(guān)節(jié)點,然后遍歷到連接的節(jié)點來提取相關(guān)事實。
如果有新消息帶來矛盾的事實,它會更新節(jié)點,同時保留舊事實。
這和Mem0不同,Mem0是一個基于向量的解決方案,它會把提取的事實疊加起來,并用一個自我編輯系統(tǒng)來識別并完全覆蓋無效事實。
Letta的工作方式類似,但還包括額外的功能,比如核心記憶(core memory),它會存儲對話摘要以及定義需要填充內(nèi)容的塊(或類別)。
所有解決方案都能設(shè)置類別,我們可以定義系統(tǒng)需要捕獲什么。比如,如果你建一個冥想應用,一個類別可以是用戶的“當前心情”。這些就是我們之前在ChatGPT系統(tǒng)里看到的小型事實分類。
我之前提到過,向量優(yōu)先的方法在時間推理和多跳推理上有問題。
比如,如果我說兩個月后要搬到柏林,但之前提到住在斯德哥爾摩和加利福尼亞,幾個月后我問系統(tǒng)時,它能明白我現(xiàn)在住在柏林嗎?
它能識別模式嗎?用知識圖譜,信息已經(jīng)結(jié)構(gòu)化,LLM更容易利用所有可用上下文。
用向量,隨著信息增長,噪聲可能會變得太大,系統(tǒng)難以連接信息點。
Letta和Mem0雖然總體上更成熟,但這兩個問題還是可能出現(xiàn)。
對于知識圖譜,關(guān)注點在于規(guī)模擴大時的基礎(chǔ)設(shè)施復雜性,以及如何管理越來越多的信息。
雖然我還沒徹底測試所有方案,也還缺一些數(shù)據(jù)(比如延遲數(shù)字),但我想提一下它們在企業(yè)安全方面的處理,以防你想在公司內(nèi)部使用。

記憶云安全 —— 我總是把資源收集在這個倉庫里 | 圖片由作者提供
我找到的唯一SOC 2 Type 2認證的云選項是Zep。不過,很多方案可以自托管,這種情況下安全性取決于你自己的基礎(chǔ)設(shè)施。
這些解決方案還很新。你可能最終會自己構(gòu)建,但建議先試試這些,看看它們?nèi)绾翁幚磉吘壡闆r。
使用供應商的經(jīng)濟性
為LLM應用添加功能很棒,但你得記住這也會增加成本。
我總是會提到實施某項技術(shù)的經(jīng)濟性,這次也不例外。這是我在添加任何東西時首先會檢查的。我需要知道這對應用的單位經(jīng)濟性(unit economics)會有什么長期影響。
大多數(shù)供應商解決方案會讓你免費開始。但一旦消息量超過幾千條,成本就會迅速增加。

“估算”每條消息的記憶定價 —— 我總是把資源收集在這個倉庫里 | 圖片由作者提供
記住,如果你的組織每天有幾百次對話,通過這些云解決方案發(fā)送每條消息時,定價會開始累積。
一開始用云解決方案可能比較理想,然后隨著規(guī)模擴大轉(zhuǎn)到自托管。
你也可以嘗試混合方式。
比如,自己實現(xiàn)一個分類器來決定哪些消息值得存為事實,以降低成本,同時把其他內(nèi)容推到自己的向量存儲里,定期壓縮和總結(jié)。
話雖如此,在上下文窗口里使用小型事實應該比直接粘貼5000個token的歷史記錄要好。提前給LLM相關(guān)事實也有助于減少幻覺(hallucinations),總體上降低LLM生成成本。
注意事項
重要的是要注意,即使有了記憶系統(tǒng),也別指望完美。這些系統(tǒng)有時還是會產(chǎn)生幻覺或漏掉答案。
與其追求100%的準確率,不如接受不完美,這樣能省去很多挫敗感。
目前沒有哪個系統(tǒng)能達到完美準確,至少現(xiàn)在還沒有。研究顯示,幻覺是LLMs的固有問題。即使加了記憶層,也無法完全消除這個問題。
本文轉(zhuǎn)載自??AI大模型觀察站??,作者:AI研究生

















