小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

【AI大模型應用開發(fā)】以LangChain為例:從短期記憶實戰(zhàn),到如何讓AI應用保持長期記憶的探索

 小張學AI 2024-04-22 發(fā)布于山東
公眾號內(nèi)文章一覽


在AI應用中,無論是多輪對話場景、RAG場景還是AI Agent場景中,記憶能力都是不可或缺的一部分。然而,記憶能力是目前大模型的短板,所以,現(xiàn)在很多框架,諸如 LangChain、MetaGPT 等,都封裝了自己的記憶模塊,以方便開發(fā)者實現(xiàn)自己大模型應用的記憶功能。

之前我們簡單概覽了一下 LangChain 的 Memory 模塊(【AI大模型應用開發(fā)】【LangChain系列】3. 一文了解LangChain的記憶模塊(理論實戰(zhàn)+細節(jié))),那只是在多輪對話場景中,簡單的取最近幾次的對話歷史作為記憶。這是最簡單的使用記憶的方法,也是短期記憶的一種。

本文我們來系統(tǒng)看下實現(xiàn)大模型應用記憶的方法,包括短期記憶和長期記憶。還是以LangChain為例來進行實戰(zhàn)。

0. LangChain中 Memory 實戰(zhàn)

我這里將記憶簡單理解為對話歷史,查詢歷史等歷史記錄。

0.1 記憶封裝羅列

在 LangChain 中提供了多種獲取記憶的封裝,例如ConversationBufferMemoryConversationBufferWindowMemoryConversationTokenBufferMemory等。

簡單羅列如下:

  • · ConversationBufferMemory可以理解為通用的將全部的歷史記錄取出來。

  • · ConversationBufferWindowMemory可以理解為滑動窗口,每次只取最近的K條記錄。

  • · ConversationTokenBufferMemory可以理解為控制每次取的歷史記錄的Token數(shù)。

  • · ConversationSummaryMemory: 對上下文做摘要

  • · ConversationSummaryBufferMemory: 保存 Token 數(shù)限制內(nèi)的上下文,對更早的做摘要

  • · VectorStoreRetrieverMemory: 將 Memory 存儲在向量數(shù)據(jù)庫中,根據(jù)用戶輸入檢索回最相關(guān)的部分

  • · ConversationEntityMemory:保存一些實體信息,例如從輸入中找出一個人名,保存這個人的信息。

  • · ConversationKGMemory:將歷史記錄按知識圖譜的形式保存和查詢

這里面的大部分記憶封裝,之前咱們已經(jīng)學習過了,這里不再重復。詳細的使用教程可以參考我之前的文章:【AI大模型應用開發(fā)】【LangChain系列】3. 一文了解LangChain的記憶模塊(理論實戰(zhàn)+細節(jié))。

下面看下 VectorStoreRetrieverMemory 的使用和實現(xiàn)效果。

0.2 實踐:VectorStoreRetrieverMemory的使用

0.2.1 完整代碼

from langchain.memory import VectorStoreRetrieverMemory
from langchain_openai import ChatOpenAI
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import ConversationChain
from langchain.prompts import PromptTemplate

