離開抱抱臉: 讓Dify擁抱Ollama / Leaving Hugging Face: Embracing Ollama with Dify
在「自行架設大型語言模式應用程式:Dify」這篇我講到我在Dify裡面使用Hugging Face API作文字嵌入(embedding),但啟動等待跟限速的限制降低了使用效率。這次我們把文字嵌入的工作交給自行架設的Ollama,讓我們來看看自行架設到底可以帶來什麼效益吧。
In the article "Self-Hosting a Large Language Model Application: Dify," I discussed using the Hugging Face API for text embedding within Dify. However, startup latency and rate limiting reduced efficiency. This time, we'll offload the text embedding task to a self-hosted Ollama instance. Let's explore the benefits of self-hosting.
Ollama:自行架設大型語言模型的入門 / Ollama: Self-Hosting Large Language Models for Begginer
Ollama是一個開放原始碼的工具,讓使用者可以在自己的電腦上運行大型語言模型(Large Language Model, LLM),並對整個LLM的架設與管理LLM流程進行了簡化。Ollma支援多種作業系統,包含Linux、macOS和Windows,並且提供了一個直覺的介面,讓使用者可以輕鬆地下載、安裝和運行各種熱門的LLM,例如Meta的Llama、法國的Mistral和Google開源的Gemma等。透過Ollama,開發者、研究人員和AI愛好者都能夠在本地環境快速實驗、管理和部署最新的LLM,而不需要仰賴雲端服務,進而省下成本並提升資料安全性。
https://github.com/ollama/ollama/blob/main/docs/api.md
Ollama的設計理念著重於簡潔和易用性。使用者只需透過簡單的指令,即可下載和運行LLM,並透過命令列或API與模型互動。Ollama也支援模型的客製化,讓使用者可以根據自己的需求調整模型參數,或是載入自行訓練的模型。此外,Ollama 也提供 REST API,讓開發者可以輕鬆地將 Ollama 整合到其他的應用程式中,而本次要講的Dify也是能夠與Ollama完美整合的其中一個例子。
運作環境 / Environment
我在Promxox VE裡面用LXC容器來運作Ollama。Ollama運作模型的時候需要大量記憶體、CPU跟硬碟空間。CPU推薦是4核心,記憶體至少要4GB以上,硬碟空間則推薦預留8GB給Ollama下載模型。作業系統使用的是Ubuntu 22.04。
所幸這次我只要Ollama運作文字嵌入的模型,不使用GPU加速也不會太慢。那我們就繼續吧。
用Docker Compose架設Ollama / Setting Up Ollama with Docker Compose
Ollama預設的安裝方式是透過指令把Ollama安裝在電腦環境中。但通常我不會選擇這樣做。由於伺服器上還要運作其他的服務,如果安裝多個不同的軟體工具,很有可能造成Ollama跟其他工具有所衝突。
https://strapi.io/blog/what-is-docker-compose-all-you-need-to-know
為了管理的方便,我通常使用Docker Compose來架設Ollama。Docker Compose跟直接執行Docker指令基本上是一樣的效果,都是設定好Docker的容器(container),並讓它執行。但Docker Compose將設定以YAML格式撰寫,而且可以調整的細項比較多,管理起來更加容易。因此在Docker指令和Docker Compose設定上,我往往會選擇後者。
docker-compose.yml
version: '3.8'
services:
ollama:
image: ollama/ollama:0.4.7
volumes:
- ./ollama:/root/.ollama
- ./entrypoint.sh:/entrypoint.sh
ports:
- "11434:11434"
restart: always
entrypoint: ["/usr/bin/bash", "/entrypoint.sh"]
運作Ollama的docker-compose.yml並不複雜。這邊我選用的是前幾天才發佈的Ollama 0.4.7映像檔。Ollama API需要使用的連接埠為11434。然後將restart設為「always」,以確保Ollama當機的時候還能自己重新啟動。
比較特別的是,這份docker-compose.yml還要搭配entrypoint.sh才能啟動。這個檔案是什麼呢?
在Ollama裡面下載模型 / Downloading Models in Ollama
架設Ollama環境真的不難。Ollama只是一堆小工具的集合,本身並不負責大型語言模型的計算,所以整體而言還算是單純。問題在於把Ollama裝好之後,要怎麼下載模型呢?
在原始的安裝情境中,我們是把Ollama裝在作業系統上,再從作業系統執行模型下載的指令,例如:「ollama pull bge-m3」這樣Ollama就會從官方的儲存庫下載bge-m3到本機端,之後就可以使用bge-m3模型了。
但是在Docker Compose的使用情境裡,我們執行了「docker compose up -d」指令讓整個容器在背景運作之後,通常就不會用指令操作容器本身。那到底要怎麼執行上述那段拉取模型的指令呢?
https://stackoverflow.com/a/78501628
這邊我參考了datawookie的做法,用entrypoint.sh來控制Ollama容器的運作。entrypoint.sh的內容如下:
#!/bin/bash
# Start Ollama in the background.
/bin/ollama serve &
# Record Process ID.
pid=$!
# Pause for Ollama to start.
sleep 5
ollama pull bge-m3
# Wait for Ollama process to finish.
wait $pid
這意思是先將Ollama服務開啟,然後取得Ollama的程序運作編號,等待5秒之後再開始執行拉取模型的操作。
將上述程式碼儲存成entrypoint.sh,加上可執行權限,並跟docker-compose.yml放在一起,我們就能用「docker compose up -d」來啟用Ollama。
根據Docker Compose的設定,通常Ollama下載的模型會放在目前所在資料夾底下的「ollama」裡面。如果有出現blobs跟manifests的資料夾,裡面有新增的檔案,就表示模型已經正常下載。
文字嵌入模型的選擇 / Text Embedding Model Selection
https://ollama.com/search?c=embedding
之前我在Hugging Face使用的文字嵌入模型(Embedding)是intfloat/multilingual-e5-large,那換到Ollama之後,要選擇那個模型好呢?Ollama的Models裡面有列出了提供Embedding的模型,目前只有七種。由於我們的環境主要是以中文為主,特別是繁體中文,因此模型是否有支援繁體中文的訓練集,就是我們在選擇模型時最主要的考量。
https://ollama.com/library/bge-m3
一開始我嘗試的是paraphrase-multilingual,但是它實際上不能讀懂繁體中文的內容。後來改用了bge-m3表現就好了很多,因此上面entrypoint.sh的設定拉取的就是bge-m3模型。
https://arxiv.org/abs/2402.03216
BGE-M3 是2024年發佈的新模型,它一款專為多功能、多語言及多層次應用而設計的文字嵌入模型,適用於廣泛的語言處理與檢索應用。BGE-M3 支援了超過 100 種語言,能夠在多語言環境中提供一致的高效能表現,適用於全球化應用場景。該模型可處理不同粒度的輸入內容,從短句到長文檔(最長可達 8192 個 tokens),展現了對多樣化資料處理的適應能力。有興趣的話,可以到arxiv看看原始的論文內容。
在Dify裡面連結Ollama / Connecting Ollama in Dify
如果Ollama已經設定完成,那麼我們接下來就只要到Dify裡面設定連接Ollama即可。整個步驟並沒有太困難的地方,容易設定也是Dify的特色呢。
設定完成之後,連接Ollama作文字嵌入的操作,讓整個處理速度從7.5秒縮減到3.1s,效率提升了將近2.5倍,真是令人印象深刻。
另一方面,在知識庫裡面匯入大量文件,我也不用擔心像之前使用Hugging Face那樣被限流或禁用,而可以放心慢慢地讓Ollama處理大量文件。雖然運作的時候非常吃CPU的運算速度,但仍不至於會弄到當機的程度。
結語:文字嵌入是RAG的第一步 / Conclusion: Text Embedding Is At The Beginning Of RAG
現今的RAG基本上都是圍繞著文字嵌入來做設計。你要取得合適的資料給LLM解讀,那就必須選擇合適的文字嵌入模型、將文件轉換成合適的切片。這之間任何一步沒有做好,都會讓RAG找出不合適的資料,而LLM也只能就不合適的資料來解讀,結果就會不盡人意。
本篇用Ollma的BGM-M3作為Dify的文字嵌入,雖然它比直接呼叫Hugging Face API還來得快,也比paraphrase-multilingual更能讀懂繁體中文,但單靠它和Dify,也只能打造出堪用的RAG。距離我理想的RAG,還有很長一段路要走。
摸著石頭過河吧。
文章的最後要來問大家的是:你會怎麽選擇文字嵌入的模型呢?
- 1. 直接使用OpenAI的text-embedding-3-large不就好了嗎?又不貴。
- 2. Hugging Face有很多選擇,慢慢來的話還是很好用的。
- 3. 原來Ollama不只是聊天機器人,還能當文字嵌入模型的API使用啊?
- 4. 其他:歡迎在下面留言,聊聊你的想法!