如何微調 LLM [以及何時改用 RAG 或提示詞]

本指南逐步說明如何微調 LLM,比較全面微調與 LoRA 及 QLoRA 的分別,並說明何時使用提示詞或 RAG 是改善模型輸出的更佳方法。

Diagram comparing pre-training and fine-tuning: pre-training turns a vast general text corpus (trillions of tokens, large labs, huge compute) into a base model, while fine-tuning combines a base model with a small task-specific dataset (a few hundred to a few thousand examples, one GPU, hours) to produce a specialized model.

微調大型語言模型(LLM)是指以細小、針對特定任務的數據集,進一步優化已預訓練的 LLM,讓它產生單靠提示無法得到的輸出。

微調的過程包括:收集能展示理想行為的輸入/輸出範例組合、執行訓練使模型權重朝這些範例調整,再將結果與原始模型的輸出作比較。LoRA 等參數高效方法令成本大幅降低,只需單一 GPU 便能執行。

如果你對 LLM 的輸出不滿意,請先優化提示和檢索增強生成(RAG)。微調改變的是 LLM 的行為方式。如果你需要它使用最新或專有資訊,提示和 RAG 通常是更好的選擇。

以下將逐步說明如何微調 LLM、主要的微調方法(LoRA 和 QLoRA),以及可能令整個過程失敗的挑戰和錯誤。

甚麼是 LLM 微調,與 LLM 預訓練有何不同

LLM 預訓練是以龐大的語料庫從零開始建立模型的通用語言能力;而 LLM 微調則是以細小的數據集調整已預訓練的模型,使其專注於單一工作。

LLM 預訓練是產生基礎模型、耗用大量資源的階段。模型從廣泛的文本語料庫中學習,因而掌握一般的文法、事實和推理能力,但並未針對你的任務進行專門訓練。

LLM 微調是在經精心整理的細小數據集上繼續訓練基礎模型,使其針對特定任務或使用情境產生理想的輸出。例如一致的格式、品牌語調或語氣、特定領域的模式,或可靠的工具與函數呼叫。

何時應微調 LLM,何時應改用提示或 RAG

要提升 LLM 的表現,應循序漸進:提示 -> RAG -> 微調。

以更詳細的指示優化提示,並使用 RAG 為模型提供最新資訊。只有在改善提示和檢索都未能奏效時,才使用微調。

做法

改變的對象

適用情況

主要限制

提示工程

你發送的請求

行為已接近理想,而你希望快速見效且可隨時還原

受限於基礎模型現有的能力

RAG

模型在推論時看到的內容

事實經常變化,而你需要 LLM 存取最新資訊

會增加檢索延遲及基礎設施負擔;不會改變行為

LLM 微調

模型的權重(模型內部參數)

你需要大規模維持一致的行為、格式或語氣,或在每次呼叫時使用較短的提示

前期成本高、融入權重的知識會過時、有遺忘預訓練行為的風險

何時更好的提示勝過微調,何時又不足夠

提示是最快捷、最便宜的方法。在許多情況下,更準確、更詳細的提示已能達到所需的行為改變。

不過,較長的提示會拖慢工作、增加成本,而且無法克服模型現有的限制。

提示可能已達極限的跡象:

  • 新的邊緣情況不斷令輸出出錯:例如,你需要 JSON 時模型卻傳回一般文字,或者語氣走樣,而你要為每個新情況修補提示。
  • 系統提示越來越長:提示長達數百甚至數千行,難以管理。
  • 每次呼叫都要付出代價:每個請求都會重新發送和處理提示,因此 token 成本和延遲不斷增加。
  • 修改不再見效:新增的指示未能改善輸出。

即使如此,仍應先嘗試成本較低的提示層面修正。你可以使用少樣本範例向模型展示模式(輸入/輸出組合)、使用提示鏈將困難任務拆分為較小的步驟,或使用函數呼叫掛鈎來處理精確的查詢或運算。

