
有一段时间我每次做大模型微调都处于一种半手工状态数据清洗用一个脚本SFT 用 LLaMA-Factory 跑一遍reward model 再单独折腾一套环境PPO 又要换 trl 的版本最后想上线了还得另找时间做量化、剪枝和评测。整个链路下来光环境适配和任务衔接就吞掉一大半时间。后来我把整套流程搬到了 CubeStudio 的大模型任务模板上用 LLaMA-Factory 统一跑 SFT / reward / PPO再做蒸馏、剪枝、量化最后接 OpenCompass 和安全评估才算是把这条流水线真正捋顺。这篇就重点拆解我在这个平台上完成微调—瘦身—验收全过程的实操细节包括每个阶段的命令、参数理由、显存估算和踩过的坑适合正在做模型落地、想规范训练流程的工程师参考。1. 为什么偏偏是平台一站式从裸脚本到模板化流水线先说个很实在的问题微调链路远不止跑一个训练脚本这么简单。你至少需要处理数据格式、模型存取、分布式环境、多阶段任务串联、模型评估、导出部署这些环节。每个环节背后都是一套独立的依赖关系。LLaMA-Factory 虽然本身已经把 SFT、reward modeling、PPO 封装得很友好但你在裸机上用仍需要自己解决 CUDA、PyTorch、transformers、peft、trl 这些库的版本兼容。我曾经在一个项目里因为 trl 版本不兼容导致 PPO trainer 初始化时直接报KeyError: clip_range排查了一整天最后发现是 trl 0.9 和 0.10 之间的 API 变化。CubeStudio 这类平台上的大模型任务模板本质是把最繁琐的运行环境和任务编排固化成半成品净菜。它预置了 LLaMA-Factory 的运行环境、数据集目录约定、任务产出的传递方式你只需要像填表单一样把模型地址、数据集路径、训练参数一填剩下的事情交给平台。我特别想说清楚一点平台模板不是黑盒。它跑的还是 LLaMA-Factory 那一套 CLI 命令只是帮你把环境准备、资源申请、任务之间的依赖关系做成了可复用的模板。换句话说你在这里学会的东西迁回裸机照样能用反过来裸机跑通的命令填进模板也就行了。还有很重要的一点是任务串联。我们经常忽略微调不是一个独立动作而是一条链SFT 的产出是 reward model 的底座reward model 和 SFT 模型一起参与 PPOPPO 之后进蒸馏或剪枝最后还要做评测。在裸脚本里这个链条靠人肉记录路径经常发生下一个任务找不到上一个任务的输出这种情况。平台模板会把每一步的产物保存在约定好的目录里下一个任务直接引用这比我之前自己维护一堆软链接可靠得多。如果你经历过训练任务跑了一半发现路径不对、或者在不同服务器之间来回拷贝模型的痛苦就会明白这一步省了多少事。2. 任务模板的初始配置模型、数据、算力怎么选2.1 基础模型选型基座还是指令版很多人第一步就选错了模型。如果你计划做完整的 SFT reward PPO 对齐我建议从**基座模型base**开始而不是直接用 Chat/Instruct 版。原因很简单instruct 模型已经经过一轮对齐你再拿它做指令微调相当于在别人装修过的房子里再改水电很容易把原有风格带偏出现重复微调后回答啰嗦语气怪异的问题。反过来从 base 模型出发SFT 阶段你完全掌控数据风格后面的 RM 和 PPO 也更干净。平台模板通常会让你填model_name_or_path这里可以直接填模型社区里能访问的模型 ID也可以填平台共享存储里的本地路径。我习惯用本地路径因为多阶段任务之间要反复引用同一个底座模型本地路径稳定性更高也不用每次启动任务都去拉权重。显存方面7B 量级的 base 模型做 LoRA 微调单卡 A100 40G 是舒服的如果只有 24G 显存就开 QLoRA4bit 量化加载再配合梯度累积。2.2 数据集格式提前对齐 LLaMA-Factory 的约定LLaMA-Factory 对数据格式的约定比较死但也就那么几种。最常用的是 alpaca 格式一个 JSON 数组每条包含instruction、input、output三个字段多轮对话则用conversations字段。我强烈建议在进平台之前先用一个 Python 脚本把原始数据统一转成这种格式不要直接拿脏数据上去试。模板虽然有数据校验但格式错误提示往往要到训练开始后才会暴露出来。[ { instruction: 请解释什么是梯度累积, input: , output: 梯度累积是将多个小 batch 的梯度累加后一次性更新参数用来在显存受限时模拟更大的 batch size。 } ]数据处理有两点容易忽略。一是system字段要不要保留。LLaMA-Factory 的 alpaca 格式支持system如果你的任务有固定的角色设定建议每条样本都带上或者在数据集配置里指定系统提示词否则训练时会把系统提示词丢掉上线后模型行为会不一致。二是数据质量要按训练集—验证集—评估集拆分别把一个 CSV 从头到尾全喂进去。平台模板一般允许你在数据集配置里指定val_size我习惯取 5% 做验证剩下的做训练。2.3 算力和批大小估算LoRA 训练 7B 模型用 bf16 per_device_train_batch_size2 gradient_accumulation_steps8等效 batch size 是 16显存占用大约 18G 到 24G。如果你用 QLoRA4bit 加载底座同样的配置大概只需要 12G 左右。平台模板里一般会暴露per_device_train_batch_size、gradient_accumulation_steps、finetuning_type这些参数我的建议是显存充足就 batch size 尽量开到 4减少累积步数训练更稳显存紧张就保持 batch 2但把gradient_checkpointing打开这能显著降低激活值显存学习率和 LoRA rank 的配合要谨慎rank 到 64 之后学习率建议降到 1e-4 左右否则容易震荡。3. LLaMA-Factory 三阶段微调实操SFT、reward、PPO3.1 阶段一SFT 指令微调SFT 是整个对齐链路的地基。在模板里创建一个LLaMA-Factory 训练任务stage 选sft命令本质上长这样llamafactory-cli train \ --model_name_or_path /models/Qwen2.5-7B-Base \ --stage sft \ --dataset my_instruction_data \ --template qwen \ --finetuning_type lora \ --lora_target q,k,v,o \ --output_dir /outputs/sft_model \ --num_train_epochs 3 \ --per_device_train_batch_size 2 \ --gradient_accumulation_steps 8 \ --learning_rate 2e-4 \ --lr_scheduler_type cosine \ --warmup_ratio 0.03 \ --bf16 True \ --gradient_checkpointing True这里最值得解释的是--lora_target。只选 q,k,v,o 是 LoRA 微调的标准保守配置改动参数少、训练稳定适合数据量不太大的场景。如果数据量足够大可以加上gate_proj、up_proj、down_proj模型能学到更多前馈网络的知识但显存和训练时间也会涨。至于学习率LoRA 一般用 1e-4 到 3e-4 之间取 2e-4 是平衡点。全量微调的典型学习率是 1e-5 到 2e-5差一个数量级这个别记混。跑完之后模板会产出 adapter 权重LoRA 的小几百 MB 文件。LLaMA-Factory 支持把它和底座合并导出也可以用export命令导出完整模型。我一般在微调完先合并再用合并后的完整模型去跑 RM 和 PPO这样后续阶段不用每次加载都带 adapter路径干净也避免多阶段任务之间 LoRA 加载混乱。3.2 阶段二reward model 训练reward modelRM不是所有场景都需要但只要你做 PPORM 就是必需品。RM 的输入是一条 prompt 和两个回答——一个 chosen更优一个 rejected更差模型需要学会给 chosen 打出比 rejected 更高的分数。LLaMA-Factory 里 stage 选rm使用的数据集是 preference 格式[ { instruction: 用户指令, input: , chosen: 这是更优的回答内容, rejected: 这是较差的回答内容 } ]训练命令和 SFT 很像差别在于 stage 和输出llamafactory-cli train \ --model_name_or_path /outputs/sft_model \ --stage rm \ --dataset my_preference_data \ --template qwen \ --finetuning_type lora \ --lora_target q,k,v,o \ --output_dir /outputs/rm_model \ --num_train_epochs 1 \ --per_device_train_batch_size 1 \ --gradient_accumulation_steps 16 \ --learning_rate 1e-5 \ --bf16 TrueRM 训练有三个容易踩的坑。第一RM 不需要训练太多 epoch我试过 3 个 epoch 之后验证集上排序准确率不升反降开始对训练集过拟合1 个 epoch 通常足够。第二chosen 和 rejected 必须严格控制除了回答质量外其他条件一致如果 chosen 比 rejected 长一大截、或者格式不同RM 学到的是长度偏好而不是内容质量后面 PPO 会放大这个 bias。第三一个 batch 里只能放一条 prompt 对应的 pairbatch size 1这样模型在 batch 内比较时才不会跨样本混在一起。你会在 RM 训练日志里看到一个类似 acc 的指标代表 pair 判断准确率跑几步之后就心里有数了。3.3 阶段三PPO 对齐PPO 阶段就是把 SFT 模型policy和一个训练好的 RM 拼在一起用强化学习让模型在保持语言能力的前提下学会偏向 RM 认可的回答。LLaMA-Factory 的 stage 选ppo命令会稍微复杂一点因为它要同时加载 policy、reference model 和 reward modelllamafactory-cli train \ --model_name_or_path /outputs/sft_model \ --adapter_name_or_path /outputs/ppo_adapters \ --stage ppo \ --reward_model /outputs/rm_model \ --dataset my_prompt_data \ --template qwen \ --finetuning_type lora \ --lora_target q,k,v,o \ --output_dir /outputs/ppo_model \ --per_device_train_batch_size 1 \ --gradient_accumulation_steps 8 \ --learning_rate 1e-5 \ --bf16 True \ --kl_coef 0.1PPO 里最关键的直觉是光追求 RM 分数高模型会慢慢忘掉人类语言的分布甚至出现奖励黑客——输出一串让 RM 高兴但实际不可读的内容。为了防止这个PPO 会在 reward 里减去一个 KL 散度惩罚项kl_coef就是控制这个惩罚强度的旋钮。kl_coef设太大模型几乎不偏离 SFT 分布PPO 白跑设太小奖励黑客风险直线上升。从 0.1 起步是比较稳妥的观察几轮训练后生成的文本再调。PPO 阶段平台模板一般会要求你在任务里同时指定 policy 模型、RM、参考数据三样东西记牢这个结构别漏。如果你发现 PPO 训练中 reward 一路飙升但文本质量肉眼可见地变差第一件事就是加大kl_coef而不是等它自己收敛。3.4 三阶段任务串联的经验在平台模板里比较省心的做法是把 SFT、RM、PPO 做成三个独立的训练任务通过产出目录进行上下游引用SFT 输出目录 → RM 的 base modelSFT 输出 RM 输出 → PPO 的模型输入。这样任何一个阶段失败都可以单独重跑不会污染整条链。我之前在裸脚本里图省事把三步写进一个 shell 脚本结果 RM 训练后忘了保存 adapterPPO 加载时直接报模型不匹配全部重来。模板化的任务编排恰好解决了这种人肉传参容易断的问题。4. 模型瘦身蒸馏、剪枝、量化的衔接顺序别看到瘦身就想着直接量化。我自己的经验是先把蒸馏和剪枝做完最后压缩位宽效果最稳。顺序的逻辑是蒸馏改变的是模型内部的知识分布剪枝干的活是去掉冗余参数量化是把参数的数值精度降低。如果你先量化再剪枝剪枝过程中会对数值分布敏感精度损失会被放大如果你先剪枝再蒸馏学生模型学的老师本身就带伤效果打折。4.1 蒸馏把大模型的知识灌进小模型蒸馏最朴素的做法是用大模型teacher生成一批高质量回答小模型student用这些回答做 SFT。LLaMA-Factory 的蒸馏入口一般有两种一种是在训练任务里配置 teacher 模型路径让训练过程直接对齐 teacher 的 logits另一种更简单——先让 teacher 批量跑你的指令集把输出存成标准数据集再让 student 用普通 SFT 训练这批数据。我常用后面这种 response distillation操作成本低也容易排查问题。大致流程是准备一份高质量指令集覆盖你想要的核心场景用微调好的大模型批量生成答案temperature 调到 0.7 左右保证多样性人工或规则过滤掉空答、跑题、乱码的样本把过滤后的数据转成 alpaca 格式交给小模型做 SFT。注意蒸馏时 teacher 不一定非要是百亿级的大模型。如果你的业务场景有限7B teacher 蒸馏 3B student 也能拿到不错的收益。关键是数据质量跑偏的 teacher 只会把错误蒸馏得更彻底。4.2 剪枝先看稀疏度对困惑度的影响剪枝这步很多团队直接跳过因为收益不如量化明显但如果你要部署的设备存储或内存卡得很死剪枝就很有用。我的操作流程是先用 Wanda 这类无需训练的重构剪枝方法在给定的稀疏度下剪掉一层马上看模型的困惑度perplexity上涨多少如果 PPL 涨得离谱就降低稀疏度。python prune_llm.py \ --model /outputs/ppo_model \ --sparsity_ratio 0.2 \ --sparsity_type unstructured \ --prune_method wanda \ --eval_ppl0.2意味着剪掉 20% 的权重是一个相对温和的起点。结构化剪枝比如按整行整列去剪对硬件更友好但精度损失通常比非结构化更大需要在业务容忍范围内多试几档。剪完之后跑一遍基本的生成测试别只盯着 PPL 看PPL 下降不代表真实问答更好。4.3 量化AWQ 和 GGUF 怎么选量化这一步和你的部署环境强相关。如果你用 vLLM 做在线推理可以走 AWQ 4bit 量化吞吐高显存占用小如果你要在 CPU 或者边缘设备跑GGUF 搭配 llama.cpp / Ollama 更现实。以 AWQ 为例LLaMA 系列模型可以这样量化python -m awq.entry \ --model_path /outputs/ppo_model \ --tasks quantize \ --calib_data pileval \ --group_size 128 \ --bits 4 \ --output_dir /outputs/ppo_model_awq这里calib_data是校准集作用是统计权重和激活值的分布从而决定量化参数。校准集选择有个很容易犯的错拿评测集去做校准或者让校准集和评测集有重叠量化后的分数会虚高看着漂亮一上真实业务就露馅。我一般会从真实业务样本里抽取一小批单独留作校准不求多几百条就够。在平台模板里模型瘦身这一步也可以做成串联任务蒸馏任务产出小模型 → 剪枝任务产出稀疏模型 → 量化任务产出量化模型。每一步都做一次快速评测记录 PPL 和关键业务指标的变化方便定位是哪一步掉的精度。5. 验收环节OpenCompass 评测与安全评估5.1 OpenCompass 基础评测微调和瘦身做完最怕的事情是自我感觉良好上线就翻车。我习惯用 OpenCompass 跑一遍标准评测至少覆盖 MMLU、C-Eval 这类通用基准再加自己的业务评测集。OpenCompass 的使用方式比较直接核心是配置模型和数据集。python run.py \ --models hf /outputs/ppo_model \ --datasets mmlu_gen ceval_gen \ --output /outputs/eval_result \ --reuse跑完会生成每个任务的分数字典我一般拿三组数对比原始底座模型、微调后的模型、量化后的模型。重点看两个东西微调有没有把通用能力打掉量化让通用能力跌了多少。如果你的模型是专用助手MMLU 掉几分可能无所谓但如果是通用场景掉 5 分以上就得回头检查训练数据和量化校准了。OpenCompass 还可以做主观评测比如alignbench或者你自建的主观问答集。我的习惯是每次把微调前后的模型输出并排抽 50 条在真实业务 prompt 下人工盲评赢、平、输三档统计胜率。这个虽然累但比任何指标都更能反映真实体验。5.2 安全评估不能只靠通用榜单安全评估在标题里占了半壁江山但很多项目实际是上线后才开始补的。我的做法是分成三层跑。第一层用现成的安全评测集比如内容安全、有害指令识别类的题库批量跑一遍模型计算有害内容拒答率。第二层自己构造对抗样本包括恶意指令、隐私窃取、诱导输出违规内容等场景逐条看模型的反应。第三层做多轮越狱测试——单轮测试拦住不代表多轮引导拦得住比如通过上下文包装、角色扮演等方式尝试绕过限制。这里有个平衡点要说明白安全评估不是在越严格越好和越宽松越好之间选边而是看业务定位。完全拒绝所有敏感请求模型会变成复读机误伤大量正常问题完全不设防出问题的是你自己。我的做法是设一个红线测试集和一个误伤测试集同时统计拒答率和正常回答率取一个可接受的工作点。平台模板如果带了安全评估能力的入口喂同样的测试集跑完看报表就行如果没带自己用脚本批量调用模型接口统计也很快。另外OpenCompass 出来的通用榜单分数和安全评估没有必然关系。通用榜单高不代表内容安全过关两件事必须分开测、分开盯。我见过不止一次模型量化后通用能力几乎不掉但安全拒答能力明显退化原因就是量化校准集里没有覆盖安全相关的敏感分布。所以量化之后安全测试集必须重新跑一遍。6. 我踩过的坑和补救办法版本对齐问题。LLaMA-Factory 升级速度不算慢transformers、peft、trl 三个库又各有自己节奏。跑 RM 和 PPO 时经常出现训练能启动但某个 callback 调用了不存在的 API 的问题。解决办法很土在平台上把运行环境锁定在一个已知可用版本组合不要每次都改成最新版。我自己固定过的一个组合是 transformers 4.43.x peft 0.12.x trl 0.9.x跑完整个链路没出幺蛾子。显存不足问题。PPO 阶段同时加载 policy、reference、RM显存压力比 SFT 大不少。第一次跑 7B 模型 PPO我在 24G 卡上开 batch size 1 也 OOM 了后来把gradient_checkpointing打开并且顺手把--output_dir里的历史 checkpoint 清理了一下才算稳定跑完。如果你在平台模板里看到显存相关参数不用犹豫先开 checkpointing。重复微调 instruct 模型问题。有一版我用了 Qwen 的 Instruct 底座做 SFT训练 loss 倒是正常收敛但生成结果总带着一股既想讨好用户又想遵循原本风格的别扭感。换成 Base 底座重跑之后风格干净多了。如果你的目标任务已经有一个明确的对齐需求从 Base 开始会少很多麻烦。校准集污染评测集问题。之前量化后模型在评测集上分数意外地高后来一查量化校准集里混了一部分和评测集同源的数据。重做校准后分数回落到合理区间真实业务表现反而比虚高的时候更稳。从那以后我的校准集单独放在一个固定目录而且评测集和校准集永远不共用。数据集里的隐性 bias 问题。RM 训练时我一度发现模型对长回答的偏好特别明显排查发现 chosed 样本普遍更长模型根本是在学写长文高分。后来用长度匹配策略重新筛选 pair把两边长度分布对齐RM 的排序准确率才真正反映了内容质量问题。最后留一个习惯性动作我现在每次拿到一个新模型或新任务都会先跑一个最小规模的完整链路小数据量 SFT → 小 batch PPO → 快速量化 → 10 条业务用例人工检查。这一步不花多少时间但能暴露 80% 的环境和流程问题。平台模板解决的是流程编排的问题至于效果能不能达标还得靠你对数据、指标和评估集的较真。把这套链路跑顺之后再面对更大规模的模型剩下的就只是资源和耐心的问题了。