[繁](./README_ZH.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)):** > 类别:「创意台」