何時 RAG 比微調模型更合適

RAG 改變的是 LLM 所知道的內容,而 LLM 微調改變的是它的行為方式。如果欠缺的是知識,特別是經常變化或存在於你自己文件中的知識,RAG 就是答案。如果欠缺的是行為,就應進行微調。

微調也會改變模型所知道的內容,但它吸收的任何事實都會凍結在訓練時的狀態,在發展迅速的領域中很快便會過時。而且這些資訊會融入模型的權重之中,因此無法追溯其來源。

更新檢索層所使用的來源文件更快捷、更便宜,而且檢索層可以引用其所用的確切來源。因此,當你需要有據可依的最新資訊時,這是更好的選擇。

RAG 的缺點?你需要額外建立和維護一層架構,而且它會增加延遲。

實際上,你往往兩者都需要。生產系統會將微調模型與 RAG 結合使用,前者負責一致的行為,後者負責提供最新事實。

常見的微調陷阱、風險和挑戰

即使微調是合適的工具,它亦有其成本和風險:

  • 成本和時間:整理乾淨且具代表性的訓練數據,以及訓練所需的運算資源,都相當昂貴。
  • 災難性遺忘:以範圍狹窄的數據集訓練後,模型可能會失去通用技能,並產生新的失效模式,犯下基礎模型原本不會犯的錯誤。
  • 過度擬合:如果數據太少或過於重複,模型會死記你的訓練範例而非學習模式,因此在訓練樣本上表現良好,但面對真實輸入時表現欠佳。
  • 過時:融入權重的知識很快便會過時,因此你必須以新數據重新訓練。
  • 被淘汰:當更強大的模型推出時,它往往無需任何調整便勝過你的微調模型,你只能重做一遍。
  • 評估與重現的挑戰:要證明微調模型的表現勝過基礎模型並不容易。即使設定相同,兩次 GPU 訓練也可能產生略有不同的模型。
  • 數據管治:以專有或敏感數據進行訓練會引起私隱和授權方面的問題;模型日後可能會洩露其訓練內容的片段。

主要的微調方法

不同類型的 LLM 微調,主要分別在於改變模型的程度:完整微調會重新訓練整個模型,而 LoRA 和 QLoRA 等參數高效微調(PEFT)方法只會更新部分權重。PEFT 方法所需的記憶體只是完整微調的一小部分,而且只要設定得宜,效果亦可與之媲美。

完整微調會更新模型的每一個權重。這是成本最高的方法,出現災難性遺忘的風險亦最高。請只在擁有足夠數據和運算資源支援時,才將其用於大幅度的行為改變。

另一個選擇是參數高效微調(PEFT)。這是一個統稱,泛指凍結模型大部分參數、只訓練一小組參數的方法。由於基礎模型保持完整,它使用的記憶體少得多,亦較不容易出現遺忘。

在低秩設定下,PEFT 的學習效果不及完整微調,但提高秩並調整學習率,便能在指令微調任務上縮窄大部分差距。

PEFT 方法包括:

  • LoRA(低秩適應):最常用的起點。它會凍結原始權重,只訓練一小組新增的適配器參數,通常不到總數的 1%,因此單一消費級 GPU 便能執行。
  • QLoRA(量化低秩適應):它會先將基礎模型壓縮至 4 位元精度,再套用 LoRA,讓你可以在單一 GPU 上微調大型模型。

方法

更新的對象

實際硬件需求

適用情況

完整微調

模型中的每一個權重

7B 級模型需要多 GPU 節點,更大的模型則需要多得多

你需要深度的行為改變,並擁有足夠的數據和運算資源

LoRA(PEFT)

一小組新增的適配器權重

單一消費級 GPU

你的預設起點

QLoRA(PEFT)

在 4 位元壓縮基礎模型上使用 LoRA 適配器

單一 GPU 即可運行超大型模型

你的記憶體不足,但想使用大型基礎模型

