繁 | [简](./README_SC.md) | [EN](./README.md)
原創性:   創新性:   挑戰性:
🛠️ 運作原理 | 📁 文件結構 | 🖥️ 使用說明 | 👀 結果示例 | 📣 常見報錯 | 🙋🏻♂️ 常見問題
# 連登語言模型 LiLM 受 [林亦](https://www.youtube.com/@lyi) 的 [bilibot 項目](https://github.com/linyiLYi/bilibot/tree/main) 和 [影片](https://www.youtube.com/watch?v=52clfKcM4M4&t=1s) 所啟發,本實驗性項目使用帶有獨特語言風格的 [LIHKG 討論區](https://lihkg.com) 用戶回應作微調訓練,創建了這個廣東話貼文回應生成語言模型。 在平衡運算成本和 [基礎模型的中文能力](https://github.com/jeinlee1991/chinese-llm-benchmark) 後,本實驗性項目選用的開源基礎模型為 [Qwen/Qwen1.5-32B-Chat](https://huggingface.co/Qwen/Qwen1.5-32B-Chat),具有320億參數,借助 Apple Silicon 平台 AI 專用框架 [MLX](https://github.com/ml-explore/mlx) 的 [MLX-LM LoRA 微調示例](https://github.com/ml-explore/mlx-examples/blob/main/llms/mlx_lm/LORA.md#fine-tune),利用 [LoRA 算法](https://arxiv.org/abs/2106.09685) 在 M3 Max 128GB 和 M2 Ultra 192GB 上對基礎模型進行微調。 微調後的模型在廣東話語言能力上有顯著提升,其語氣和風格亦深受一眾 [連登](https://zh.wikipedia.org/zh-hk/LIHKG討論區) 用戶的薰陶,詳情可參見 [結果示例](#結果示例)。模型已上載至 Hugging Face: [alphrc/lilm](https://huggingface.co/alphrc/lilm/tree/main)。 若想了解更多關於人工智能的資訊,並在未來查看更多創新有趣的項目,請關注 [alphrc](https://github.com/alphrc)。 ### 項目動機 - 本項目旨在展示大型語言模型基於廣東話口語數據和獨特語言風格的語言風格模仿能力,主要用於普及教學、學術研究和技術展示,因此內容會比較詳細 ### 使用限制 - 模型訓練基於公開數據,雖已努力清理敏感內容,但仍可能包含基於訓練內容的偏見,使用時應避免生成不當內容 - 生成的文本反映特定社群文化,使用前應了解相關背景 - 在實際應用前進行充分測試,避免在敏感或爭議性場合使用,並設立監控機制以防生成不當內容 ### 備注 - 本項目所有代碼均為自行編寫,同時亦鼓勵開源社區成員對項目進行審查,提供反饋和建議,以及直接參與項目的改進 - 本項目的性質為第三方訓練框架和模型的使用和實踐,主要挑戰在於系統配置、數據抓取、數據工程、反覆試錯和漫長的等待 - 本項目整理了部分配置信息和內容在 `.env` 文件中,以便使用者根據個人或組織的具體需求自行調整,確保靈活性和適用性,其格式已放置在 `.env.template`,使用時把檔案名稱改為 `.env` 便可 ## 運作原理 ### 微調 大型預訓練語言模型 ([pretrained language model](https://www.kaggle.com/code/vad13irt/language-model-pre-training)),擁有基本和通用的人類語言對答能力。透過特定文字數據對模型進行微調 ([fine-tuning](https://en.wikipedia.org/wiki/Fine-tuning_(deep_learning))),能讓它在這些數據上進一步學習,增加其對數據的模仿能力,如語氣、風格、資訊和用詞等等。要注意,使用特定數據進行微調並不能讓模型從零開始得到語言能力,只能在其本來預訓練而獲得的語言能力上,加深其對局部文字資訊和規律的理解。 ### 數據集 本項目在 [LIHKG 討論區](https://lihkg.com) 進行公開數據的大規模抓取,並透過對原數據的過濾和處理以產生數據集用作微調。為提高數據質量,其過濾基準為: - 貼文的第一則回應不是作者本人,確保回應所基於的資訊的完整性 - 回應反應正面,確保該回應符合討論區主流意見 - 回應的總反應數目不少於 20 以降低噪聲 - 不是在回覆其他回應 - 不是作者自己的回應 - 不包含任何外部連結和鑲嵌 - 不包含敏感字眼 - 總字數加上系統信息不超過 2048 其後以這些回應結合相應貼文的標題、內容和分類,加上系統信息 ([system message](https://promptmetheus.com/resources/llm-knowledge-base/system-message)),轉換成 MLX-LM LoRA 微調示例中所要求的 [格式](https://github.com/ml-explore/mlx-examples/blob/main/llms/mlx_lm/LORA.md#data),隨機排列後生成總數據集。總數據集會以 80 : 10 : 10 的比例分割為訓練集 (training set)、驗證集 (validation set) 和測試集 (testing set),當中測試集的貼文完全沒有在訓練集或驗證集中出現過,以驗證泛化 ([generalization](https://towardsdatascience.com/generalization-in-ai-systems-79c5b6347f2c)) 和避免過擬合 ([overfitting](https://en.wikipedia.org/wiki/Overfitting))。 最終版本的訓練集中包含了約 60000 個貼文中符合基準的 27792 項數據,驗證集和測試集則各包含 3474 項數據。 ### 基礎模型 開源基礎模型 [Qwen/Qwen1.5-32B-Chat](https://huggingface.co/Qwen/Qwen1.5-32B-Chat) 具有320億參數,精度為 BF16。系統在首次使用 MLX-LM 模組運行的時候,若檢測到 `~/.cache` 中沒有下載模型,便會自動從 Hugging Face 上下載模型到 `~/.cache/huggingface/hub/model--Qwen--Qwen1.5-32B-Chat`,用家不需要手動預先下載。模型的大小約為 65GB,分為若干個板塊下載,若下載過程受到中斷,模型會在下次下載的時候自動搜集已下載的板塊以繼續下載,不用擔心需要重新下載。 ### LoRA 在傳統的訓練和微調方法中,需要同時把模型中一些大型矩陣的所有參數進行調整,對電腦內存和計算量有很高的要求。與傳統方法相比,[LoRA (Low Rank Adaption)](https://arxiv.org/abs/2106.09685) 利用兩個小型矩陣去估算模型中的大型矩陣的變化,大幅降低參數的數量,令模型能在較低內存的設備上也能進行輕量化微調,大幅降低了訓練所需的時間。在實際執行中,原來模型的總參數量為 32.5B,而在基礎模型的所有 63 層 attention layer 上使用 LoRA 後,可學習的參數量為 8.3M,僅為本來的 0.026%。 使用 MLX-LM LoRA 去微調模型並不會改變模型本來的參數,而是另外生成 adapters 與模型配合使用。在微調的過程中,MLX-LM 會自動在當前工作目錄 (current working directory) 生成 `adapters/` 文件夾,並把 adapter 的 checkpoints 以 `.safetensors` 格式保存下來,每個 checkpoint 的大小約為 33.6MB,這些 checkpoints 能在之後繼續使用作微調。 ### 梯度檢查點 梯度檢查點 (gradient checkpointing) 是一種用於訓練大型神經網絡時節省記憶體的技術。在神經網絡訓練過程中,為了進行有效的反向傳播 ([backpropagation](https://brilliant.org/wiki/backpropagation/#:~:text=Backpropagation%2C%20short%20for%20%22backward%20propagation,to%20the%20neural%20network's%20weights.)),通常需要保存中間層的輸出結果以用於計算梯度 (gradient)。然而,這會消耗大量的記憶體,尤其是在處理深層網絡時。梯度檢查點的方法是在訓練過程中不保存所有中間層的輸出,而只保存一些關鍵層的輸出。當需要進行梯度計算時,使用這些保存的關鍵點重建丟失的中間數據。這樣可以在保證訓練效果的同時,大幅減少記憶體的使用。 ### 模型融合 微調完畢後,MLX-LM 能把 adapter 和原有的模型混合起來,在當前工作目錄中的 `model/lilm` 文件夾生成一個完整的模型,大小約為 65GB。之後便能直接透過此文件夾的路徑來使用此模型,不用再將原模型和 adapter 一起來使用。 ## 文件結構 - `src/` : Python 代碼 - `data.py` : 多執行緒代理數據抓取、格式化和初步處理 (需要 proxy 來運行) - `dataset.py` : 數據處理、變換和過濾 - `run.py` : LiLM 模型封裝和基本用戶介面 - `data/` : 數據抓取得到的原數據,以 `.csv` 儲存 - `dataset/` : 處理後得到的訓練數據,根據格式分為 `completion/` 和 `chat/` - `adapters/` : 儲存 `mlx_lm.lora` 自動生成的 adapters 和 configuration - `adapters-llama3-70b/`: Llama3-70B 的 adapters - `model/lilm` : 由基礎模型和 adapter 融合而成的融合模型,需運行以下 shell script 生成 - `demo/` : 範例數據,供 `run.py` 使用 ## 使用說明 ### 設備需求 因本項目使用 Apple 專有的 MLX 框架,所以只能在配有 Apple Silicon Chips (M1或以上) 的機器上的 MacOS 系統運行。本地機器需要約 75GB RAM 以順暢地進行推理,並需要約 122GB RAM 以順暢地進行微調。 ### 環境配置 運行以下 shell script,利用 [Anaconda](https://www.anaconda.com) 建立和配置環境,並根據 `requirements.txt` 下載所有所需的 dependency。 ```bash conda create -n lilm python=3.9 conda activate lilm pip install -r requirements.txt ``` ### 監測系統資源用量 (非必要) 利用 `asitop` 模組,透過圖像介面實時監測電腦資源用量,如 CPU、GPU 和 RAM 等,以確保程序在正常運行。 ```bash sudo asitop ``` ### 利用基礎模型進行推理 首次運行會自動下載模型,`--model` 可以使用模型在 Hugging Face 上的全稱或其所在的路徑, ```bash mlx_lm.generate \ --model Qwen/Qwen1.5-32B-Chat \ --prompt "咩係連登?" ``` ### 微調 在 `dataset/chat` 預備數據集 `train.jsonl` 和 `valid.jsonl` 後,從頭開始微調模型,並生成 `adapters/` 文件夾。 ```bash mlx_lm.lora \ --model Qwen/Qwen1.5-32B-Chat \ --train \ --data dataset/chat \ --iters 600 \ --grad-checkpoint ``` ### 繼續微調 使用現有 adapter 繼續進行微調,`--resume-adapter-file` 必須為 `.safetensors` 文件。 ```bash mlx_lm.lora \ --model Qwen/Qwen1.5-32B-Chat \ --resume-adapter-file adapters/adapters.safetensors --train \ --data dataset/chat \ --iters 600 \ --grad-checkpoint ``` 🚨 請注意,你很可能會遇到 [此報錯](#錯誤-1)。 ### 配合 adapter 進行推理 使用基礎模型配合 adapter 進行生成,adapter 必須為 `.safetensors` 文件。 ```bash mlx_lm.generate \ --model Qwen/Qwen1.5-32B-Chat \ --adapter-path adapters/adapters.safetensors \ --prompt "咩係連登?" ``` ### 融合基礎模型和 adapter `adapters/` 中最新的 checkpoint `adapters.safetensors` 會被自動選取來進行融合,並把融合後的模型放置在 `model/lilm`。 ```bash mlx_lm.fuse \ --model Qwen/Qwen1.5-32B-Chat \ --adapter-path adapters \ --save-path model/lilm ``` ### 利用融合模型進行推理 `--model` 中使用融合模型的路徑。 ```bash mlx_lm.generate \ --model model/lilm \ --prompt "咩係連登?" ``` ### 量化模型 (非必要) 利用量化 ([quantization](https://blog.csdn.net/jinzhuojun/article/details/106955059)) 降低模型參數精度,壓縮模型大小,加速推理和減少內存佔用空間。以下的 `--hf-path` 跟之前一樣,可以是 Hugging Face 上模型的完整名字,或者是模型的路徑,而 `--mlx-path` 則是壓縮後的模型所存放的路徑。然而實測後中量化模型準確度會大幅下降,且量化模型不能使用 Hugging Face 的 Transformer 運行。 ```bash mlx_lm.convert \ --hf-path model/lilm \ --mlx-path model/lilm-4Bit \ -q ``` ### 運行 LiLM 使用 `src/run.py` 來運行已融合的模型,可選擇 `interactive` 模式來輸入貼文連結作回應。 ```bash python src/run.py ``` ## 結果示例 LiLM 比起基礎模型在廣東話語言能力上有顯著提升,其語言風格亦受到連登討論區影響。以下內容僅作示例用途,可能具有冒犯性,敏感字眼會以「X」顯示。 ### 示例一 **提示 ([原文](https://lihkg.com/thread/3699748/page/1)):** > 類別:「創意台」