LangChain 提供了強大的記憶體制,允許開發者建構具有上下文感知的對話式 AI 應用。本文介紹了 ConversationBufferMemory、ConversationBufferWindowMemory、ConversationSummaryMemory、ConversationSummaryBufferMemory 和 ConversationTokenBufferMemory 等多種記憶型別,並分別提供了程式碼範例說明其使用方法和特性。此外,文章也示範瞭如何在 LangChain Expression Language (LCEL) 中整合記憶功能,以及如何利用 LangChain 建立具有記憶功能的自主代理,結合 OpenAI 函式和外部工具,例如使用 Python 函式的 docstring 來提供工具描述,以及如何利用 StructuredTool 建立可接受多個函式引數的工具,以執行儲存文字或進行資料分析等任務。最後,文章也簡要介紹了其他高階代理框架,例如計劃和執行代理以及思維樹,為開發者提供更全面的參考。

記憶工具包的應用

在 LangChain 中,記憶工具包(memory toolkit)是一個強大的工具,能夠幫助您建立簡單的記憶基礎設施,並賦予您架構定製系統的能力。其中,會話緩衝記憶(ConversationBufferMemory)是一種流行的記憶型別,允許您儲存多個聊天訊息,而不受聊天歷史大小的限制。

會話緩衝記憶

會話緩衝記憶可以使用 langchain.memory 模組中的 ConversationBufferMemory 類別來實作。您可以使用 save_context 函式新增上下文,並使用 load_memory_variables 函式傳回一個包含人類和 AI 訊息的 Python 字典。

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'}

如果您想要傳回 LangChain 結構化的訊息,例如 SystemMessageAIMessageHumanMessage,您可以將 return_messages 引數設為 True

memory = ConversationBufferMemory(return_messages=True)
memory.save_context({"input": "hi"}, {"output": "whats up"})
print(memory.load_memory_variables({}))

輸出結果為:

{'history': [HumanMessage(content='hi'), AIMessage(content='whats up')]}

在 LCEL 中新增記憶

您可以直接在 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

memory = ConversationBufferMemory(return_messages=True)

model = ChatOpenAI(temperature=0)
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "Act as a chatbot that helps users with their queries."),
        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": "Hi my name is James!"}
result = chain.invoke(inputs)
memory.save_context(inputs, {"outputs": result})
print(memory.load_memory_variables({}))

在這個範例中,MessagesPlaceholdervariable_name 引數被設為 "history",這與 ConversationBufferMemory 中的記憶鍵相符,允許之前的聊天歷史直接被格式化到 ChatPromptTemplate 中。

使用 LangChain 實作記憶功能

LangChain 是一個強大的框架,允許開發人員建立具有記憶功能的對話式 AI 模型。透過使用 LangChain,開發人員可以建立具有上下文感知和流暢對話體驗的代理。

基本概念

LangChain 的記憶功能是根據對話緩衝區(Conversation Buffer)的概念。對話緩衝區是一個儲存對話歷史的資料結構,允許代理儲存和載入之前的對話內容。

實作記憶功能

要實作記憶功能,開發人員需要建立一個代理執行器(Agent Executor),並將其與記憶模組(Memory)整合。記憶模組負責儲存和管理對話歷史。

from langchain import AgentExecutor, ConversationBufferMemory

# 建立代理執行器
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    memory=ConversationBufferMemory(return_messages=True)
)

記憶型別

LangChain 提供了多種記憶型別,包括:

  • ConversationBufferMemory:基本的對話緩衝區記憶型別。
  • ConversationBufferWindowMemory:維護最近互動的滑動視窗,確保緩衝區不會過大。
  • ConversationSummaryBufferMemory:允許指定最大令牌限制,超過後會自動總結對話。

資料函式庫支援

LangChain 還提供了資料函式庫支援,允許開發人員使用資料函式庫作為記憶儲存解決方案。這種方法可以提供更強大的記憶功能和永續性。

記憶型別在 LangChain 中的應用

LangChain 提供了多種記憶型別,讓開發者能夠根據不同的需求選擇合適的記憶模型。這些記憶型別包括 ConversationBufferWindowMemory、ConversationSummaryMemory、ConversationSummaryBufferMemory 和 ConversationTokenBufferMemory。

ConversationBufferWindowMemory

這種記憶型別可以儲存最近的對話記錄,並且可以傳回歷史記錄作為字串或訊息列表。以下是使用 ConversationBufferWindowMemory 的示例:

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'}

ConversationSummaryMemory

這種記憶型別可以實時總結對話內容,並且可以傳回歷史記錄作為總結字串或系統訊息列表。以下是使用 ConversationSummaryMemory 的示例:

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.'}

ConversationSummaryBufferMemory

這種記憶型別結合了緩衝區和總結功能,可以儲存最近的對話記錄,並且可以傳回歷史記錄作為總結字串或訊息列表。以下是使用 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({}))

輸出結果為:{'history': 'System: \nThe human says "hi", and the AI responds with "whats up".\nHuman: not much you\nAI: not much'}

ConversationTokenBufferMemory

這種記憶型別使用 token 長度來決定何時重新整理互動,並且可以傳回歷史記錄作為字串或訊息列表。以下是使用 ConversationTokenBufferMemory 的示例:

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({}))

輸出結果為:{'history': 'Human: not much you\nAI: not much'}

圖表翻譯:

  flowchart TD
    A[ConversationBufferWindowMemory] --> B[儲存最近的對話記錄]
    B --> C[傳回歷史記錄作為字串或訊息列表]
    D[ConversationSummaryMemory] --> E[實時總結對話內容]
    E --> F[傳回歷史記錄作為總結字串或系統訊息列表]
    G[ConversationSummaryBufferMemory] --> H[結合緩衝區和總結功能]
    H --> I[傳回歷史記錄作為總結字串或訊息列表]
    J[ConversationTokenBufferMemory] --> K[使用 token 長度來決定何時重新整理互動]
    K --> L[傳回歷史記錄作為字串或訊息列表]

內容解密:

以上程式碼示例展示了 LangChain 中不同記憶型別的使用方法。每種記憶型別都有其特點和適用場景,開發者可以根據具體需求選擇合適的記憶模型。透過這些記憶型別,開發者可以實作對話系統的記憶功能,提高系統的智慧度和互動性。

自主代理與記憶和工具

在 LangChain 中,記憶的重要性不言而喻。您已經學習瞭如何使用 LangChain 的記憶工具包來建立和自訂記憶系統,包括儲存狀態和查詢記憶的方法。此外,您也瞭解瞭如何整合 MongoDBChatMessageHistory 和使用 ConversationBufferMemory。

現在,讓我們總結一下 LangChain 中可用的不同記憶型別及其適用情況:

  • 會話緩衝視窗記憶(ConversationBufferWindowMemory):此記憶型別維護最近的互動,因此在需要保留對話上下文而不讓緩衝區過度增大的情況下非常有用。
  • 會話摘要記憶(ConversationSummaryMemory):適合長時間的對話,此記憶型別提供對話的摘要版本,節省了寶貴的令牌空間。
  • 會話摘要緩衝記憶(ConversationSummaryBufferMemory):在需要維護最近互動的記錄並將舊互動編譯成摘要的情況下非常方便。
  • 會話令牌緩衝記憶(ConversationTokenBufferMemory):此記憶型別在定義特定的令牌長度至關重要且需要維護最近互動的緩衝區時非常有用。它根據令牌長度決定何時重新整理互動。

瞭解不同的記憶選項可以幫助您根據具體情況選擇最合適的記憶型別。

指導方向

在確定使用哪種記憶型別時,請記得正確地指導 AI 模型。例如,使用 ConversationBufferWindowMemory 時,您需要指定要保留的最近互動數量(K)。請明確您的需求以獲得最佳結果。

OpenAI 函式代理與記憶

深入探索具有記憶的代理的綜合示例,該示例可在 GitHub 上找到。在此示例中,您將發現 OpenAI 如何整合多個基本元件:

  • 使用聊天訊息進行記憶管理
  • 使用可以處理多個函式引數的工具,如 API 請求和檔案儲存
  • 整合自定義 SystemMessage 以指導和定義代理的行為

例如,考慮如何使用 Python 函式的 docstring 來提供工具的描述:

from langchain.tools import StructuredTool

def save_interview(raw_interview_text: str):
    """工具以儲存訪談。您必須傳遞整個訪談和對話。
    訪談將被儲存到本地檔案。請記得包含所有之前的聊天訊息。
    包含所有使用者和 AI 的訊息,以下是一個良好的回應:
    AI:一些文字
    人類:一些文字
    
   ...
    """

