三步跑通 Qwen3-Coder 微调:SFT、DPO 与 LoRA 实战指南
【免费下载链接】Qwen3-CoderQwen3-Coder is the code version of Qwen3, the large language model series developed by Qwen team.项目地址: https://gitcode.com/GitHub_Trending/co/Qwen3-Coder
Qwen3-Coder 微调要解决的是"通用基座不够懂你的业务代码":三步走——先备好数据,SFT 训练流程打底,再做 DPO 偏好对齐,最后用 LoRA 适配器合并收尾。全程只用仓库里现成的脚本,按顺序执行即可。
🧩 一、动手之前:数据与配置一次备齐
这一节把训练前的两件事做完:确认你的数据格式对得上脚本的要求,把超参抄进启动脚本。数据不对,后面所有步骤都是白跑。
ChatML 数据长什么样
SFT 样本要求 ChatML 数据格式,一个 JSONL 文件、一行一个 JSON 对象,messages字段按 system、user、assistant 顺序排好:
{ "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Write a regex to match any letter of the alphabet"}, {"role": "assistant", "content": "The regex is:\n\n```regex\n[a-zA-Z]\n```"} ], "format": "chatml" }DPO 偏好数据则是三字段结构:prompt、chosen(你认可的回答)、rejected(你不认可的回答)。
预处理与质量校验怎么做
仓库自带的 binarize_data.sh 负责把原始 JSONL 转成模型能读的 token 序列:ChatML 角色拼接、按最大长度过滤、格式校验都在这一步完成,代码类样本还会跑一遍执行测试,写不出可运行代码的样本直接丢掉。传三个参数即可:输入路径、输出路径、tokenizer 路径。
关键超参速查表
| 参数 | 默认值 | 说明 |
|---|---|---|
| 学习率 | 5e-5 | 余弦调度,最小值 5e-6 |
| warmup 步数 | 100 | 预热后衰减 |
| 全局 batch size | 1024 | 由微批次×梯度累积拼出 |
| 单卡 batch size | 4 | 显存吃紧就调小 |
| 最大序列长度 | 1280 | 超出部分截断 |
| 训练轮数 | 3 | 按数据量增删 |
| 精度 | BF16 + TF32 | 提速省显存 |
这是 sft_qwencoder.sh 里的起点值,做代码大模型微调时可以按自己的数据量和显存调整。
📈 二、SFT:把代码能力喂给模型
SFT 训练流程的目标:让模型学会按 ChatML 规范生成代码,产出第一版能用的模型。跑通本节,你会拿到可以推理的 checkpoint。
一条命令启动 SFT 训练
下面的命令会用 torchrun 拉起分布式训练,把指定数据喂给基座模型,按 100 步一个 checkpoint 持续写入 output 目录:
DATA_PATH=/path/to/processed/sft.jsonl PRETRAINED_MODEL=/path/to/Qwen2.5-Coder-1.5B OUTPUT_DIR=/path/to/checkpoints/sft bash finetuning/sft/scripts/sft_qwencoder.sh ${DATA_PATH} ${PRETRAINED_MODEL} ${OUTPUT_DIR}跑完你会在 output 目录看到 checkpoint-100、checkpoint-200……,同时 tensorboard 日志开始记录每步细节。
训练日志看哪几个数
- loss:总体往下走说明在学,反复横跳多半是数据或学习率的问题。
- learning_rate:warmup 100 步后,从 5e-5 按余弦缓降到 5e-6。
- tokens/s:衡量吞吐,明显偏低就查 DeepSpeed 配置或数据加载是否拖后腿。
断点续训怎么用
每个 checkpoint 里存了模型参数、优化器状态和训练配置,中断后重跑同一条命令就行:train.py 会自动扫描 output 目录,取编号最大的 checkpoint 接着练,不用手工搬文件。
🎯 三、DPO:让输出更合你的口味
DPO 偏好对齐用偏好数据给 SFT 产物做一次"口味校准",不需要额外的奖励模型。
为什么可以跳过奖励模型
传统 RLHF 要先单独训练一个奖励模型,再拿它驱动策略优化,链路长、还容易不稳。DPO 直接在偏好对上算损失,本质是让模型在同一 prompt 下更偏向 chosen、远离 rejected,省掉了奖励模型和 PPO 那一整套流程。
关键配置与监控指标
启动脚本是 dpo_qwencoder.sh,关键配置:β=0.1,DeepSpeed Zero-3 并把优化器状态、参数都 offload 到 CPU,学习率 3e-4,1 epoch、最多 1000 步,序列长度 1280。
| 指标 | 含义 | 期望趋势 |
|---|---|---|
| rewards/chosen | chosen 回答的相对奖励 | 缓慢上升 |
| rewards/rejected | rejected 回答的相对奖励 | 缓慢下降 |
| rewards/margins | 两者之差 | 保持为正 |
| rewards/accuracies | 偏好判对比例 | 趋近 1.0 |
margins 长期为负或 accuracy 不涨,优先检查偏好数据质量,再把 β 往大调。
🔧 四、LoRA:小显存也能微调
LoRA 训练时只更新低秩矩阵,冻结原始权重;合并就是把增量算回基座,得到一个独立可用的完整模型。
适配器是怎么合并回模型的
三步走:
- 读入适配器目录里的配置(r=8、lora_alpha=32、lora_dropout=0.1),把 base_model_name_or_path 指回基座模型;
- 加载基座与适配器,把每一层的低秩乘积累加到原权重上,
merge_and_unload()一次完成; - 保存合并后的完整模型与分词器。
merge_adapter.sh 是一键合并脚本,会遍历适配器目录下所有 checkpoint-* 逐个合并:
BASE_MODEL=/path/to/Qwen2.5-Coder-1.5B ADAPTERS=/path/to/trained/adapters MERGED=/path/to/merged bash finetuning/sft/scripts/merge_adapter.sh ${BASE_MODEL} ${ADAPTERS} ${MERGED}跑完输出目录会镜像原目录结构,每个 checkpoint 对应一份完整模型;ADAPTERS 直接指向包含多个 checkpoint 的训练输出目录即可。
合并完先做这个验证
加载合并后的模型,跑两条你熟悉的代码任务,再和"基座模型 + 适配器"方式加载时的输出逐字对比。两者一致,说明合并无误;推理直接报错,先核对 peft 与 transformers 的版本是否匹配。
⚠️ 五、踩坑清单
- ChatML 顺序不对:assistant 轮必须紧跟 user 轮之后,乱序会导致 loss 计算错位。DPO 样本保持 prompt/chosen/rejected 三字段格式。
- 序列超过 1280 被截断:长上下文任务建议在数据准备阶段就按任务筛样本,别指望训练脚本兜底。
- β 别开太小:低于 0.1 时模型容易偏离参考模型,输出开始"跑偏";保持 0.1 起步,再按 margins 曲线微调。
- 合并时内存不足:在 merge_adapter.py 里显式指定 device_map 为 cpu,或配置 offload_folder 把卸下的参数落到磁盘。
- checkpoint 越攒越多:脚本默认最多保留 100 份,想省磁盘就在启动脚本里调小 save_total_limit。
SFT 给你一版能用的代码模型,DPO 让输出更贴你的偏好,LoRA 负责低成本地反复换任务实验。下一步:用仓库里的 qwencoder-eval 评测基准跑一轮,用数字确认微调收益。
【免费下载链接】Qwen3-CoderQwen3-Coder is the code version of Qwen3, the large language model series developed by Qwen team.项目地址: https://gitcode.com/GitHub_Trending/co/Qwen3-Coder
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考