LangChain 提供的記憶機制能有效提升對話式 AI 的效能,讓系統理解並回應連續提問,而非僅處理單獨的問答。文章以虛擬客服代理 Eva 為例,展示短期記憶如何使對話更自然流暢,並探討 LangChain 的記憶操作核心:讀取和儲存。文章詳細介紹了使用 MongoDB 儲存聊天記錄、使用 ConversationBufferMemory 進行記憶管理,以及如何在 LangChain Expression Language (LCEL) 中直接新增記憶到鏈,並提供程式碼範例。同時,文章也涵蓋了 LangChain 中各種記憶體型別,如 ConversationBufferWindowMemory、ConversationSummaryMemory、ConversationSummaryBufferMemory 和 ConversationTokenBufferMemory,比較它們的特性和適用場景,讓開發者能根據需求選擇合適的記憶體管理策略。

短期記憶在問答系統中的應用

在開發對話式人工智慧系統時,短期記憶(Short-Term Memory, STM)的應用能夠顯著提升系統的互動性和連貫性。想像一個名為Eva的虛擬客服代理,她能夠在與使用者的對話中,利用短期記憶來理解和回應連續的問題。

案例分析:Eva的對話流程

  1. 使用者查詢:使用者詢問電子產品的退貨政策。

    • 使用者: “電子產品的退貨政策是多久?”
    • Eva: “電子產品的退貨政策是30天。”
  2. 後續查詢:使用者接著詢問服裝類別商品的退貨政策。

    • 使用者: “那服裝類別商品呢?”
    • Eva(利用STM): “服裝類別商品的退貨政策是45天。您還想了解其他類別嗎?”

在這個例子中,Eva透過運用短期記憶,能夠無縫地繼續對話,預測使用者可能提出的後續問題。這種流暢性得益於短期記憶的有效佈署,使對話式代理能夠將對話視為一個連貫的互動過程,而非孤立的問答。

LangChain中的記憶機制

LangChain提供了簡便的方法來為大語言模型(LLMs)新增記憶功能。如圖所示,每個記憶系統在鏈中負責兩個基本操作:讀取和儲存。

記憶操作的核心

  1. 讀取記憶:在收集初始使用者資料後,但在執行之前,鏈會從其記憶中檢索資訊,並將其新增到使用者的輸入中。

  2. 儲存資訊:在鏈完成處理後,但在傳回答案之前,鏈會將當前執行的輸入和輸出寫入記憶,以便在未來的執行中參考。

建立記憶系統的關鍵選擇

  1. 狀態儲存方法:選擇適合的資料函式庫或儲存方案來儲存對話狀態。

  2. 查詢記憶狀態的方法:根據應用需求,設計查詢記憶內容的方式。

狀態儲存

生成式AI模型的基礎記憶本質上是結構化的聊天訊息序列。這些訊息可以儲存在臨時的記憶體列表中,或固定在更持久的資料函式庫中。對於長期儲存的需求,可以利用多種資料函式庫整合方案,以簡化流程,避免手動整合的麻煩。

使用MongoDB儲存聊天記錄

# 提供連線到MongoDB資料函式庫的連線字串
connection_string = "mongodb://mongo_user:password123@mongo:27017"
chat_message_history = MongoDBChatMessageHistory(
    session_id="test_session",
    connection_string=connection_string,
    database_name="my_db",
    collection_name="chat_histories",
)

# 新增使用者和AI的訊息
chat_message_history.add_user_message("我喜歡程式設計!")
chat_message_history.add_ai_message("你喜歡程式設計的哪個方面?")

# 檢視聊天記錄
print(chat_message_history.messages)
# [HumanMessage(content='我喜歡程式設計!'), AIMessage(content='你喜歡程式設計的哪個方面?')]

查詢狀態

不同的應用對記憶查詢有不同的需求。LangChain的記憶工具箱允許開發者建立簡單的記憶基礎設施,同時也能架構出自定義的系統,以滿足特定的需求。

ConversationBufferMemory的使用

