跳到主要內容
Open on GitHub

使用 Langchain 進行非同步程式設計

先決條件

基於 LLM 的應用程式通常涉及大量 I/O 綁定操作,例如對語言模型、資料庫或其他服務進行 API 調用。非同步程式設計(或 async 程式設計)是一種範例,允許程式同時執行多個任務,而不會阻止其他任務的執行,從而提高效率和響應能力,尤其是在 I/O 綁定操作中。

注意

在閱讀本指南之前,您應該熟悉 Python 中的非同步程式設計。如果您不熟悉,請在網路上尋找適當的資源來學習如何在 Python 中進行非同步程式設計。本指南專門關注您需要在非同步環境中使用 LangChain 的知識,假設您已經熟悉非同步。

Langchain 非同步 API

許多 LangChain API 都設計為非同步的,讓您可以構建高效且響應迅速的應用程式。

通常,任何可能執行 I/O 操作(例如,進行 API 調用、讀取檔案)的方法都將具有非同步的對應項。

在 LangChain 中,非同步實作與其同步對應項位於相同的類別中,非同步方法帶有 'a' 前綴。例如,同步 `invoke` 方法有一個名為 `ainvoke` 的非同步對應項。

LangChain 的許多組件都實作了 Runnable 介面,其中包括對非同步執行的支持。這意味著您可以使用 Python 中的 `await` 關鍵字非同步地運行 Runnables。

await some_runnable.ainvoke(some_input)

其他組件(如 Embedding Models 和 VectorStore)雖然沒有實作 Runnable 介面,但通常仍然遵循相同的規則,並在同一類別中包含帶有 'a' 前綴的方法的非同步版本。

例如,

await some_vectorstore.aadd_documents(documents)

使用 LangChain 運算式語言 (LCEL) 建立的 Runnables 也可以非同步運行,因為它們實作了完整的 Runnable 介面。

有關更多資訊,請查看您正在使用的特定組件的 API 參考。

委派給同步方法

大多數流行的 LangChain 整合都實作了其 API 的非同步支持。例如,許多 ChatModel 實作的 `ainvoke` 方法使用 `httpx.AsyncClient` 對模型提供商的 API 進行非同步 HTTP 請求。

當非同步實作不可用時,LangChain 會嘗試提供預設實作,即使這會產生輕微的開銷。

預設情況下,LangChain 會將未實作的非同步方法的執行委派給同步對應項。LangChain 幾乎總是假設同步方法應被視為阻塞操作,並應在單獨的線程中運行。這是通過使用 `asyncio` 庫提供的 `asyncio.loop.run_in_executor` 功能完成的。LangChain 使用 `asyncio` 庫提供的預設執行器,該執行器延遲初始化一個線程池執行器,該執行器具有預設數量的線程,這些線程在給定的事件循環中重複使用。雖然這種策略由於線程之間的上下文切換而產生輕微的開銷,但它可以保證每個非同步方法都有一個開箱即用的預設實作。

效能

LangChain 中的非同步程式碼通常應該能表現良好,開箱即用且開銷極小,並且不太可能成為大多數應用程式的瓶頸。

主要的兩個開銷來源是

  1. 當委派給同步方法時,線程之間上下文切換的成本。這可以通過提供原生非同步實作來解決。
  2. 在 LCEL 中,任何作為鏈一部分出現的「廉價函數」都將被安排為事件循環上的任務(如果它們是非同步的)或在單獨的線程中運行(如果它們是同步的),而不是僅僅內聯運行。

您應該預期從這些產生的延遲開銷在幾十微秒到幾毫秒之間。

更常見的效能問題來源是用戶在非同步上下文中調用同步程式碼(例如,調用 `invoke` 而不是 `ainvoke`)而意外阻止事件循環。

兼容性

LangChain 僅與 `asyncio` 庫兼容,該庫作為 Python 標準庫的一部分發布。它不適用於其他非同步庫,如 `trio` 或 `curio`。

在 Python 3.9 和 3.10 中,asyncio 的任務不接受 `context` 參數。由於此限制,LangChain 無法在某些情況下自動將 RunnableConfig 向下傳播到調用鏈中。

如果您在使用 Python 3.9 或 3.10 的非同步程式碼中遇到串流、回調或追蹤問題,這很可能是原因。

請閱讀 Propagation RunnableConfig 以獲取更多詳細資訊,以了解如何手動將 RunnableConfig 向下傳播到調用鏈中(或升級到 Python 3.11,其中不再存在此問題)。

如何在 ipython 和 jupyter notebook 中使用

從 IPython 7.0 開始,IPython 支持非同步 REPL。這意味著您可以在 IPython REPL 和 Jupyter Notebook 中使用 `await` 關鍵字,而無需任何額外設置。有關更多資訊,請參閱 IPython 部落格文章。


此頁面是否有幫助?