2026年1月12日 星期一

Open-WebUI - 建立知識庫 RAG

我原本的期望是將資料庫的資料表轉出來,

有 TableName, TableDesc, FieldName, FieldDesc, FieldDataType 等資料,

當我要找某個欄位,但是不知道在哪個資料表的時候會有用處。

首先就跟 AI 討論討論,

中間有一大段故事就不說了,

總之最後的結論就是直接轉出 Table Crate SQL ,

然後在後面欄位備註中文就好。

之前有將整個資料庫的資料表轉出成一個檔,

大概 1.1MB ,無奈怎麼轉都無法成功;

後來 AI 說太大,我只好每個資料表都轉出一個檔案,

但是 1,500 個檔案的知識庫用起來效能實在太差了,

我根本沒耐心等結果出來;

最近又重新跟 AI 討論,結論太多檔案效能會不好,

一個檔案就可以了!跟 AI 老是會繞圈圈,總之又繞回原點;

又轉不進去,AI 叫我要切檔案....又來!

總之後來又東問西問的,開始 try 一些東西,結果如下...


1.利用指令監控 log,將 log 丟給 AI 去解答

# 顯示最後 100 行 log 並持續監控 

docker logs -f --tail 100 open-webui


系統資源耗盡問題!

aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host ollama:11434 ... [Too many open files]

這才是真正的起因

  1. Too many open files (開啟太多檔案/連線): Linux 系統把網路連線 (Socket) 也視為檔案。這行錯誤表示 Open WebUI 在短時間內對 Ollama 發起了太多同時的連線,導致系統的 File Descriptor (FD) 額度被用光了,無法再建立新連線。

  2. 為什麼會有 IndexError (陣列越界)?

    • 您有 1336 個切片 (Items) 需要做 Embedding。

    • 但因為連線在中途爆掉,Ollama 只成功回傳了 988 個 Embedding 結果。

    • Open WebUI 的程式碼沒有防呆,它以為會拿到全部,結果迴圈跑第 989 次時發現沒有資料,就崩潰了 (list index out of range)。


🛠️ 解決方案

這個問題不是模型算得慢,而是**「並發請求太多」**塞爆了連線池。請採取以下兩個步驟來修復:

步驟 1:大幅降低 Batch Size (最有效解法)

Open WebUI 預設可能試圖一次處理大量切片,導致瞬間開啟數百個連線。我們需要限制它「細水長流」。

步驟 2:增加 Docker 的 ulimit (治本解法)

如果您的專案很大,建議直接在 Docker 層級放寬「開啟檔案數量」的限制。

在您的 docker-compose.yml 中,針對 open-webui 的服務區塊加入 ulimits 設定:

YAML
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    # ... 其他設定 ...
    ulimits:
      nofile:
        soft: 65536
        hard: 65536

(如果是用 docker run 啟動,請加上參數 --ulimit nofile=65536:65536)


1.在 .env 檔案增加

# --- Open WebUI 優化設定 --- 

# 這裡設定會覆蓋 docker-compose 預設值 

RAG_EMBEDDING_BATCH_SIZE=5 

WEBUI_TIMEOUT=300


2.在 docker-compose.yml 修改設定

# --- Ollama: RAG 嵌入引擎 (輔助) --- 