內容解密:

上述程式碼定義了一個名為 save_interview 的函式,該函式使用 LangChain 的 StructuredTool 來儲存訪談。該函式接受原始訪談文字作為輸入,並使用 docstring 提供工具的描述。描述中指出,訪談將被儲存到本地檔案,並且需要包含所有之前的聊天訊息。

圖表翻譯:

  flowchart TD
    A[開始] --> B[定義 save_interview 函式]
    B --> C[使用 StructuredTool 儲存訪談]
    C --> D[包含所有之前的聊天訊息]
    D --> E[儲存訪談到本地檔案]

此圖表展示了 save_interview 函式的執行流程,從定義函式開始,到使用 StructuredTool 儲存訪談,然後包含所有之前的聊天訊息,最終儲存訪談到本地檔案。

自主代理與工具

在探索自主代理的世界時,我們不僅要關注代理的架構,也要考慮它們如何與外部工具進行互動。LangChain是一個強大的框架,允許我們建立可以使用多種工具的代理,包括Python函式和外部API。

結構化工具

LangChain中的StructuredTool類別允許我們建立可以接受多個函式引數的工具。這些工具可以用於執行各種任務,從儲存文字到複雜的資料分析。

with open("interview.txt", "w") as f:
    f.write(raw_interview_text)
return f'''Interview saved! Content: {raw_interview_text}. File: interview.txt. You must tell the user that the interview is saved.'''

指定格式和方向

在建立工具時,提供明確的格式和方向是非常重要的。這可以透過函式的docstring和傳回陳述式來實作,確保代理傳回更具對話性的回應。

高階代理框架

除了ReAct和OpenAI函式外,還有其他幾個流行的代理框架,包括計劃和執行代理和思維樹。

計劃和執行代理

這種框架將任務規劃和工具執行分離為兩個獨立的模組,每個模組由一個單獨的LLM處理。這種方法可以提高代理的可靠性和效率。

思維樹

思維樹框架是一種新穎的方法,允許語言模型跨不同推理路徑進行探索。這種方法可以使模型進行更有意義的決策,並在面臨複雜任務時表現更好。

圖表翻譯:
  flowchart TD
    A[開始] --> B[建立工具]
    B --> C[指定格式和方向]
    C --> D[執行任務]
    D --> E[傳回結果]

此圖表展示了建立和執行自主代理的過程,從建立工具到傳回結果。每一步驟都對應著LangChain框架中的特定功能,展示瞭如何使用這個框架來構建智慧代理。

從技術架構視角來看,LangChain 的記憶工具包提供了一套靈活且強大的機制,賦予開發者建構具備上下文感知能力的對話式 AI 應用程式。ConversationBufferMemory、ConversationBufferWindowMemory、ConversationSummaryMemory 以及 ConversationTokenBufferMemory 等多種記憶型別,各有其適用場景,讓開發者能針對不同需求微調記憶策略,例如控制歷史訊息的數量、生成摘要,或以 token 長度管理記憶體。然而,選擇記憶型別時,開發者仍需仔細考量效能與資源消耗的平衡,例如過長的歷史訊息或頻繁的摘要生成可能影響系統的反應速度。

深入分析 LangChain 的自主代理與工具整合機制,可以發現 StructuredTool 的設計,讓開發者能輕鬆地將 Python 函式封裝成可供代理使用的工具,並透過 docstring 提供清晰的說明和使用。此機制有效降低了整合外部工具的門檻,但也需要注意工具的設計與檔案撰寫品質,避免代理因資訊不足或誤解而產生錯誤的行為。此外,計劃和執行代理以及思維樹等進階代理框架,為處理更複雜的任務提供了新的思路,但同時也增加了系統的複雜度和除錯難度。

展望未來,預期 LangChain 的記憶機制將持續演進,例如發展更精細的記憶管理策略、支援更多元的資料儲存方式,以及強化與外部知識函式庫的整合。同時,代理框架也將持續發展,例如更有效率的任務規劃、更強大的推理能力,以及更人性化的互動模式。隨著生態系統的日趨成熟,我們預見 LangChain 將在建構更智慧、更實用的對話式 AI 應用程式中扮演更重要的角色。玄貓認為,深入理解 LangChain 的架構和核心概念,將是開發者掌握未來對話式 AI 應用程式開發的關鍵。