除此之外,我們亦會使用指令微調和偏好微調方法,由 RLHF(基於人類回饋的強化學習)到較輕量的替代方案,例如直接偏好優化(DPO)和勝算比偏好優化(ORPO),以塑造模型遵循指示和符合人類偏好的方式。

如何逐步微調 LLM

確定微調 LLM 是正確的選擇後,以下是具體的工作流程。

第 1 步:定義任務及衡量成功的方式

決定你希望 LLM 呈現甚麼行為,以及如何確認已經達到。

列明你希望微調模型完成的具體工作,例如將支援工單分類、以固定格式總結合約,或按照公司內部的風格產生程式碼。

然後定義何謂成功。常見的選項包括:

  • 輸出有效性:例如,結果能否解析為有效的 JSON,或是否符合你需要的 Markdown 結構?
  • 自動評分:使用 BLEU 或 ROUGE 等指標,將產生的文本與參考答案作比較,或在已標記的數據集上量度任務準確度。
  • 人工評分:針對語氣或實用性等腳本難以評分的特質,採用評分制或合格/不合格的評分準則。
  • 處理困難輸入的可靠性:它能否處理曾經難倒基礎模型的特殊輸入?

第 2 步:準備數據集

數據質素決定微調能否成功,因此要投入心力收集合適的微調數據集。

將數據整理成 JSONL 格式的指令/回應組合,每一行包含輸入(以及任何上下文)和你希望得到的確切輸出。

你可以參考一些公開數據集,例如通用指令的 Alpaca-cleaned 數據集或 Databricks 的 Dolly,或者針對特定任務的 banking77,其中包含超過 13,000 個真實的支援查詢,並標記為 77 種意圖。

對於目標明確的任務,數百至數千個乾淨且多樣化的範例便足以改變行為,前提是這些範例能反映真實的生產輸入(包括邊緣情況),而且格式一致。

還沒有輸入/輸出組合?可以利用你現有的數據建立數據集,例如支援工單及其最佳回覆,或文件及其摘要。

如果你只有輸出,可以使用更強大的模型為每個輸出產生合理的輸入,或者人手編寫一小組種子數據,再以更大型的「教師」模型擴充,然後保留最佳的組合。

最後,將數據分為訓練集、驗證集和測試集,以便使用模型未曾見過的範例進行量度。

第 3 步:選擇基礎模型和方法

先從 30 億至 70 億參數的小型開源模型入手,並搭配 LoRA 或 QLoRA 等參數高效微調方法。

Llama、Mistral 和 Qwen 等開放模型系列為你提供可自行託管的強大基礎,而 PEFT 方法則令硬件門檻維持在低水平:QLoRA 會將基礎模型量化為 4 位元,因此微調 7B 模型只需一張 16-24GB 的消費級顯示卡。若要對同一模型進行完整微調,所需記憶體則是其許多倍。

第 4 步:設定訓練超參數

以下是主要的 LLM 微調參數及建議的起始範圍:

  • 學習率控制每次權重更新的幅度。Biderman 等人於 2024 年進行的研究發現,LoRA 的最佳學習率大約是完整微調的十倍,一般為 5e-5 至 5e-4,而完整微調則為 1e-5 至 5e-5。該研究建議在 1e-5 至 5e-4 之間進行掃描,並採用能穩定訓練的最高值。
  • 批次大小是指模型每次更新權重前所學習的樣本數量。使用單一 GPU 時,可將每部裝置的批次大小設為 1 至 8 的較小值,並配合梯度累積,令有效批次大小達到約 16 至 64。
  • 訓練週期數是指模型完整看過整個數據集的次數。訓練模型執行特定任務時,1 至 3 個週期是不錯的經驗法則,但 LoRA 訓練通常需要更多週期。
  • LoRA 秩(r)決定適配器的容量,即它能學到多少。處理較簡單的任務時可從 8 至 32 開始,任務越困難就調得越高:在上文引用的 Biderman 等人的 LoRA 研究中,以程式碼對 7B 模型進行指令微調時,需要秩 256 才能達到與全面微調相當的效果,而在數學任務上,秩 64 已相當接近。
  • 最大序列長度是指該次訓練所能處理的最長輸入。請將其設定為足以涵蓋最長的樣本,上限為模型的上下文視窗,因為超出長度的內容都會被截斷。
  • 預熱與排程控制學習率在整個訓練過程中如何逐步提升及變化。短暫預熱加上餘弦衰減是常見的預設做法。不過,Pareja 等人針對小型模型的研究發現,取消預熱並不會影響最終分數。

