LangChain 提供多種記憶體型別,例如 ConversationBufferWindowMemory 適用於保留近期對話,ConversationSummaryMemory 則適用於摘要長對話,ConversationSummaryBufferMemory 結合兩者,ConversationTokenBufferMemory 則以 Token 長度管理記憶體。選擇記憶體型別時需正確引導 AI 模型,例如使用 ConversationBufferWindowMemory 時需指定保留的互動次數。OpenAI Functions Agent with Memory 的範例展示瞭如何使用聊天訊息管理記憶體、處理多個函式引數以及自定義 SystemMessage。使用 Pydantic 的 BaseModel 和 BaseTool 可進行引數驗證,確保工具的引數在執行前經過驗證,提高可靠性和效率。除了 ReAct 和 OpenAI 函式外,還有 Plan-and-Execute Agents 和 Tree of Thoughts 等進階代理框架。

LangChain 記憶體系統深度解析與實務應用

在前面的章節中,我們探討了 LangChain 中記憶體的重要性,並學習瞭如何使用 LangChain 的記憶體工具包來建立和自定義記憶體系統,包括儲存狀態和查詢記憶體的方法。同時,我們也看到了如何整合 MongoDBChatMessageHistory 和使用多功能的 ConversationBufferMemory。

LangChain 中的記憶體型別綜覽

LangChain 提供了多種記憶體型別,以滿足不同的應用需求。瞭解這些記憶體型別的特點和適用場景,可以幫助我們選擇最合適的記憶體解決方案。

1. ConversationBufferWindowMemory

這種記憶體型別維護最近的互動記錄,適用於需要保留對話上下文但又不想讓緩衝區過度膨脹的場景。透過指定保留最近的互動次數(K),可以有效地管理記憶體大小。

2. ConversationSummaryMemory

對於較長的對話,ConversationSummaryMemory 提供了一個摘要版本的對話內容,從而節省了寶貴的 token 空間。這種記憶體型別非常適合需要長期跟蹤對話內容的應用。

3. ConversationSummaryBufferMemory

這是一種混合型的方法,不僅維護最近的互動記錄,還會將較早的互動內容編譯成摘要。這種方法在需要同時保留近期對話細節和長期對話摘要的場景中非常有用。

4. ConversationTokenBufferMemory

當需要根據特定的 token 長度來管理記憶體時,ConversationTokenBufferMemory 是一個理想的選擇。它根據 token 長度來決定何時清除互動記錄,從而有效地控制記憶體的大小。

正確引導 AI 模型

在選擇合適的記憶體型別的同時,也需要正確地引導 AI 模型。例如,使用 ConversationBufferWindowMemory 時,需要明確指定要保留的最近互動次數(K)。清晰地定義需求可以獲得最佳的效果。

OpenAI Functions Agent with Memory 例項解析

在 GitHub 上有一個關於 OpenAI Functions Agent with Memory 的詳細範例,展示瞭如何整合多個關鍵元件:

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

以下是一個 Python 函式的範例,展示瞭如何使用 docstring 來提供工具的描述:

from langchain.tools import StructuredTool

def save_interview(raw_interview_text: str):
    """
    Tool to save the interview. You must pass the entire interview and conversation in here.
    The interview will then be saved to a local file. Remember to include all of the previous chat messages.
    Include all of the messages with the user and the AI, here is a good response:
    AI: some text
    Human: some text
    ...
    ---
    """
    # Save to local file:
    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.'''

save_interview = StructuredTool.from_function(save_interview)

內容解密:

此範例展示瞭如何建立一個 LangChain 工具,該工具能夠接受多個函式引數。docstring 中的格式指導 LLM 如何使用 raw_interview_text 引數。同時,傳回陳述式強調了告知使用者面試已儲存的重要性,以確保代理在工具執行後傳回更具對話性的回應。

使用 Pydantic 進行引數驗證

另一個範例展示瞭如何使用 Pydantic 的 BaseModelBaseTool 來進行引數驗證:

from pydantic.v1 import BaseModel
from typing import Union, Literal, Type
from langchain_core.tools import BaseTool

class ArgumentType(BaseModel):
    url: str
    file_type: Union[Literal["pdf"], Literal["txt"]]

class SummarizeFileFromURL(BaseTool):
    name = "SummarizeFileFromURL"
    description = "Summarize a file from a URL."
    args_schema: Type[ArgumentType] = ArgumentType

內容解密:

此範例中,args_schema 屬性利用 ArgumentType 類別來確保工具的引數在執行前經過驗證。具體來說,它強制要求提供有效的 URL 字串,並且 file_type 引數必須是 “pdf” 或 “txt”。透過新增驗證檢查,可以保證代理正確處理函式引數,從而提高工具執行的可靠性和效率。

先進的代理框架

除了 ReAct 和 OpenAI 函式外,還有多種其他的代理框架,如 plan-and-execute 代理和 tree of thoughts。

Plan-and-Execute Agents

這種框架將任務規劃和工具執行分成兩個獨立的模組,每個模組由個別的 LLM 處理。BabyAGI 和 AutoGPT 是兩種流行的 plan-and-execute 框架版本。

BabyAGI 代理設定

BabyAGI 的代理設定旨在將 OpenAI LLM 與向量資料函式庫(如 Chroma/Weaviate)整合,建立一個強健且適應性的任務管理系統。

  graph LR
    A[開始] --> B[取得任務]
    B --> C[執行任務]
    C --> D[儲存結果]
    D --> E[建立新任務]
    E --> F[優先排序任務]
    F --> B

圖表翻譯: 此圖示展示了 BabyAGI 的工作流程。首先,系統取得一個任務並傳遞給執行代理,執行代理利用 OpenAI 根據上下文資料執行任務。完成後,結果被豐富並存檔在 Chroma/Weaviate 中。然後,任務建立代理利用 OpenAI 從目標和先前任務的結果中辨別新任務。這些任務以字典列表的形式呈現,為結果任務提供結構。最後,優先排序代理與 OpenAI 互動,重新排列任務列表,以確保與主要目標保持一致。

自主代理與記憶及工具的進階應用

在前述章節中,我們探討了自主代理的基本架構及其與大語言模型(LLM)的整合方式。本章節將進一步探討自主代理的進階應用,特別是在記憶管理、工具使用以及除錯技術方面的進展。

具備記憶與工具的自主代理

自主代理(Autonomous Agents)能夠透過整合外部工具和記憶體系來提升其功能性和靈活性。這種整合方式使得代理能夠更有效地處理複雜任務,並在執行過程中進行動態調整。

BabyAGI:一個根據任務驅動的自主代理範例

BabyAGI是一種採用任務驅動機制的自主代理架構,其核心特點是透過計劃和執行兩個階段來完成任務。首先,BabyAGI會根據給定的目標生成一系列子任務;接著,它會利用LLM來執行這些子任務,並根據執行的結果進行動態調整。

# BabyAGI基本架構範例
class BabyAGI:
    def __init__(self, objective, llm):
        self.objective = objective
        self.llm = llm
        self.tasks = []

    def generate_tasks(self):
        # 利用LLM生成子任務
        self.tasks = self.llm.generate_tasks(self.objective)

    def execute_tasks(self):
        # 執行生成的子任務
        for task in self.tasks:
            result = self.llm.execute_task(task)
            # 根據執行結果進行動態調整
            self.adjust_tasks(result)

    def adjust_tasks(self, result):
        # 根據執行結果調整任務列表
        pass

內容解密:

此範例展示了BabyAGI的基本架構,包括任務生成、執行以及動態調整三個主要階段。其中,generate_tasks方法利用LLM生成子任務列表;execute_tasks方法負責執行這些子任務,並將執行結果傳遞給adjust_tasks方法進行動態調整。

思維樹(Tree of Thoughts, ToT)框架

ToT框架是一種突破傳統思維鏈(Chain of Thought)限制的新型推理方法。它允許LLM在多個推理路徑之間進行探索和切換,從而提高了模型在複雜任務中的表現。

  graph TD;
    A[初始狀態] --> B[思維1];
    A --> C[思維2];
    B --> D[思維1-1];
    B --> E[思維1-2];
    C --> F[思維2-1];
    C --> G[思維2-2];

圖表翻譯: 此圖示展示了ToT框架的基本結構。從初始狀態出發,模型可以探索多個不同的思維路徑(如思維1和思維2),並在每個思維路徑下進一步衍生出更多的子思維(如思維1-1和思維1-2)。這種多路徑的探索機制使得模型能夠更全面地考慮各種可能的解決方案。

內容解密:

ToT框架的核心優勢在於其能夠讓LLM進行更為複雜和多樣化的推理。透過在不同思維路徑之間進行切換,模型可以避免陷入區域性最優解,從而提高整體的解決問題的能力。

回撥函式(Callbacks)在LangChain中的應用

LangChain提供了強大的回撥函式機制,用於監控和除錯根據LLM的應用。透過實作BaseCallbackHandler類別,開發者可以自定義各種回撥函式,以便在模型的執行過程中捕捉關鍵事件。

# 自定義回撥函式範例
class CustomCallbackHandler(BaseCallbackHandler):
    def on_llm_start(self, serialized, prompts, **kwargs):
        print("LLM啟動")

    def on_llm_end(self, response, **kwargs):
        print("LLM結束")

    def on_chain_error(self, error, **kwargs):
        print(f"鏈錯誤:{error}")

內容解密:

此範例展示瞭如何透過繼承BaseCallbackHandler類別來自定義回撥函式。其中,on_llm_starton_llm_end方法分別用於捕捉LLM的啟動和結束事件,而on_chain_error方法則用於處理鏈執行過程中的錯誤。

結語

本章節探討了自主代理的進階應用,包括BabyAGI架構、ToT框架以及LangChain中的回撥函式機制。這些技術和方法為開發更為複雜和智慧的根據LLM的應用提供了強有力的支援。未來,我們將繼續探索這些技術的發展趨勢和潛在應用場景。

使用 LangChain 進行 Token 計數與回呼功能詳解

在開發與大語言模型(LLM)相關的應用時,瞭解如何有效管理與監控模型的輸入與輸出至關重要。LangChain 提供了一系列工具與方法來實作這些功能,其中包括 Token 計數與回呼(Callbacks)機制。本文將探討這些功能的實作與應用。

回呼(Callbacks)功能

回呼是 LangChain 中一個強大的功能,允許開發者在 LLMChain 或 Agent 的執行過程中插入自定義邏輯。這些回呼可以被用於日誌記錄、監控、甚至是將輸出串流至特定的端點,如 WebSocket。

回呼的定義與使用

回呼可以透過兩種主要方式定義:

  1. 建構函式回呼(Constructor Callbacks)

    • 適合用於需要跨整個鏈(Chain)或代理(Agent)進行全域性任務的場景,如日誌記錄或監控。
    • 示例程式碼:
      from langchain.callbacks import StdOutCallbackHandler
      from langchain.chains import LLMChain
      from langchain_openai import OpenAI
      from langchain_core.prompts import PromptTemplate
      
      handler = StdOutCallbackHandler()
      llm = OpenAI()
      prompt = PromptTemplate.from_template("What is 1 + {number} = ")
      chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])
      chain.invoke({"number": 2})
      
  2. 請求回呼(Request Callbacks)

    • 適合用於特定的使用場景,如將單一請求的輸出串流至特定的端點。
    • 示例程式碼:
      chain.invoke({"number": 2}, {"callbacks": [handler]})
      

詳細內容解密:

  • 在這個例子中,我們首先匯入必要的模組,包括 StdOutCallbackHandler 用於處理回呼、LLMChain 用於建立鏈、OpenAI 用於初始化語言模型,以及 PromptTemplate 用於建立提示範本。
  • 建立一個 StdOutCallbackHandler 例項,並將其傳遞給 LLMChain 的建構函式或 invoke 方法,以實作對鏈執行的監控。
  • 當鏈被呼叫時,回呼處理程式將捕捉並處理相關事件。

Verbose 引數

verbose 引數是 LangChain 中一個有用的除錯工具。當設定為 True 時,它相當於將 ConsoleCallbackHandler 新增到物件及其後代的 callbacks 引數中,用於直接將事件記錄到控制檯。

詳細內容解密:

  • verbose=True 可以幫助開發者監控和除錯 LLMChain 或 Agent 的執行過程。
  • 透過將詳細的日誌輸出到控制檯,開發者可以更好地理解模型的執行流程和內部狀態。

何時使用何種回呼

  • 建構函式回呼:適合用於需要跨整個鏈或代理進行全域性任務的場景,如日誌記錄或監控。
  • 請求回呼:適合用於特定的使用場景,如將單一請求的輸出串流至特定的端點。
  • Verbose 引數:適合用於除錯和本地 LLM 開發,但可能會產生大量的日誌。

使用 LangChain 進行 Token 計數

LangChain 提供了一個有效的方法來計算與生成式 AI 模型互動過程中的 Token 使用量。

詳細步驟與程式碼示例

  1. 設定必要的模組

    import asyncio
    from langchain.callbacks import get_openai_callback
    from langchain_core.messages import SystemMessage
    from langchain_openai.chat_models import ChatOpenAI
    
    model = ChatOpenAI()
    
  2. 使用 get_openai_callback 上下文管理器進行請求並計算 Token 使用量

    with get_openai_callback() as cb:
        model.invoke([SystemMessage(content="My name is James")])
        total_tokens = cb.total_tokens
        print(total_tokens)
        # 輸出:25
        assert total_tokens > 0
    

詳細內容解密:

  • 在這個例子中,我們使用 get_openai_callback 上下文管理器來捕捉並統計模型呼叫過程中的 Token 使用量。
  • 當模型被呼叫時,上下文管理器會自動記錄使用的 Token 數量,並將結果儲存在 cb.total_tokens 中。

多次請求的 Token 計數

當在上下文管理器內進行多次請求時,可以驗證計數的準確性。

with get_openai_callback() as cb:
    model.invoke([SystemMessage(content="My name is James")])
    model.invoke([SystemMessage(content="My name is James")])
    assert cb.total_tokens > 0
    print(cb.total_tokens)
    # 輸出:50

詳細內容解密:

  • 多次呼叫模型會累積 Token 使用量,cb.total_tokens 將反映總的 Token 使用量。

非同步回呼與平行執行

LangChain 支援平行執行多個請求,這對於提高效率和效能非常有幫助。

with get_openai_callback() as cb:
    await asyncio.gather(
        model.agenerate(
            [
                [SystemMessage(content="Is the meaning of life 42?")],
                [SystemMessage(content="Is the meaning of life 42?")],
            ],
        )
    )
    print(cb.__dict__)
    # {'successful_requests': 2, 'total_cost': 0.000455, 'total_tokens': 235, 'prompt_tokens': 30, 'completion_tokens': 205}

詳細內容解密:

  • 在這個例子中,我們使用 asyncio.gather 方法平行執行多個請求,並透過 get_openai_callback 上下文管理器捕捉相關的統計資訊,包括成功的請求數量、總成本、總 Token 使用量等。

影像生成中的擴散模型介紹

擴散模型是一種生成式模型,近年來在影像生成領域取得了顯著的成果。本章節將介紹擴散模型的基本原理、主要架構以及在影像生成中的應用。

擴散模型的原理

擴散模型的核心思想是透過逐步新增噪聲到影像中,然後學習如何逆轉這個過程來生成影像。這種方法靈感來自物理學中的擴散過程。

影像生成過程

  1. 前向擴散過程:逐步將噪聲新增到輸入影像中,直到影像變成純噪聲。
  2. 反向擴散過程:學習如何從純噪聲中還原出原始影像。

詳細內容解密:

  • 在訓練過程中,模型學習如何根據給定的描述(文字提示)生成匹配的影像。
  • 透過大量的影像-文字對資料進行訓練,模型能夠學習到不同藝術風格和主題的模式。

主要擴散模型介紹

  1. DALL-E 2:由 OpenAI 開發,能夠根據文字描述生成高品質的影像。
  2. Stable Diffusion:一個開源的擴散模型,廣泛應用於影像生成和編輯任務。
  3. Midjourney:一個流行的閉源擴散模型,以其生成藝術影像的能力而聞名。

詳細內容解密:

  • 每個模型都有其特點和優勢,選擇合適的模型取決於具體的應用場景和需求。
  • 例如,DALL-E 2 在生成高品質影像方面表現出色,而 Stable Diffusion 由於其開源特性,更受開發者歡迎。

圖表翻譯:擴散模型示意圖

  graph LR;
    A[輸入文字] --> B[編碼器];
    B --> C[潛在空間表示];
    C --> D[擴散模型];
    D --> E[生成的影像];

圖表翻譯:

此圖示展示了擴散模型的典型工作流程,從輸入文字到最終生成的影像。文字首先被編碼成潛在空間表示,然後透過擴散模型生成匹配的影像。