轉自:https://zhuanlan.zhihu.com/p/695534674
Ollama 與 OpenWebUI 介紹
Ollama 是一個執行大模型的工具,可以看成是大模型領域的 Docker,可以下載所需的大模型並暴露 API。
OpenWebUI 是一個大模型的 Web UI 互動工具,支援 Ollama,即呼叫 Ollama 暴露的 API 實現與大模型互動:
部署方案選型
OpenWebUI
的倉庫中自帶 Ollawma
+ OpenWebUI
的部署方式,主要是 kustomize
和 helm
這兩種方式,參考 open-webui 倉庫的 kubernetes 目錄。
但我更推薦直接寫 YAML 進行部署,原因如下:
Ollama
+OpenWebUI
所需 YAML 相對較少,直接根據需要寫 YAML 更直接和靈活。- 不需要研究
OpenWebUI
提供的kustomize
和helm
方式的用法。
選擇模型
Llama3 目前主要有 8b
和 70b
兩個模型,分別對應 80 億和 700 億規模的引數模型,CPU 和 GPU 都支援,8b
是小模型,對配置要求不高,一般處於成本考慮,可以直接使用 CPU 執行,而 70b
則是大模型, CPU 肯定吃不消,GPU 的配置低也幾乎跑不起來,主要是視訊記憶體要大才行,經實測,24G 視訊記憶體跑起來會非常非常慢,32G 的也有點吃力,40G 的相對流暢(比如 Nvdia A100)。
準備 Namespace
準備一個 namespace,用於部署執行 llama3 所需的服務,這裡使用 llama
namespace:
kubectl create ns llama
部署 Ollama
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ollama
namespace: llama
spec:
serviceName: "ollama"
replicas: 1
selector:
matchLabels:
app: ollama
template:
metadata:
labels:
app: ollama
spec:
containers:
- name: ollama
image: ollama/ollama:latest
ports:
- containerPort: 11434
resources:
requests:
cpu: "2000m"
memory: "2Gi"
nvidia.com/gpu: "0" # 如果要用 Nvidia GPU,這裡宣告下 GPU 卡
limits:
cpu: "4000m"
memory: "4Gi"
volumeMounts:
- name: ollama-volume
mountPath: /root/.ollama
tty: true
volumeClaimTemplates:
- metadata:
name: ollama-volume
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 200Gi # 注意要確保磁碟容量能夠容納得下模型的體積
---
apiVersion: v1
kind: Service
metadata:
name: ollama
namespace: llama
labels:
app: ollama
spec:
type: ClusterIP
ports:
- port: 11434
protocol: TCP
targetPort: 11434
selector:
app: ollama
部署 OpenWebUI
OpenWebUI
是大模型的 web 介面,支援 llama 系列的大模型,透過 API 與 ollama 通訊,官方映象地址是:ghcr.io/open-webui/open-webui
,在國內拉取速度非常慢,如果你的環境有 DockerHub 加速,可以替換成 DockerHub 里長期自動同步的 mirror 映象:docker.io/imroc/open-webui
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webui-pvc
namespace: llama
labels:
app: webui
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: webui
namespace: llama
spec:
replicas: 1
selector:
matchLabels:
app: webui
template:
metadata:
labels:
app: webui
spec:
containers:
- name: webui
image: imroc/open-webui:main # docker hub 中的 mirror 映象,長期自動同步,可放心使用
env:
- name: OLLAMA_BASE_URL
value: http://ollama:11434 # ollama 的地址
tty: true
ports:
- containerPort: 8080
resources:
requests:
cpu: "500m"
memory: "500Mi"
limits:
cpu: "1000m"
memory: "1Gi"
volumeMounts:
- name: webui-volume
mountPath: /app/backend/data
volumes:
- name: webui-volume
persistentVolumeClaim:
claimName: webui-pvc
---
apiVersion: v1
kind: Service
metadata:
name: webui
namespace: llama
labels:
app: webui
spec:
type: ClusterIP
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: webui
開啟 OpenWebUI
你有很多方式可以將 OpenWebUI
暴露給叢集外訪問,比如 LoadBalancer
型別 Service
、Ingress
等,也可以直接用 kubectl port-forward
的方式將 webui 暴露到本地:
kubectl -n llama port-forward service/webui 8080:8080
瀏覽器開啟:http://localhost:8080
,首次開啟需要建立賬號,第一個建立的賬號為管理員賬號。
下載模型
方法一:透過 OpenWebUI 下載
進入 OpenWebUI
並登入後,在 設定-模型
裡,輸出需要下載的 llama3
模型並點選下載按鈕(除了基礎的模型,還有許多微調的模型,參考 llama3 可用模型列表)。
接下來就是等待下載完成:
注意:如果頁面關閉,下載會中斷,可重新開啟頁面並重新輸入要下載的模型進行下載,會自動斷點續傳。
方法二:執行 ollama pull 下載
進入 ollama 的 pod:
kubectl -n llama exec -it ollama-0 bash
執行 ollama pull
下載需要的模型,這裡以下載 70b
模型為例:
ollama pull llama3:70b
等待下載完成。
注意: 如果kubectl
的連線中斷,下載也會中斷,可重新執行命令斷點續傳。
你也可以使用nohup ollama pull llama3:70b &
來下載,透過tail -f nohup.out
檢視下載進度,這樣可以保證即使 kubectl 中斷或退出也會繼續下載。
方案三:使用 init container 自動下載模型
如果不想每次在新的地方部署需要手動下載模型,可以修改 Ollama 的部署 YAML,加個 initContainer
來實現自動下載模型(自動檢測所需模型是否存在,不存在才自動下載):
initContainers:
- name: pull
image: ollama/ollama:latest
tty: true
stdin: true
command:
- bash
- -c
- |
model="llama3:8b" # 替換需要使用的模型,模型庫列表: https://ollama.com/library/llama3
ollama serve &
sleep 5 # 等待 ollama server 就緒,就緒後才能執行 ollama cli 工具的命令
result=`ollama list | grep $model`
if [ "$result" == "" ]; then
echo "downloading model $model"
ollama pull $model
else
echo "model $model already been downloaded"
fi
volumeMounts:
- name: ollama-volume
mountPath: /root/.ollama
開始對話
開啟 OpenWebUI
頁面,選擇模型,然後就可以在對話方塊中開始對話了。
小技巧
GPU 排程策略
對於像 70b
這樣的模型,需要較好的 GPU 才能跑起來,如果叢集內有多種 GPU 節點,需要加下排程策略,避免分配到較差的 GPU。
比如要排程到顯示卡型號為 Nvdia Tesla V100
的節點,可以給節點打上 label:
kubectl label node gpu=v100
然後配置下排程策略:
nodeSelector:
gpu: v100
省錢小妙招
- 如果使用雲廠商託管的 Kubernetes 叢集,且不需要大模型高可用,可以購買競價例項(Spot),會便宜很多。
- 如果只在部分時間段使用,可以使用定時伸縮,在不需要的時間段將 Ollama 和 OpenWebUI 的副本數自動縮到 0 以停止計費,比如 使用 KEDA 的 Cron 觸發器實現定時伸縮。
常見問題
節點無公網導致模型下載失敗
ollama 所在機器需要能夠訪問公網,因為 ollama 下載模型需要使用公網,否則會下載失敗,無法啟動,可透過檢視 init container 的日誌確認:
$ kubectl logs -c pull ollama-0
time=2024-04-26T07:29:45.487Z level=INFO source=images.go:817 msg="total blobs: 5"
time=2024-04-26T07:29:45.487Z level=INFO source=images.go:824 msg="total unused blobs removed: 0"
time=2024-04-26T07:29:45.487Z level=INFO source=routes.go:1143 msg="Listening on [::]:11434 (version 0.1.32)"
time=2024-04-26T07:29:45.488Z level=INFO source=payload.go:28 msg="extracting embedded files" dir=/tmp/ollama188207103/runners
time=2024-04-26T07:29:48.896Z level=INFO source=payload.go:41 msg="Dynamic LLM libraries [cuda_v11 rocm_v60002 cpu cpu_avx cpu_avx2]"
time=2024-04-26T07:29:48.896Z level=INFO source=gpu.go:121 msg="Detecting GPU type"
time=2024-04-26T07:29:48.896Z level=INFO source=gpu.go:268 msg="Searching for GPU management library libcudart.so*"
time=2024-04-26T07:29:48.897Z level=INFO source=gpu.go:314 msg="Discovered GPU libraries: [/tmp/ollama188207103/runners/cuda_v11/libcudart.so.11.0]"
time=2024-04-26T07:29:48.910Z level=INFO source=gpu.go:126 msg="Nvidia GPU detected via cudart"
time=2024-04-26T07:29:48.911Z level=INFO source=cpu_common.go:11 msg="CPU has AVX2"
time=2024-04-26T07:29:49.089Z level=INFO source=gpu.go:202 msg="[cudart] CUDART CUDA Compute Capability detected: 6.1"
[GIN] 2024/04/26 - 07:29:50 | 200 | 45.692µs | 127.0.0.1 | HEAD "/"
[GIN] 2024/04/26 - 07:29:50 | 200 | 378.364µs | 127.0.0.1 | GET "/api/tags"
downloading model llama3:70b
[GIN] 2024/04/26 - 07:29:50 | 200 | 15.058µs | 127.0.0.1 | HEAD "/"
pulling manifest ⠏ time=2024-04-26T07:30:20.512Z level=INFO source=images.go:1147 msg="request failed: Get \"https://registry.ollama.ai/v2/library/llama3/manifests/70b\": dial tcp 172.67.182.229:443: i/o timeout"
[GIN] 2024/04/26 - 07:30:20 | 200 | 30.012673354s | 127.0.0.1 | POST "/api/pull"
pulling manifest
Error: pull model manifest: Get "https://registry.ollama.ai/v2/library/llama3/manifests/70b": dial tcp 172.67.182.229:443: i/o timeout
大模型的生成速度非常慢
70b
是 700 億引數的大模型,使用 CPU 執行不太現實,使用 GPU 也得視訊記憶體足夠大,實測用 24G 視訊記憶體的顯示卡執行速度也非常非常慢,如果沒有更好的 GPU,如何提升生成速度呢?
可以使用多張 GPU 卡並行,修改 ollama 的 YAML,在 requests 中宣告 GPU 的地方,多宣告一些 GPU 算卡:
resources:
requests:
nvidia.com/gpu: "4"
這樣,在模型跑起來的時候,幾張 GPU 算卡可以均攤視訊記憶體,而不至於跑滿: