模型 / 資料集
predibase/lorax avatar
predibase/lorax

LoRAX:把上千個 LoRA adapter 塞進一張 GPU 的推論伺服器

Multi-LoRA inference server that scales to 1000s of fine-tuned LLMs

3,831 個 Star324 個 ForkPythonApache-2.0

秒懂

它是什麼?
LoRAX 用單一 base model 加上即時載入的 LoRA adapter,讓多租戶微調模型的服務成本不再隨模型數量線性成長。它的價值在排程與批次設計,代價是硬體門檻與 adapter 生命週期管理的複雜度。
適合誰用?
如果你手上有一批共用同一個 base model 的 PEFT 或 Ludwig LoRA adapter,而且服務量足以讓每張 GPU 都閒置浪費,LoRAX 值得進到測試環境;如果你的 adapter 各自基於不同 base model,或你只需要服務一個微調模型,那 LoRAX 的多租戶排程器對你毫無用處,直接跑一般推論框架更單純。導入前先確認三件事:GPU 是否為 Ampere 以上、CUDA 驅動是否達 11.8、adapter 的 target module 是否落在 LoRAX 支援的線性層範圍內。
可以商用嗎?
可以。Apache-2.0 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
還在維護嗎?
有在維護。儲存庫最近一次提交在 110 天前。
用什麼語言寫的?
主要是 Python(依據 GitHub 的語言統計)。

以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。

開源專案深度解析

一張 GPU 服務上千個微調模型,問題出在哪裡

微調模型數量一多,推論成本就開始失控。傳統做法是每個微調模型複製一份完整權重、各自佔一張 GPU,於是 50 個客戶的 50 個模型就要 50 份記憶體,即使多數模型一天只被呼叫幾十次。LoRAX 針對的正是這種長尾分布:adapter 只佔 base model 權重的一小部分,把共用部分留在 GPU 上,讓差異部分按需進出,就能讓同一張卡同時應付大量低頻模型。

目標讀者是已經在用 PEFT 或 Ludwig 訓練 LoRA adapter、並且需要把這些 adapter 當成對外服務的團隊。README 把這件事講得很直接:LoRAX 是「serve thousands of fine-tuned models on a single GPU」的框架。關鍵字是 single GPU 與 thousands,兩個數字放在一起才構成它的存在理由。如果你的微調模型只有三五個,這套排程機制帶來的複雜度大於它省下的成本。

base model 與 adapter 拆開之後,請求怎麼流動

LoRAX 的模型結構只有兩層:一個所有 adapter 共用的 base model,加上每個請求各自指定的 adapter 權重。README 說明 base model 可以是 Llama、CodeLlama、Mistral、Zephyr、Qwen 等,載入格式支援 fp16,或用量化方式壓縮,文件中列出 bitsandbytes、GPT-Q、AWQ 三種。adapter 則來自 HuggingFace Hub、Predibase,或任何本機檔案系統路徑。

請求進來時,adapter_id 決定要掛哪一組權重。這個 id 可以指向遠端 repo,例如 README 範例裡的 vineetsharma/qlora-adapter-Mistral-7B-Instruct-v0.1-gsm8k,伺服器會在請求處理過程中即時抓取並載入,而且文件強調這個載入不會阻塞其他並行請求。真正讓這件事可行的不是載入本身,而是 Heterogeneous Continuous Batching:不同 adapter 的請求被併進同一個 batch 一起算。搭配 Adapter Exchange Scheduling,系統在 GPU 與 CPU 記憶體之間非同步地預取與卸載 adapter,並依此決定批次怎麼排,目標是整體吞吐而非單一請求的最快回應。

底層的推論最佳化沿用常見組合:tensor parallelism、flash-attention、paged attention,以及 SGMV 這類專為多 adapter 設計的 CUDA kernel。v0.12.0 的 release note 另外提到 Multi-LoRA prefix caching 與 fp8 kv cache,前者對共用相同 system prompt 的多 adapter 場景有幫助,後者直接影響 KV cache 的記憶體佔用。這些機制彼此相依,拆開看任何一項都不足以解釋 LoRAX 的吞吐表現。

從 docker run 到 adapter_id:實際啟動與呼叫

README 建議直接使用預建 Docker image,理由是避免自行編譯 CUDA kernel 與其他相依項目。硬體前提寫得很明確:Nvidia GPU 需為 Ampere 世代以上、CUDA 11.8 以上的驅動、Linux 作業系統,以及 Docker。

啟動前先安裝 nvidia-container-toolkit,然後執行 sudo systemctl daemon-reload 與 sudo systemctl restart docker。伺服器本體是一行指令:

docker run --gpus all --shm-size 1g -p 8080:80 -v $volume:/data ghcr.io/predibase/lorax:main --model-id $model

其中 $model 在範例中是 mistralai/Mistral-7B-Instruct-v0.1。要注意容器內部監聽的是 80 埠,對外映射到 8080。

呼叫端有兩條路。REST API 走 POST /generate,body 裡的 inputs 放提示文字,parameters 放 max_new_tokens;要指定 adapter 就在 parameters 內加一個 adapter_id 欄位,其餘不變。同一個端點既能打 base model 也能打 adapter,差別只在有沒有帶 adapter_id。Python 端則安裝 pip install lorax-client,用 Client("http://127.0.0.1:8080") 建立連線,再呼叫 client.generate(prompt, max_new_tokens=64, adapter_id=adapter_id)。