from langchain.memory import ConversationBufferMemory

# 初始化ConversationBufferMemory
memory = ConversationBufferMemory()

# 儲存對話上下文
memory.save_context({"input": "你好"}, {"output": "最近怎麼樣"})

# 載入記憶變數
print(memory.load_memory_variables({}))
# {'history': 'Human: 你好\nAI: 最近怎麼樣'}

# 傳回LangChain架構的訊息
memory = ConversationBufferMemory(return_messages=True)
memory.save_context({"input": "你好"}, {"output": "最近怎麼樣"})
print(memory.load_memory_variables({}))
# {'history': [HumanMessage(content='你好'), AIMessage(content='最近怎麼樣')]}

在LCEL中直接新增記憶到鏈

from langchain.memory import ConversationBufferMemory
from langchain_openai.chat_models import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda
from operator import itemgetter

# 初始化記憶和模型
memory = ConversationBufferMemory(return_messages=True)
model = ChatOpenAI(temperature=0)

# 定義提示範本
prompt = ChatPromptTemplate.from_messages([
    ("system", "作為一個幫助使用者解決問題的聊天機器人。"),
    MessagesPlaceholder(variable_name="history"),
    ("human", "{input}"),
])

# 構建鏈
chain = (
    {
        "input": lambda x: x["input"],
        "history": RunnableLambda(memory.load_memory_variables) | itemgetter("history"),
    }
    | prompt
    | model
    | StrOutputParser()
)

# 呼叫鏈並儲存訊息到記憶變數
inputs = {"input": "嗨,我叫詹姆斯!"}
result = chain.invoke(inputs)
memory.save_context(inputs, {"output": result})

# 檢視記憶中的訊息
print(memory.load_memory_variables({}))
# {'history': [HumanMessage(content='嗨,我叫詹姆斯!'), AIMessage(content='你好,詹姆斯!今天我能怎麼幫你?')]}

測試鏈是否能夠使用之前的上下文回答新的問題

透過上述步驟,我們成功地在LangChain中實作了具有短期記憶功能的對話式AI系統。這種系統能夠根據之前的對話內容,提供更連貫和更具上下文相關性的回答,從而提升使用者經驗。

進一步最佳化與擴充套件

  1. 增強記憶管理:可以根據實際需求,選擇更適合的記憶儲存方案,如使用更高效的資料函式庫系統。

  2. 最佳化查詢機制:開發更智慧的查詢機制,以更精確地檢索相關資訊,提升系統回應的準確性。

  3. 擴充套件應用場景:將此技術應用於更多領域,如客戶服務、教育輔導等,以發揮其在不同場景下的價值。

#: 隨著AI技術的不斷發展,對話式AI系統將變得越來越智慧和人性化。結合短期記憶和其他先進技術,這些系統將能夠提供更加自然和流暢的互動體驗,進一步拓展其在各個領域的應用潛力。

圖表說明

此圖示展示了LangChain中記憶機制的運作流程,包括讀取和儲存兩個主要操作。這種架構使得對話式AI系統能夠有效地管理和利用對話歷史,從而提供更具上下文相關性的回應。

圖表翻譯: 此圖表呈現了LangChain內部的記憶機制,主要分為兩個部分:讀取和儲存。在每次對話過程中,系統首先從記憶中讀取相關資訊,然後根據新的輸入進行處理,最後將處理結果儲存回記憶中,以供未來參考使用。這種設計使得對話式AI能夠保持連貫性和上下文理解能力,從而提供更優質的服務。

LangChain 中的記憶體管理與應用

LangChain 提供多種記憶體型別以支援不同情境下的對話管理需求,從基本的對話緩衝區到更複雜的摘要與 Token 限制管理。本文將探討 LangChain 中的各種記憶體型別及其特性。

對話緩衝記憶體(ConversationBufferMemory)

此記憶體型別用於儲存完整的對話歷史,無論對話長度如何。它提供了基本的對話記憶功能,但缺乏對長度或 Token 數的限制。