請將這些數值視為參數掃描的起點,而非固定不變的設定。

第 5 步:訓練模型並監察損失

訓練進行期間,留意訓練損失和驗證損失曲線,以判斷訓練是否奏效。

損失用於衡量模型輸出與你的樣本之間的差距,並應隨着訓練推進而平穩下降。訓練損失根據模型用來學習的數據計算,驗證損失則根據預留的樣本計算。

如果訓練損失和驗證損失一同下降,代表模型正在學習泛化。如果訓練損失持續下降,但驗證損失趨於平緩甚至回升,代表模型正在死記訓練集,而非學習當中的規律(過度擬合)。

第 6 步:先評估,再部署

訓練損失低並不保證輸出正確,因此請根據你在第 1 步設定的標準評估微調後的模型。

模型通過評估後,你有兩種部署方式:

  • 在基礎模型之上搭載適配器提供服務,並在執行時同時載入兩者;這樣便可隨時替換適配器。
  • 將適配器合併到基礎權重中,得到一個更易於託管的單一獨立模型。

使用 Perplexity 讓你的 LLM 取得最新資訊

如果你想讓模型行為配合自身需要,微調就是正確的選擇。

如果你的模型需要最新資訊,特別是變化迅速的資訊,就需要 RAG 或可靠的第三方搜尋工具。

自訂檢索架構最適合用於專有數據集,例如你的內部 Wiki、客戶支援記錄、合約或產品文件。

如果你想使用的知識是公開的,就無需自行構建專屬的檢索層。Perplexity 是一個答案引擎,能根據即時網絡索引提供附有可點擊內嵌引用來源的回應。其 Agent API 只需一次呼叫,即可提供這些以網絡資訊為依據、附有引用來源的答案,讓你的應用程式能夠利用最新來源。

LLM 微調常見問題

可以免費微調 LLM 嗎?

可以,你可以免費微調小型開放式 LLM。例如,Google Colab 的免費方案提供足夠的 GPU 資源,可在 3B 至 8B 的模型上執行 QLoRA,足以應付目標明確的任務。當你需要更多記憶體、更長的訓練時間,或免費方案無法容納的更大基礎模型時,就要開始付費。

你需要自己的 GPU,還是可以在雲端進行微調?

微調 LLM 不一定要擁有自己的 GPU。託管服務和 GPU 雲端供應商按小時出租硬件,因此租用單一 GPU 便足以完成小型模型的 QLoRA 訓練。只有在你經常進行微調,或必須將所有數據保留在自己的機器上時,購買 GPU 才划算。

微調 LLM 需要多長時間?

就小型 LLM 而言,視乎數據集大小和硬件,一次訓練可在數分鐘至數小時內完成。舉例來說,Oumi 在其託管平台上只用了一小時多一點,就完成了 0.8B 模型的全面微調。

較大的模型或數以萬計的樣本,會令所需時間延長至一天或以上:Emburse 的 LoRA 訓練在單一 40GB GPU 上對 7B 模型進行,5,000 個樣本耗時 8 小時,50,000 個樣本則需約 30 小時。

數據有變時,可以持續更新已微調的模型嗎?

你可以用新數據重新微調,但每一輪都會耗費運算資源,並有出現災難性遺忘的風險。對於經常變化的知識,RAG 通常是更好的解決方法,因為你只需更新來源文件,而無需重新訓練。