ollama: 

     deploy: 

  resources: 

  reservations: 

  devices: 

  - driver: nvidia 

  count: all 

  capabilities: [gpu

  environment: 

  # [優化] 讓 Ollama 允許同時載入 Embedding 模型與 Chat 模型 

  - OLLAMA_MAX_LOADED_MODELS=2 

  # [優化] 允許並發請求,避免 Embedding 把 API 卡死 

  - OLLAMA_NUM_PARALLEL=4 

  volumes: 

  - ./ollama_data:/root/.ollama 


# --- Open WebUI: 前端介面 --- 

open-webui:

ports: 

  - "4000:8080" 

  # [關鍵優化] 解決 "Too many open files" 錯誤 

  ulimits: 

  nofile: 

  soft: 65536 

  hard: 65536 

  environment: 

# [關鍵優化] 解決上傳大檔案 Timeout 與崩潰問題 

  - RAG_EMBEDDING_ENGINE=ollama 

  - RAG_OLLAMA_BASE_URL=http://ollama:11434 

  - RAG_EMBEDDING_MODEL=nomic-embed-text 

  - RAG_EMBEDDING_BATCH_SIZE=${RAG_EMBEDDING_BATCH_SIZE:-5} 

  - WEBUI_TIMEOUT=${WEBUI_TIMEOUT:-300} 

  # 避免自動下載模型,強制用 Ollama 

  - RAG_OPENAI_API_BASE_URL=http://ollama:11434/v1 

  - RAG_OPENAI_API_KEY=ollama 

  volumes: 


總結

  1. 您的 5090 效能太強,加上 SQL 檔案切片很多 (1336 個),導致 Open WebUI 瞬間發送了成千上萬個請求給 Ollama。

  2. Linux 系統啟動了自我保護 (Too many open files) 拒絕連線。

  3. 請優先執行「步驟 1」:將 RAG_EMBEDDING_BATCH_SIZE 改為 5。這雖然會讓進度條跑得稍微慢一點點,但能確保絕對不會因為並發過高而崩潰。


解決了系統層級的「檔案開啟過多 (Too many open files)」問題,現在遇到的是 應用層級的「服務滿載 (503 Service Unavailable)」

簡單來說:Open WebUI 發送請求的速度,還是快過 Ollama 消化請求的速度。

Ollama 的佇列 (Queue) 被塞滿了,於是它對 Open WebUI 喊了 "503" (我沒空),導致 Open WebUI 拿不到資料而崩潰。

我們需要做兩件事來達到「流量平衡」:

  1. 提升 Ollama 的吞吐量 (讓它同時能吃更多單)。

  2. 限制 Open WebUI 的發送速度 (讓它慢慢餵,不要硬塞)。

請更新您的 docker-compose.yml,針對 ollamaopen-webui 區塊進行以下 精細調整 (Fine-tuning)

修正後的 docker-compose.yml 片段

請直接修改這兩個 Service 的 environment 設定:

ollama:

environment: 

  # [原本設定] 

  - OLLAMA_MAX_LOADED_MODELS=2 

  # [關鍵修正 1] 增加並發處理能力 

  # 您的 5090 夠強,這代表 Ollama 可以同時處理 4 個請求,減少 503 機率 

  - OLLAMA_NUM_PARALLEL=4 

  # [關鍵修正 2] 保持模型常駐,避免反覆載入卸載造成的 Timeoout 

  - OLLAMA_KEEP_ALIVE=24h

open-webui:

environment:

# --- [關鍵修正 3: 限流閥] --- 

  - RAG_EMBEDDING_ENGINE=ollama 

  - RAG_OLLAMA_BASE_URL=http://ollama:11434 

  - RAG_EMBEDDING_MODEL=nomic-embed-text 

  # 降到極低!確保穩定性優先於速度 

  # 意義:每次只送 2 個 chunk 給 Ollama (搭配 Ollama 並發=4,絕對不會塞車) 

  - RAG_EMBEDDING_BATCH_SIZE=2 

  # 限制同時發出的 HTTP 請求數,避免 DDoS 自己 

  - RAG_EMBEDDING_CONCURRENT_REQUESTS=2 

  # 增加超時寬限 

  - WEBUI_TIMEOUT=600

為什麼這樣改會成功?

  1. 供需平衡原理

    • 原本:Open WebUI 一次丟 5~10 個請求,但 Ollama 預設一次只能處理 1 個 (OLLAMA_NUM_PARALLEL 預設通常是 1 或自動)。佇列瞬間爆炸。

    • 現在:Open WebUI 限制一次只丟 2 個 (BATCH_SIZE=2),而 Ollama 開放一次處理 4 個 (NUM_PARALLEL=4)。

    • 結果:供給 (4) > 需求 (2),Ollama 永遠行有餘力,就不會回傳 503 錯誤。

  2. 執行步驟

    1. 修改 docker-compose.yml

    2. 重啟服務:docker compose up -d (這會重建容器並套用新參數)。

    3. 強烈建議:進入 Open WebUI 後,先刪除那個上傳失敗的檔案,重新整理頁面後再上傳一次。

這次應該能穩穩地看著進度條跑完 100%。雖然速度不會是「秒殺」,但會是「穩定且持續」的。

後續還是有問題!

非常頑固的 503 Service Unavailable 錯誤。這代表即便我們調低了 Batch Size,Open WebUI 的 「原生 Ollama 連接器 (Native Connector)」 還是太脆弱,遇到 Ollama 稍微忙不過來(回傳 503)時,它沒有重試 (Retry) 就直接崩潰了。

我們現在要用一招**「移花接木」**的解法: 不要用 Open WebUI 的 Ollama 連接器,改用 OpenAI 連接器去連 Ollama。

為什麼這樣有效?

Ollama 其實有內建「相容 OpenAI」的 API 介面 (/v1/embeddings)。Open WebUI 的 OpenAI 連接器通常寫得比較好,內建了自動重試 (Auto-Retry) 與指數退避 (Backoff) 機制。當它收到 503 時,它會等一下再試,而不是直接報錯導致程式崩潰。


🚀 修改 Docker Compose (最終解法)

請修改 docker-compose.yml 中的 open-webui 區塊,將環境變數改成以下設定:


# --- Open WebUI: 前端介面 --- 

  open-webui:

environment:

# --- [關鍵修改] 改用 OpenAI 協議連線 Ollama --- 

  # 1. 告訴 Open WebUI 我們要用 "openai" 引擎 (騙它是 OpenAI) 

  - RAG_EMBEDDING_ENGINE=openai 

  # 2. 但網址其實是指向 Ollama 的 v1 接口 

  - RAG_OPENAI_API_BASE_URL=http://ollama:11434/v1 

  - RAG_OPENAI_API_KEY=ollama 

  # 3. 指定模型名稱 (必須與 Ollama 內一致) 

  - RAG_EMBEDDING_MODEL=nomic-embed-text 

  # 4. 極限保守設定:一次只處理 1 批,讓 OpenAI 協議自動處理並發 

  - RAG_EMBEDDING_BATCH_SIZE=1 

  # 5. 增加超時寬限 

  - WEBUI_TIMEOUT=600

最後終於成功了!

沒有留言:

張貼留言