程式碼範例:

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.save_context({"input": "hi"}, {"output": "whats up"})
print(memory.load_memory_variables({}))
# 輸出:{'history': 'Human: hi\nAI: whats up'}

內容解密:

  1. 初始化 ConversationBufferMemory 物件。
  2. 使用 save_context 方法儲存對話上下文,包括輸入與輸出。
  3. 使用 load_memory_variables 方法載入儲存的對話歷史。

對話緩衝視窗記憶體(ConversationBufferWindowMemory)

此型別維護最近的 K 次互動,確保緩衝區不會過度增長。它適合用於需要限制對話歷史長度的場景。

程式碼範例:

from langchain.memory import ConversationBufferWindowMemory

memory = ConversationBufferWindowMemory(k=1)
memory.save_context({"input": "hi"}, {"output": "whats up"})
memory.save_context({"input": "not much you"}, {"output": "not much"})
print(memory.load_memory_variables({}))
# 輸出:{'history': 'Human: not much you\nAI: not much'}

內容解密:

  1. 設定 k=1 表示只保留最後一次互動。
  2. 儲存多輪對話上下文。
  3. 載入記憶體變數時,只傳回最近的一次互動。

對話摘要記憶體(ConversationSummaryMemory)

此記憶體型別會動態摘要對話內容,適合用於較長的對話場景,以減少 Token 使用量。

程式碼範例:

from langchain.memory import ConversationSummaryMemory
from langchain_openai import OpenAI

memory = ConversationSummaryMemory(llm=OpenAI(temperature=0))
memory.save_context({"input": "hi"}, {"output": "whats up"})
print(memory.load_memory_variables({}))
# 輸出:{'history': '\nThe human greets the AI, to which the AI responds.'}

內容解密:

  1. 使用 OpenAI 模型進行對話摘要。
  2. 儲存對話上下文並自動生成摘要。
  3. 載入記憶體變數時傳回生成的摘要。

對話摘要緩衝記憶體(ConversationSummaryBufferMemory)

結合了緩衝區與摘要功能,保留近期互動並將舊互動摘要化。

程式碼範例:

from langchain.memory import ConversationSummaryBufferMemory
from langchain_openai.chat_models import ChatOpenAI

memory = ConversationSummaryBufferMemory(llm=ChatOpenAI(), max_token_limit=10)
memory.save_context({"input": "hi"}, {"output": "whats up"})
print(memory.load_memory_variables({}))
# 輸出:包含最近互動及摘要的歷史記錄

內容解密:

  1. 設定 max_token_limit 以控制 Token 使用量。
  2. 結合近期互動與摘要內容傳回完整的對話歷史。

對話 Token 緩衝記憶體(ConversationTokenBufferMemory)

使用 Token 長度決定何時清除互動記錄,適合需要嚴格控制 Token 使用的場景。

程式碼範例:

from langchain.memory import ConversationTokenBufferMemory
from langchain_openai.chat_models import ChatOpenAI

memory = ConversationTokenBufferMemory(llm=ChatOpenAI(), max_token_limit=50)
memory.save_context({"input": "hi"}, {"output": "whats up"})
print(memory.load_memory_variables({}))
# 輸出:根據 Token 限制傳回對話歷史

內容解密:

  1. 設定 max_token_limit=50 以限制 Token 使用量。
  2. 根據設定的 Token 限制傳回適當的對話歷史。

各種記憶體型別的比較

記憶體型別主要特點適用場景
ConversationBufferMemory完整儲存對話歷史,無長度限制需要完整對話記錄的場景
ConversationBufferWindowMemory只保留最近 K 次互動需要限制對話歷史長度的場景
ConversationSummaryMemory自動摘要對話內容較長對話,需要減少 Token 使用
ConversationSummaryBufferMemory結合近期互動與摘要功能需要平衡 Token 使用與對話完整性的場景
ConversationTokenBufferMemory根據 Token 長度管理對話歷史需要嚴格控制 Token 使用量的場景