構建由大型語言模型(LLM)驅動的 Go 應用程序

本文由 Eli Bendersky  於  2024 年 9 月 12 日發表在 https://go.dev/blog

隨着過去一年大型語言模型(LLM)及其相關工具(如嵌入模型)的能力顯著增長,越來越多的開發者開始考慮將 LLM 集成到他們的應用程序中。

由 於 LLM 通常需要專用硬件和大量的計算資源,它們最常見的形式是作爲提供 API 訪問的網絡服務。這就是領先的 LLM 如 OpenAI 或 Google Gemini 的 API 的工作方式;即使是運行你自己的 LLM 工具,如 Ollama[1],也會將 LLM 包裝在 REST API 中供本地使用。此外,利用 LLM 的開發者通常還需要輔助工具,如向量數據庫,這些通常也作爲網絡服務部署。

換句話說,LLM 驅動的應用程序很像其他現代雲原生應用程序:它們需要對 REST 和 RPC 協議、併發性和性能有出色的支持。這些恰好是 Go 擅長的領域,使它成爲編寫 LLM 驅動應用程序的絕佳語言。

這篇博客文章通過一個簡單的例子,展示瞭如何使用 Go 爲 LLM 驅動的應用程序工作。它首先描述了演示應用程序要解決的問題,然後展示了幾個變體的應用程序,它們都完成了相同的任務,但使用了不同的包來實現。這篇帖子的所有演示代碼都可以在線獲取 [2]。

用於問答的 RAG 服務器

LLM 驅動應用程序的一種常見技術是 RAG -  Retrieval Augmented Generation[3]。RAG 是爲特定領域的交互定製 LLM 知識庫的最可擴展方式之一。

我們將用 Go 構建一個 RAG 服務器。這是一個 HTTP 服務器,爲用戶提供兩個操作:

在典型的現實世界場景中,用戶會向服務器添加一批文檔,然後開始提問。例如,一家公司可以用內部文檔填充 RAG 服務器的知識庫,並使用它爲內部用戶提供 LLM 驅動的問答能力。

以下是顯示我們服務器與外部世界交互的圖:

除了用戶發送 HTTP 請求(上述兩個操作)之外,服務器還與以下內容交互:

我們的演示使用的服務包括:

直接使用 Gemini API 和 Weaviate

Gemini API 和 Weaviate 都有方便的 Go SDK(客戶端庫),我們的第一個服務器變體直接使用這些。這個變體的完整代碼在這個目錄 [7] 中。

我們不會在這篇博客文章中複製整個代碼,但在閱讀時請注意以下幾點:

使用 LangChainGo

我們的第二個 RAG 服務器變體使用 LangChainGo 來完成相同的任務。

LangChain[9] 是一個流行的 Python 框架,用於構建 LLM 驅動的應用程序。LangChainGo[10] 是它的 Go 框架。該框架有一些工具,可以將應用程序構建爲模塊化組件,並支持許多 LLM 提供商和向量數據庫的通用 API。這允許開發者編寫可以與任何提供商一起工作的代碼,並很容易地更改提供商。

這個變體的完整代碼在這個目錄 [11] 中。在閱讀代碼時,你會注意到兩件事:

使用 Genkit for Go

今年早些時候,Google 爲 Go 引入了 Genkit[12] - 一個構建 LLM 驅動應用程序的新開源框架。Genkit 與 LangChain 有一些共同的特點,但在其他方面有所不同。

像 LangChain 一樣,它提供了可以由不同提供商(作爲插件)實現的通用接口,從而使從一個提供商切換到另一個提供商變得更簡單。然而,它並不試圖規定不同的 LLM 組件如何交互;相反,它專注於生產特性,如提示管理和工程,以及集成開發工具的部署。

我們的第三個 RAG 服務器變體使用 Genkit for Go 來完成相同的任務。它的完整代碼在這個目錄 [13] 中。

這個變體與 LangChainGo 非常相似 - 使用 LLM、嵌入器和向量數據庫的通用接口,而不是直接提供 API,使得從一個切換到另一個變得更容易。此外,使用 Genkit 將 LLM 驅動的應用程序部署到生產環境要容易得多;我們沒有在我們的變體中實現這一點,但如果你感興趣,可以閱讀文檔 [14]。

總結 - Go 用於 LLM 驅動的應用程序

這篇文章中的示例只是構建 Go 中 LLM 驅動應用程序的可能性的一小部分。它展示瞭如何用相對較少的代碼構建一個功能強大的 RAG 服務器;最重要的是,由於 Go 的一些基本特性,這些示例具有相當程度的生產準備度。

與 LLM 服務合作通常意味着向網絡服務發送 REST 或 RPC 請求,等待響應,根據該響應向其他服務發送新請求等等。Go 在所有這些方面都表現出色,爲管理併發性和處理網絡服務的複雜性提供了出色的工具。

此外,Go 作爲雲原生語言的卓越性能和可靠性使其成爲實現 LLM 生態系統更基本構建塊的自然選擇。一些例子包括 Ollama、LocalAI[15]、Weaviate 或 Milvus[16] 等項目。

參考資料

[1]

ollama: https://ollama.com/

[2]

go.dev ragserver demo: https://github.com/golang/example/tree/master/ragserver

[3]

RAG: https://en.wikipedia.org/wiki/Retrieval-augmented_generation

[4]

vector embedding: https://en.wikipedia.org/wiki/Sentence_embedding

[5]

Weaviate: https://weaviate.io/

[6]

weaviate github: https://github.com/weaviate/weaviate

[7]

ragserver demo: https://github.com/golang/example/tree/master/ragserver/ragserver

[8]

routing-enhancements: https://go.dev/blog/routing-enhancements

[9]

LangChain: https://www.langchain.com/

[10]

langchaingo: https://github.com/tmc/langchaingo

[11]

ragserver langchaingo: https://github.com/golang/example/tree/master/ragserver/ragserver-langchaingo

[12]

Genkit: https://developers.googleblog.com/en/introducing-genkit-for-go-build-scalable-ai-powered-apps-in-go/

[13]

ragserver-genkit: https://github.com/golang/example/tree/master/ragserver/ragserver-genkit

[14]

genkit start doc: https://firebase.google.com/docs/genkit-go/get-started-go

[15]

localai: https://localai.io/

[16]

milvus: https://zilliz.com/what-is-milvus

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/W5OpauBtdhsUu6AEqeP53w