README 也提到 OpenAI 相容的 chat API、JSON 模式的 structured output、Prometheus 指標與 Open Telemetry 分散式追蹤,以及透過 per-request tenant isolation 隔離私有 adapter。這些是生產環境會用到的介面,但文件只給出存在性,實際設定鍵值需要查對應的 reference 頁面。

Ampere 門檻與 adapter 生命週期,兩道容易低估的牆

第一個限制寫在需求清單裡,沒有模糊空間:GPU 必須是 Ampere 世代以上。這直接排除了 V100、T4 這類仍大量存在於舊機房的卡。原因不難推測,flash-attention 與 paged attention 這類核心最佳化對運算能力有要求,LoRAX 並沒有為較舊架構保留退化路徑。如果你的現有資源是 T4 叢集,評估到此就可以停。

第二個限制不在硬體,而在 adapter 的來源與變動。Dynamic Adapter Loading 的賣點是請求帶著 adapter_id 就能載入,但這意味著 adapter 的可用性與網路、Hub 狀態綁在一起。文件描述載入不會阻塞並行請求,卻沒有說明首次載入的延遲落在哪裡、失敗時請求會回什麼錯誤、以及同一組 adapter 被卸載後再次命中是否要重新抓取。這些是壓測時最先暴露的問題,而 README 層級的材料無法回答。

還有一個結構性前提:所有 adapter 必須共用同一個 base model。LoRA 的設計本來就是相對 base model 的增量,一旦你的微調模型分散在不同 base model 上,就得分別起多個 LoRAX 實例,單卡服務上千模型的算術立刻不成立。這是選型時最該先盤點的一件事。

和 vLLM 的差別不在速度,在誰負責管理 adapter

最直接的替代方案是 vLLM,它同樣提供 OpenAI 相容 API,同樣支援 continuous batching 與 paged attention。兩者真正分岔的地方是 adapter 的處理層級。

vLLM 的 LoRA 支援以 --enable-lora 與 --lora-modules 這類啟動參數為主,adapter 在服務啟動時註冊,之後以模型名稱定址。這種模式適合 adapter 集合固定、可以隨部署一起版本化的情境,運維邏輯和部署一般模型沒有差別。LoRAX 走的是另一條路:adapter 由請求本身帶入,伺服器負責在 GPU 與 CPU 之間調度,並把不同 adapter 的請求併批。差別不在單一請求的延遲,而在於當 adapter 數量遠大於 GPU 記憶體能同時容納的數量時,誰來決定什麼時候換入、什麼時候換出。vLLM 把這個決定交給部署者,LoRAX 把它做成執行期的排程問題。

代價是狀態。LoRAX 的服務實例會隨請求累積 adapter 快取,你需要理解它的卸載策略才能預測記憶體行為;vLLM 的 adapter 集合在啟動後就固定,記憶體輪廓好推算。如果你的 adapter 數量在個位數到數十個、且變動不頻繁,vLLM 的模型更單純;如果 adapter 是持續新增的長尾集合,LoRAX 的即時載入與換出才是它存在的意義。

版本節奏與 Apache-2.0 的實務含義

從 release 列表看,2024 年 11 月連續出了 v0.12.0 與 v0.12.1,前者帶進 Multi-LoRA prefix caching、fp8 kv cache、Mllama 與 function calling,後者是兩週後的修補。2025 年 1 月出了 lorax-0.4.0,命名規則與先前的 v0.x 不同,這種版本號跳動本身是升級時要留意的地方,部署前應確認對應的 Docker tag 與 Python client 版本是否匹配。倉庫在 2026 年 5 月仍有推送,並非停滯專案。

授權是 Apache-2.0,README 也明講可商用。這對需要把推論服務包進產品的團隊是實質利多,但授權只涵蓋 LoRAX 本身。base model 與 adapter 各自帶著自己的授權條款,Mistral、Llama、Qwen 的使用限制並不相同,這部分不是 LoRAX 能替你處理的。

維護成本主要落在兩處:一是 CUDA kernel 與驅動的相容性,官方為此提供預建 image,等於把升級壓力轉嫁到 image tag 的跟進上;二是 adapter 的版本治理,當 adapter_id 直接寫在請求裡,誰能呼叫哪個 adapter 就變成應用層的授權問題,README 提到的 per-request tenant isolation 正是為此存在,但具體設定方式需查文件。

編輯結論

如果你手上有一批共用同一個 base model 的 PEFT 或 Ludwig LoRA adapter,而且服務量足以讓每張 GPU 都閒置浪費,LoRAX 值得進到測試環境;如果你的 adapter 各自基於不同 base model,或你只需要服務一個微調模型,那 LoRAX 的多租戶排程器對你毫無用處,直接跑一般推論框架更單純。導入前先確認三件事:GPU 是否為 Ampere 以上、CUDA 驅動是否達 11.8、adapter 的 target module 是否落在 LoRAX 支援的線性層範圍內。驗證順序建議先用 README 的 docker run 指令搭配 mistralai/Mistral-7B-Instruct-v0.1 起服務,再以 curl 對 /generate 帶入 vineetsharma/qlora-adapter-Mistral-7B-Instruct-v0.1-gsm8k,確認 adapter 能即時載入且不阻塞並行請求,最後才把真實 adapter 接上。

官方來源

  1. License: Apache-2.0
  2. predibase/lorax on GitHub
  3. Project website
  4. README
  5. Releases
社群筆記

社群筆記