LocalAI是 OpenAI 的開源替代品,它能在本地計算機上執行 LLM。不需要 GPU,消費級硬體就足夠了
如果您可以使用與 OpenAI 相同的 Rest API 在本地執行模型,那不是很棒嗎?嗯,這正是LocalAI必須為您提供的!
LocalAI 是 OpenAI 的開源替代方案,具有與 OpenAI API 規範相容的 Rest API。除此之外,不需要 GPU,您可以在消費級硬體上執行它。不過,建議使用 GPU,因為它的速度大約快 20 倍。
此處描述了 LocalAI for CPU 的安裝。
1、克隆 LocalAI git 儲存庫。
$ git clone https://github.com/go-skynet/LocalAI
2、導航到儲存庫目錄。
$ cd LocalAI
3、儲存庫包含.env您需要自定義的檔案。
- 取消註釋THREADS:並將數字調整為您擁有的物理核心數量(在我的例子中為 12);
- 取消註釋GALLERIES:並將其調整為安裝指南中所述的galleries 。
## Set number of threads. |
4、啟動 Docker 容器。
Docker 映象引用的是最新標籤,在撰寫本文時,LocalAI 的 v2.0.0 是最新標籤。你可以導航到映象倉庫,搜尋最新標籤,複製清單雜湊值,然後搜尋複製的清單雜湊值。
$ docker compose up -d --pull always
請耐心等待,這需要一些時間。映象檔案約為 70GB。上一版本 v1.40.0 大約為 14GB。
當容器成功啟動後,你應該可以檢索到可用的模型:
$ curl http://localhost:8080/models/available
安裝模型
首先,您需要安裝一個模型。您可以透過應用程式介面的模型相簿進行安裝,但在撰寫本文時,這仍處於試驗階段。我更喜歡手動新增模型。說明可以在這裡找到,但要知道,隨著時間的推移,說明可能會發生變化,所以不要完全依賴本段的內容。
在 models 目錄下建立 lunademo.yaml 檔案。將執行緒數改為你機器上的物理核心數。
name: lunademo |
模型指的是包含模型的檔案。從 HuggingFace 將檔案下載到模型目錄。HuggingFace 包含許多您可以使用的開源模型,但在本示例中,您將使用基於 Llama 2 的模型,Llama 2 是由 Meta 建立的人工智慧模型。請注意,在 "模型卡 "中,模型與其用例一起列出。此外,用例中還說明了建議使用的模型。請注意只能使用 GGUF 模型,Llama 2 不再支援 GGML。
還要注意的是,模型的配置檔案中定義了兩個模板。一個是聊天模板,另一個是完成模板。
在模型目錄中建立一個檔案 lunademo-chat.tmpl。該模板來自 HuggingFace 的模型卡(搜尋 Prompt 模板)。
USER: {{.Input}} |
在模型目錄下建立 lunademo-completion.tmpl 檔案。
Complete the following sentence: {{.Input}} |
重啟 Docker 容器以載入模型。
$ docker compose restart
提問
既然模型已經載入,您就可以開始提問了。您可以檢視 OpenAPI 規範,以下是一些示例,以驗證本地模型的響應情況和準確性。
你好嗎?
作為第一個簡單的例子,您可以詢問模型感覺如何。在請求中,您可以提及要使用的模型、資訊,還可以設定溫度。溫度越高,模型就越有創造力。模型回答說它做得很好。
$ curl http:<font>//localhost:8080/v1/chat/completions -H "Content-Type: application/json" -d '{<i> |
整合LangChain4j
上面展示瞭如何透過 LocalAI 執行類似於 OpenAI 的大型語言模型 (LLM)。
使用 OpenAI 的 Rest API 來與 LocalAI 互動。將這些功能整合到 Java 應用程式中可能會很麻煩。
LangChain4j 為您提供了與大模型整合的簡化方法。它基於 Python 庫LangChain。
LangChain4j 示例儲存庫中提供了許多示例。特別是,目錄中的示例other-examples已被用作此部落格的靈感。
本部落格中使用的資源可以在GitHub上找到。
為了將 LangChain4j 與 LocalAI 結合使用,您需要將langchain4j-local-ai依賴項新增到 pom 檔案中。
<dependency> |
為了與 LocalAI 整合,您需要建立一個指定以下專案的 ChatLanguageModel:
- 可訪問 LocalAI 例項的 URL;
- 您希望在 LocalAI 中使用的模型名稱;
- 溫度,溫度越高,模型的響應越有創意。
然後,要求模型生成問題的答案並列印出來。
ChatLanguageModel model = LocalAiChatModel.builder() |
啟動 LocalAI 並執行上述示例。
響應與預期一致。
I'm doing well, thank you. How about yourself?
LanguageModel 和 ChatLanguageModel 之間的區別
這兩個類在 LangChain4j 中都有,那麼該選哪個呢?
- 聊天模型是語言模型的一種變體。如果您需要 "文字輸入,文字輸出 "功能,您可以選擇 LanguageModel。
- 如果還想使用 "聊天資訊 "作為輸入和輸出,則應使用 ChatLanguageModel。
在上面的示例中,你可以只使用 LanguageModel,它的表現也會類似。
嵌入文件
嵌入文件的最簡單方法是閱讀文件,將其分割成塊,然後嵌入這些塊。嵌入意味著將文字轉換為向量(數字)。您要提出的問題也需要嵌入。
向量儲存在一個向量儲存庫中,該儲存庫能找到與您的問題最接近的結果,並用這些結果作出回應。原始碼source code由以下部分組成:
- 文字需要嵌入。為此需要一個嵌入模型,為簡單起見,您可以使用 AllMiniLmL6V2EmbeddingModel。該模型使用 BERT 模型,這是一種流行的嵌入模型。
- 嵌入需要儲存在一個嵌入儲存庫中。通常情況下,向量資料庫會被用於此目的,但在這種情況下,你可以使用記憶體中的嵌入儲存。
- 讀取兩個文件並將其新增到 DocumentSplitter 中。在這裡,您將定義將文件分割成 500 個字元且不重疊的片段。
- 透過文件分割器,文件被分割成文字段。
- 嵌入模型用於嵌入文字段。TextSegments 及其嵌入的對應內容都儲存在嵌入儲存區中。
- 問題也使用相同的模型嵌入。
- 要求嵌入儲存查詢與嵌入問題相關的嵌入片段。您可以定義儲存應檢索多少個結果。
在本例中,只要求一個結果:如果找到匹配結果,控制檯將列印以下資訊:
- The score得分:表示結果與問題匹配程度的數字;
- The original text原文:片段的文字;
- The meta data後設資料:將顯示片段來自哪個文件。
private static void askQuestion(String question) { |
問題如下,是檔案中可以找到的一些事實:
public static void main(String args) { |
嵌入 Markdown 文件
將 PDF 文件轉換成 Markdown 檔案後會有什麼變化?在 Markdown 檔案中識別表格可能比在 PDF 文件中更好,而且它允許你在行級而不是任意的塊大小上分割文件。只有文件中包含問題答案的部分才會被轉換。這意味著唱片目錄中的錄音室專輯和合輯以及錄製的歌曲列表。
分割過程如下
- 逐行分割文件;
- 在變數 dataOnly 中讀取表格資料;
- 在變數 header 中儲存表頭;
- 為 dataOnly 中的每一行建立一個文字段,並將頁首新增到文字段中。
source code :
List<Document> documents = loadDocuments(toPath(<font>"markdown-files")); |
到目前為止得出的結論是
- 檔案格式以及檔案分割和嵌入的方式對結果有很大影響;
- 如果問題使用的術語與文件中的資料接近,則會取得更好的結果。
- 讀取和嵌入文件的方式似乎對結果影響最大。這種方法的優點是可以顯示多個結果。這樣,您就可以確定哪個結果是正確的。
- 更改您的問題,使其使用文字段中使用的術語,有助於獲得更好的結果。向量儲存的查詢速度非常快。嵌入需要花費一些時間,但只需要做一次。
- 在不使用 GPU 的情況下,使用 LLM 獲取結果需要更多時間。
向量資料庫
Weaviate是一個向量資料庫,還支援RAG
可以使用 Weaviate、LangChain4j 和 LocalAI 實現 RAG,結果是相當驚人的。以正確的方式嵌入文件、過濾結果並將其提供給大模型是一個非常強大的組合,可用於許多用例。
步驟:
- 文件嵌入並儲存在 Weaviate 中;
- 嵌入問題並使用 Weaviate 執行語義搜尋;
- Weaviate 返回語義搜尋結果;
- 結果被新增到提示中並饋送到 LocalAI,後者使用 LangChain4j 執行 LLM;
- LLM返回問題的答案。
在GitHub上找到實現原始碼