vectorstore = Chroma(embedding_function=OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
memory = VectorStoreRetrieverMemory(retriever=retriever)

memory.save_context({"input""我喜歡學習"}, {"output""你真棒"})
memory.save_context({"input""我不喜歡玩兒"}, {"output""你可太棒了"})

PROMPT_TEMPLATE = """以下是人類和 AI 之間的友好對話。AI 話語多且提供了許多來自其上下文的具體細節(jié)。如果 AI 不知道問題的答案,它會誠實地說不知道。

以前對話的相關(guān)片段:
{history}

(如果不相關(guān),你不需要使用這些信息)

當前對話:
人類:{input}
AI:
"""


prompt = PromptTemplate(input_variables=["history""input"], template=PROMPT_TEMPLATE)
chat_model = ChatOpenAI()
conversation_with_summary = ConversationChain(
    llm=chat_model,
    prompt=prompt,
    memory=memory,
    verbose=True
)

print(conversation_with_summary.predict(input="你好,我叫同學小張,你叫什么"))
print(conversation_with_summary.predict(input="我喜歡干什么?"))

0.2.2 代碼解釋

(1)代碼中我們使用了 VectorStoreRetrieverMemory 作為記憶存儲和獲取的模塊。它既然是向量存儲和查詢,所以接收參數(shù):retriever=retriever,必須要穿給它一個向量數(shù)據(jù)庫才能工作。

(2)然后使用了 ConversationChain 作為對話的Chain。它接收一個 memory = memory 參數(shù)設(shè)置,指定使用的記憶類型。默認是最普通的 ConversationBufferMemory 類型。

(3)什么時候會去檢索記憶呢?在Chain運行 invoke 的一開始,就加載了。源碼如下:

可以看到,最后就是用用戶的輸入,去向量數(shù)據(jù)庫中檢索相關(guān)的片段作為需要的記憶。

0.2.3 運行效果展示

第一個問題,檢索到的內(nèi)容不相關(guān),但是也得檢索出一條。

第二個問題,檢索到的內(nèi)容相關(guān),用檢索到的內(nèi)容回答問題。

1. 如何讓AI應用具備長期記憶?

我這里將“長期記憶”理解為持久化記憶或者長上下文記憶。也就是兩種形式的記憶我都認為是“長期記憶”:

  • · 第一種:持久化記憶,對話歷史等歷史記錄持久化保存,不會隨著進程的退出而消失。例如保存成功文件或存儲進數(shù)據(jù)庫等。

  • · 第二種:長上下文記憶,當歷史記錄特別多時,如何從歷史記錄中找出有用的記憶,而不是只關(guān)注最近的幾條歷史記錄。

1.1 LangChain 中的記憶模塊是否具有長期記憶的能力?

上面羅列的和實戰(zhàn)的 LangChain 中的記憶模塊,ConversationBufferMemory、 ConversationBufferWindowMemory、ConversationTokenBufferMemory 看起來都無法實現(xiàn)長期記憶的能力:無法持久化(看源碼,底層都是一個List類型,保存到內(nèi)存,隨著進程消亡而消亡),也沒法查詢長的上下文。

 ConversationSummaryMemoryConversationSummaryBufferMemory 在一定程度上能提供更多的記憶信息(因為其對之前的歷史記錄做了總結(jié)壓縮),所以在某些上下文不是特別長的場景中,還是可以用一用來實現(xiàn)簡單的長期記憶能力的。

ConversationEntityMemory、ConversationKGMemory一個只保存實體信息,一個將歷史記錄組織成知識圖譜,會對長上下文場景中的長時記憶功能非常有用。它可以從全局的角度將用戶提問中的實體或相關(guān)知識作補充,而不是關(guān)注最近的幾次對話。

VectorStoreRetrieverMemory應該是最好和最能實現(xiàn)長期記憶能力的類型了。一方面,它是向量數(shù)據(jù)庫存儲,可以方便的持久化數(shù)據(jù),另一方面,它的向量檢索能力,本來就是針對用戶提問檢索出最相關(guān)的文檔片段,不受長上下文的窗口限制。但是其檢索的相關(guān)片段之間是否存在信息缺失等,會影響長時記憶的準確性,從而影響最終的結(jié)果。

所以,ConversationEntityMemory、ConversationKGMemory + VectorStoreRetrieverMemory 是否可以一試?三者結(jié)合,保持相關(guān)片段的相關(guān)性,同時利用實體關(guān)系和知識圖譜進行補充,是否可以更好地實現(xiàn)長時記憶的能力?感興趣的可以一起討論~

1.2 關(guān)于讓AI應用具備長期記憶的一些研究

1.2.1 記憶思考:回憶和后思考使LLM具有長期記憶

論文原文:Think-in-Memory: Recalling and Post-thinking Enable LLMs with Long-Term Memory

這篇文章提出了一種名為TiM(Think-in-Memory)的記憶機制,旨在使LLM在對話過程中保持記憶,存儲歷史思考。TiM包括兩個關(guān)鍵階段:在生成回復之前,LLM從記憶中回想相關(guān)思考;在生成回復之后,LLM進行后思考并將歷史和新思考結(jié)合起來更新記憶。

下圖描述了TiM方法的使用方式:

(1)在回答第二個問題時,需要考慮問題1的內(nèi)容,從問題1中推理出答案,而后在回答問題2。 (2)在回答第三個問題時,需要同時考慮問題1和問題2,從問題1和問題2中推理出答案,而后再回答問題3。

這就導致了問題的存在:問題1被推理了兩遍,兩遍的結(jié)果還可能不一樣,導致最終的錯誤。

而TiM的思路,是將每一個問題的思考也存起來,這樣,在回答問題3時,可以使用問題2之前的思考,避免重新思考問題1,從而避免多次思考結(jié)果不一致導致的錯誤。

具體步驟如下:

總的原理是,將相關(guān)的記憶放到一起,例如上圖中,關(guān)于book的談話放到index 0中,關(guān)于moive的談話放到index 1中。

如何將相關(guān)內(nèi)容放到一起的?論文中實現(xiàn)了一種基于局部敏感哈希(LSH)的存儲系統(tǒng),用于高效地存儲和檢索大規(guī)模的向量數(shù)據(jù)。LSH的作用是將每個向量映射到一個哈希索引,相似的向量有更高的概率被映射到相同的哈希索引。

而相同的哈希索引可以將用戶問題固定到某一塊記憶中,然后只在這一塊記憶中進行向量檢索,大大提高了檢索效率。

這篇文章還是值得精讀一下的,數(shù)據(jù)的組織方式和索引方式都比較高級,很有啟發(fā)。

1.2.2 遞歸總結(jié)在大型語言模型中實現(xiàn)長期對話記憶

論文原文:Recursively Summarizing Enables Long-Term Dialogue Memory in Large Language Models

這篇文章提出了一種遞歸總結(jié)的方法,用于增強大模型的長期記憶能力,以解決在長對話中無法回憶過去信息和生成不一致響應的問題。該方法首先刺激LLM記憶小的對話上下文,然后遞歸地使用先前的記憶和后續(xù)的上下文生成新的記憶。

其流程如下:

簡單概括,就是:上一輪的內(nèi)容總結(jié) + 本輪的問題回答 = 本輪的內(nèi)容總結(jié)。本輪的內(nèi)容總結(jié) + 下輪的問題回答 = 下輪的內(nèi)容總結(jié)。...... 不斷迭代。與 LangChain中ConversationSummaryMemory 的實現(xiàn)很類似。

這種方法每一輪都要總結(jié)一次,也就是調(diào)用一次大模型,使用成本很高啊...... 實際生產(chǎn)中應該落地比較難。

1.2.3 更多研究

更多關(guān)于AI應用 Memory 的研究可以參考下面這個文章:

張澤宇,公眾號:RUC AI EngineLLM-based Agent Memory相關(guān)論文集錦

加個TODO,還沒看完,大家可以一起看。

如果覺得本文對你有幫助,麻煩點個贊和關(guān)注唄 ~~~


  • · 大家好,我是 同學小張,日常分享AI知識和實戰(zhàn)案例

  • · 歡迎 點贊 + 關(guān)注 ??,持續(xù)學習,持續(xù)干貨輸出。

    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多