1. 项目缘起与核心目标最近在折腾大模型本地化部署和个性化定制目标很明确让一个开源大模型能更好地理解并处理我手头特定领域的数据。我选择了Google的Gemma 2B/7B模型作为基座因为它开源友好、性能不错且对个人开发者相对友好。但直接全量微调动辄需要数十GB显存对大多数人的硬件来说都是天方夜谭。因此LoRALow-Rank Adaptation这种参数高效微调技术就成了不二之选。它能以极小的参数量通常只占原模型参数的0.1%-1%来学习新任务大幅降低显存和计算需求。我的完整链路是在支持AMD GPU的ROCm环境下使用Axolotl或LLaMA-Factory等微调框架对Gemma进行LoRA微调然后将微调后的LoRA权重与原始模型合并最终封装成Ollama支持的Modelfile格式实现一键本地部署和对话。整个过程涉及异构计算环境搭建、微调脚本编写、模型转换与部署坑点不少。这篇文章就是我的完整操作记录和踩坑总结希望能帮你绕过我走过的弯路。2. 环境准备ROCm on Ubuntu 与核心工具链我的测试机是一台搭载AMD RX 7900 XTX24GB显存的工作站系统为Ubuntu 22.04 LTS。选择ROCm是因为它是AMD GPU的官方计算平台对于运行PyTorch等深度学习框架至关重要。2.1 ROCm 6.0 安装与验证首先必须确保系统内核和软件包是最新的。ROCm对系统版本有要求Ubuntu 22.04是经过充分测试的稳定选择。sudo apt update sudo apt dist-upgrade -y sudo reboot安装ROCm的官方仓库和核心包。这里需要注意网络环境可能导致下载缓慢或失败可以考虑配置国内镜像源或使用代理此处指代网络加速服务具体配置方法因环境而异需自行解决。wget https://repo.radeon.com/amdgpu-install/6.0/ubuntu/jammy/amdgpu-install_6.0.60002-1_all.deb sudo apt install ./amdgpu-install_6.0.60002-1_all.deb -y sudo amdgpu-install --usecaserocm,hip,mllib --no-dkms -y安装完成后需要将当前用户添加到render和video组并设置环境变量。sudo usermod -a -G render,video $USER echo export PATH/opt/rocm/bin:$PATH ~/.bashrc echo export LD_LIBRARY_PATH/opt/rocm/lib:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc验证安装是否成功运行rocminfo查看GPU检测信息确认能识别到你的AMD显卡。运行rocm-smi类似NVIDIA的nvidia-smi查看GPU状态、温度、功耗和显存占用。关键提示如果rocm-smi显示“No GPU found”最常见的原因是系统内核版本与ROCm驱动不兼容。尝试安装linux-headers-generic和linux-image-generic或者将内核升级到ROCm官方支持的具体版本如5.15.0-91-generic。另一个常见坑是权限问题务必确认用户已在render和video组中有时需要完全注销再重新登录才能生效。2.2 PyTorch with ROCm 及微调框架选型PyTorch官方为ROCm提供了预编译的wheel包。访问PyTorch官网根据你的ROCm版本选择对应的安装命令。例如对于ROCm 6.0pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.0安装后在Python中运行以下命令验证PyTorch是否能正确调用AMD GPUimport torch print(fPyTorch version: {torch.__version__}) print(fIs ROCm available? {torch.cuda.is_available()}) # 注意在ROCm下cuda这个API名称被复用 print(fDevice name: {torch.cuda.get_device_name(0)})如果一切正常会显示你的AMD显卡型号。接下来是微调框架的选择。我主要对比了Axolotl和LLaMA-Factory。Axolotl配置驱动通过一个YAML文件定义几乎所有训练参数对实验管理和复现非常友好。它封装得很好但自定义训练循环或复杂逻辑时不够灵活。LLaMA-Factory提供了Web UI和命令行两种方式对新手更友好。它的代码结构清晰易于修改和调试并且集成了多种微调方法LoRA, QLoRA, Full等。考虑到我需要更精细的控制和调试最终选择了LLaMA-Factory。它的安装也很简单git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e .[torch,metrics]2.3 模型与数据准备模型下载从Hugging Face下载Gemma模型。你需要先访问Hugging Face网站同意Gemma的使用协议然后使用huggingface-cli登录并下载。pip install huggingface-hub huggingface-cli login # 输入你的HF token huggingface-cli download google/gemma-2b-it --local-dir ./model/gemma-2b-it数据准备LoRA微调的效果极度依赖于数据质量。我的数据是JSON格式的指令遵循Instruction-Following数据结构如下[ { instruction: 将以下中文翻译成英文。, input: 今天天气真好。, output: The weather is really nice today. }, { instruction: 解释什么是机器学习。, input: , output: 机器学习是人工智能的一个分支它使计算机系统能够从数据中学习并改进而无需进行明确的编程。 } ]LLaMA-Factory支持多种格式如alpaca、sharegpt等。我需要将数据转换为对应的格式。通常我会准备一个dataset_info.json文件来定义数据集。3. LoRA微调实战配置、训练与问题排查一切就绪开始最核心的微调环节。3.1 训练配置详解在LLaMA-Factory中我使用命令行进行训练。一个典型的训练命令如下CUDA_VISIBLE_DEVICES0 python src/train_bash.py \ --stage sft \ --model_name_or_path ./model/gemma-2b-it \ # 基座模型路径 --do_train \ --dataset my_dataset \ # 数据集名称在dataset_info.json中定义 --template gemma \ # 使用Gemma专用的对话模板 --finetuning_type lora \ # 微调类型lora --lora_target q_proj,v_proj \ # LoRA注入的目标模块。对于Gemma通常是注意力机制中的Q、V投影层 --output_dir ./saves/gemma-2b-lora \ # 输出目录 --overwrite_cache \ --per_device_train_batch_size 4 \ # 根据显存调整。24G显存的7900XTX2B模型可以设到8-16。 --gradient_accumulation_steps 4 \ # 梯度累积步数用于模拟更大的batch size --lr_scheduler_type cosine \ --logging_steps 10 \ --save_steps 500 \ --learning_rate 5e-5 \ # LoRA学习率通常比全量微调大1e-4到5e-5 --num_train_epochs 3.0 \ --plot_loss \ # 绘制损失曲线 --fp16 # 使用混合精度训练节省显存并加速关键参数解析lora_target这是LoRA微调的灵魂参数。它决定了将可训练的LoRA适配器添加到原始模型的哪些线性层。对于类似LLaMA、Gemma的Transformer架构通常选择注意力机制中的q_proj查询投影和v_proj值投影。有些实践也会加上k_proj、o_proj。通过仅微调这些关键投影层就能高效地改变模型的行为。你可以通过--lora_target all尝试添加到所有线性层但这会增加参数量和显存消耗。per_device_train_batch_size和gradient_accumulation_steps实际有效的总批次大小 per_device_train_batch_size*gradient_accumulation_steps。如果显存不足就减小前者增大后者但训练时间会变长。fp16混合精度训练。在AMD ROCm上使用FP16有时会遇到稳定性问题。如果训练中出现损失值为NaN可以尝试移除--fp16使用纯FP32训练但这会显著增加显存占用。另一个更优的选项是使用--bf16如果你的硬件支持。ROCm 6.0和RX 7000系列GPU支持BF16它比FP16具有更宽的动态范围训练更稳定。3.2 训练过程监控与常见问题启动训练后控制台会输出损失值、学习率等信息。LLaMA-Factory还会在输出目录生成一个trainer_log.jsonl文件记录所有日志。使用--plot_loss参数会在训练结束后生成损失曲线图便于直观判断模型是否收敛损失值应平稳下降并趋于平缓。我遇到的主要问题及解决方案CUDA Out Of Memory (OOM)现象训练开始不久即报错。排查首先运行rocm-smi监控显存占用。使用--per_device_train_batch_size 1和--gradient_accumulation_steps 1启动看是否是基础显存不足。解决逐级降低per_device_train_batch_size。启用梯度检查点--gradient_checkpointing这是一种时间换空间的技术会稍微降低训练速度但能节省大量显存。如果使用了--fp16尝试关闭它或改用--bf16。对于Gemma-7B在24G显存上使用QLoRA4-bit量化可能是必须的LLaMA-Factory也支持--quantization_bit 4。损失值为NaN或训练不稳定现象损失曲线剧烈波动或突然变成NaN。排查这通常是梯度爆炸或精度问题。检查学习率是否过高。对于LoRA5e-5是一个不错的起点对于7B模型可以尝试1e-5。解决降低学习率--learning_rate 1e-5。添加梯度裁剪--max_grad_norm 1.0。将--fp16改为--bf16或移除。确保数据集格式正确没有异常字符或空样本。ROCm相关内核崩溃或HIP错误现象报错信息中包含HIP、hipError或直接导致系统卡顿。排查这可能是ROCm驱动、PyTorch版本或内核不兼容的深层次问题。解决确保严格按照ROCm官方文档安装指定版本。尝试完全卸载PyTorch后重新从ROCm专属索引安装。有时降低PyTorch版本如从2.3.0降到2.2.0可以解决临时兼容性问题。在社区论坛如ROCm GitHub Issues搜索特定错误码。3.3 模型导出与合并训练完成后输出目录./saves/gemma-2b-lora里保存的是LoRA权重通常是adapter_model.bin或safetensors格式而不是一个完整的模型。为了在Ollama中部署我们需要将LoRA权重与原始基座模型合并成一个完整的、独立的模型文件。LLaMA-Factory提供了导出脚本python src/export_model.py \ --model_name_or_path ./model/gemma-2b-it \ --adapter_name_or_path ./saves/gemma-2b-lora \ --template gemma \ --finetuning_type lora \ --export_dir ./merged_model/gemma-2b-my-lora \ --export_size 2 \ # 量化位数2表示FP164表示4-bit量化 --export_legacy_format false # 导出为Hugging Face标准格式这个命令会创建一个新的目录./merged_model/gemma-2b-my-lora里面包含了完整的模型文件pytorch_model.bin,config.json,tokenizer.*等。这个模型已经“学会”了你的数据可以独立运行。4. Ollama本地部署封装、运行与优化Ollama的魅力在于它简化了本地大模型的运行通过一个简单的Modelfile进行定义。4.1 创建Modelfile在合并后的模型目录同级创建一个Modelfile文件FROM ./merged_model/gemma-2b-my-lora # 设置参数 PARAMETER temperature 0.7 # 控制随机性越高越有创意越低越确定 PARAMETER top_p 0.9 # 核采样参数影响输出多样性 PARAMETER num_ctx 4096 # 上下文长度不能超过模型训练时的最大值 # 设置系统提示词塑造模型角色 SYSTEM 你是一个专业、友好的助手精通我所微调的特定领域知识。请用清晰、准确的方式回答用户的问题。FROM指令可以直接指向本地文件夹路径。这使得部署自己微调的模型变得极其简单。4.2 创建并运行Ollama模型使用ollama create命令基于Modelfile构建一个可用的模型ollama create my-gemma-lora -f ./Modelfile这个过程会读取本地的模型文件并进行一些优化封装。完成后就可以像使用任何其他Ollama模型一样运行它ollama run my-gemma-lora然后就可以在命令行中进行对话了。你也可以通过Ollama的REST APIhttp://localhost:11434与模型交互或者集成到OpenAI兼容的客户端中。4.3 性能调优与实用技巧加速推理在运行ollama run时可以添加-numa参数尝试优化CPU内存访问对于多CPU插槽的系统可能有效。更根本的加速依赖于GPU。确保Ollama能使用GPU运行ollama ps查看模型运行时是否显示GPU信息。Ollama默认会利用可用的GPU。显存管理如果同时运行多个模型实例注意显存占用。使用ollama ps查看运行中的模型用ollama stop model-name停止不需要的实例。自定义系统提示词Modelfile中的SYSTEM指令非常强大。你可以在这里精确定义模型的角色、回答风格和禁忌这比在数据集中反复强调要高效得多。例如你可以要求它“始终以要点列表形式回答”、“避免使用专业术语”等。模型版本管理如果你对同一个基座模型进行了多次不同数据或参数的微调可以通过创建不同的Modelfile指向不同的合并模型路径和不同的模型名如my-gemma-lora-v1,my-gemma-lora-v2来进行管理和A/B测试。5. 效果评估与迭代循环部署完成后如何知道微调是否成功定性测试准备一组涵盖微调领域和通用领域的测试问题。观察模型在“领域内”问题上的回答是否比原始Gemma更准确、更专业在“领域外”的通用问题上能力是否出现严重退化好的LoRA微调应该在提升目标能力的同时尽量保留模型的原始通用能力。定量评估可选对于指令遵循任务可以使用像MT-Bench这样的基准测试但需要将其转化为适合你领域的评估集。更实用的方法是构建一个包含标准答案的小型测试集使用BLEU、ROUGE等自动评估指标或者使用GPT-4作为裁判进行评分。迭代改进根据评估结果回到数据环节。如果模型在某些问题上表现不佳可能是训练数据中缺少相关示例或质量不高。补充数据、清洗数据、调整数据格式例如尝试思维链CoT格式的数据然后重新进行微调。这是一个“数据-训练-评估”的循环过程。我的几点核心心得数据质量 数据数量几百条精心构造的高质量数据远胜于几万条爬取的脏数据。数据的清晰度、多样性和准确性是LoRA微调成功的基石。LoRA参数不是越多越好lora_r秩和lora_alpha缩放系数是关键超参数。通常r8或16alpha32是一个不错的起点。盲目增加r不仅增加计算量还可能导致过拟合。alpha可以粗略理解为学习率一般设置为r的两倍。注意灾难性遗忘如果微调数据领域非常狭窄模型可能会“忘记”原有知识。在数据集中适当混合一些通用语料如Alpaca数据的一部分可以帮助缓解这个问题这被称为“混合微调”。ROCm环境耐心排错AMD的生态仍在快速发展中遇到问题多查GitHub Issues和ROCm社区文档。版本兼容性是最大的挑战记录下你成功搭配的“系统内核-ROCm-PyTorch”组合这是宝贵的环境快照。从ROCm环境搭建到Ollama最终部署这条链路打通后你就拥有了一个完全在自己掌控之下的、定制化的AI助手。它运行在你的本地硬件上无需担心数据隐私并且可以根据你的需求不断进化。整个过程虽然技术点密集但每一步拆解开来都是可以攻克的标准操作。希望这份详尽的记录能成为你本地化AI之旅的一份实用地图。