Agent 在调用工具(Function-Calling)时,可能会遇到以下问题:
❌ 选择错误的工具
❌ 参数拼接错误
❌ 多轮对话中遗漏关键信息
❌ 明明需要工具却回答“我不知道”
❌ 工具调用格式不符合 API Schema
本文教你,使用 llama factory 通过 强化学习(RL)中的 DPO算法 进行微调,提升 Agent 工具调用(Function-Calling)能力,解决上述问题。
一、LLaMA-Factory 微调
数据内容可以使用Agent生成,也可以使用其他方法进行生成或者人工标注,这里不做介绍。LLaMA-Factory对微调数据格式有严格的要求,具体看如下内容:
数据准备的核心要点
要点 1:文件格式必须是 JSONL
LLaMA-Factory 的所有数据加载(SFT、DPO、RM)底层都使用 datasets.load_dataset("json") 逐行解析。
严格要求 :
- ✅ 每行是一个合法的 JSON 对象
- ✅ 每行之间无逗号分隔
- ❌ 不能有数组包裹符号 [ ]
- ❌ 文件末尾不能有空行
要点 2:每条数据结构必须一致
所有 JSON 对象必须具有 相同的键集合 ,无论字段是否为空。
示例 :
{"system": "...", "tools": "...", "messages": [...], "chosen": "...", "rejected": "..."}
注意 :即使某条数据的 tools 为空,也要保留该字段并写为 "tools": "" ,不能省略。
要点 3:避免使用转义换行符 \n
LLaMA-Factory UI 在前端直接展示字符串内容。如果使用 \n ,会按字面意义显示而非换行。
最佳实践 :
- ✅ 在生成数据时写入真实换行符(实际回车)
- ❌ 避免使用转义序列 \n
要点 4:避免非法 JSON 字符
常见错误 :
- 结尾多余逗号
- 非 UTF-8 编码
- 字符串中未转义的双引号 "
- 中文全角符号(如 ,:; )混入英文环境导致转义失败
数据集注册的关键点
要点 1:dataset_info.json 必须是标准 JSON
错误示例 (缺少外层大括号):
"my\_dataset": {...}
"another": {...}
正确示例 :
{
"my\_dataset": {...},
"another": {...}
}
要点 2:字段映射 columns 必须对齐实际数据
dataset_info.json 中的 columns 字段必须与实际数据的键名完全一致,否则会导致加载错误或预览为空。
示例 : 如果数据包含 tools 、 chosen 、 rejected 字段,则需配置:
"columns": {
"system": "system",
"tools": "tools",
"messages": "messages",
"chosen": "chosen",
"rejected": "rejected"
}
要点 3:DPO 数据集必须添加 "ranking": true
通过该标志告知 LLaMA-Factory 这是偏好学习格式,包含 chosen 和 rejected 字段。
配置示例 :
"RL\_data\_dpo": {
"file\_name": "RL\_data\_dpo.jsonl",
"ranking": true,
"formatting": "sharegpt",
"columns": {...}
}
要点 4:注册目录与启动命令保持一致
启动 WebUI 或 CLI 时, --dataset_dir 必须指向包含 dataset_info.json 的目录。
启动命令示例 :
llamafactory-cli webui --dataset\_dir ./datasets/RL\_data\_dpo
推荐目录结构 :
datasets/
└── RL\_data\_dpo/
├── dataset\_info.json
└── RL\_data\_dpo.jsonl
数据二次转换
为确保数据格式符合 LLaMA-Factory 格式要求,使用以下转换脚本 convert_to_jsonl.py :
执行命令 :
python convert\_to\_jsonl.py --input RL\_data\_dpo.jsonl --output RL\_data\_dpo\_fixed.jsonl
对应的 dataset_info.json 配置 :
{
"RL\_data\_dpo": {
"file\_name": "RL\_data\_dpo\_fixed.jsonl",
"ranking": true,
"formatting": "sharegpt",
"columns": {
"system": "system",
"tools": "tools",
"messages": "messages",
"chosen": "chosen",
"rejected": "rejected"
}
}
}
注意 :需要在 LLaMA-Factory 微调界面验证数据集是否能正常加载和预览。
微调配置与使用
模型下载
使用 ModelScope 下载基座模型:
modelscope download --model Qwen/Qwen3-4B-Instruct-2507 --local\_dir /home/ubuntu/Qwen3-4B
启动 DPO 微调
完整的训练命令如下:
llamafactory-cli train \
--stage dpo \
--do\_train True \
--model\_name\_or\_path /home/ubuntu/Qwen3-4B \
--preprocessing\_num\_workers 16 \
--finetuning\_type lora \
--template qwen3\_nothink \
--flash\_attn auto \
--dataset\_dir data \
--dataset RL\_data\_dpo \
--cutoff\_len 4096 \
--learning\_rate 1e-05 \
--num\_train\_epochs 2.0 \
--max\_samples 100000 \
--per\_device\_train\_batch\_size 4 \
--gradient\_accumulation\_steps 8 \
--lr\_scheduler\_type cosine \
--max\_grad\_norm 1.0 \
--logging\_steps 5 \
--save\_steps 100 \
--warmup\_steps 0 \
--packing False \
--enable\_thinking True \
--report\_to none \
--output\_dir saves/Qwen3-4B-Instruct-2507/lora/train\_2025-11-12-20-09-23 \
--bf16 True \
--plot\_loss True \
--trust\_remote\_code True \
--ddp\_timeout 180000000 \
--include\_num\_input\_tokens\_seen True \
--optim adamw\_torch \
--lora\_rank 8 \
--lora\_alpha 16 \
--lora\_dropout 0 \
--lora\_target all \
--pref\_beta 0.1 \
--pref\_ftx 0 \
--pref\_loss sigmoid
参数说明
总体目标 :
使用 LoRA 低秩微调方式,基于 DPO 偏好数据集对 Qwen3-4B 进行偏好优化
(Direct Preference Optimization,强化学习阶段的无奖励模型替代方案)
核心参数详解 :
| 参数 | |
| 说明 | |
| --stage dpo | |
| 指定训练阶段为 | |
| DPO (Direct Preference Optimization) | |
| ,一种无需奖励模型的强化学习对齐方法,通过偏好对比直接优化模型。 | |
| --do_train True | |
| 启动训练模式(而非推理或验证)。 | |
| --model_name_or_path /home/ubuntu/Qwen3-4B | |
| 预训练基座模型的本地路径。 | |
| --preprocessing_num_workers 16 | |
| 数据预处理的并行线程数,加速数据加载。 | |
| --finetuning_type lora | |
| 采用 | |
| LoRA(低秩适配) | |
| 微调,仅训练部分参数,大幅降低显存消耗。 | |
| --template qwen3_nothink | |
| 使用 Qwen3 系列的无思维链模板格式。 | |
| --flash_attn auto | |
| 自动启用 FlashAttention,节省显存并提升速度。 | |
| --dataset_dir data | |
| 数据集所在目录。 | |
| --dataset RL_data_dpo | |
| 指定使用的数据集名称,包含 chosen(正样本)和 rejected(负样本)。 | |
| --cutoff_len 4096 | |
| 最大序列长度,超出部分截断。 | |
| --learning_rate 1e-05 | |
| 学习率(DPO 阶段通常较低,防止过拟合)。 | |
| --num_train_epochs 2.0 | |
| 训练轮数(完整遍历数据集 2 次)。 | |
| --max_samples 100000 | |
| 最大样本数量限制。 | |
| --per_device_train_batch_size 4 | |
| 每张 GPU 的 batch size。 | |
| --gradient_accumulation_steps 8 | |
| 梯度累积步数,实际 batch size = 4×8 = 32。 | |
| --lr_scheduler_type cosine | |
| 学习率调度策略(余弦衰减)。 | |
| --max_grad_norm 1.0 | |
| 梯度裁剪上限,防止梯度爆炸。 | |
| --logging_steps 5 | |
| 每 5 步打印一次训练日志。 | |
| --save_steps 100 | |
| 每 100 步保存一次模型检查点。 | |
| --warmup_steps 0 | |
| 学习率预热步数(0 表示无预热)。 | |
| --packing False | |
| 禁用样本打包(每条样本独立处理)。 | |
| --enable_thinking True | |
| 启用思维过程记录功能(兼容 Qwen3 思维链模式)。 | |
| --report_to none | |
| 不上报日志到 wandb / tensorboard。 | |
| --output_dir saves/... | |
| 模型输出目录。 | |
| --bf16 True | |
| 使用 bfloat16 混合精度训练。 | |
| --plot_loss True | |
| 训练过程中绘制损失曲线。 | |
| --trust_remote_code True | |
| 允许加载模型自定义代码。 | |
| --ddp_timeout 180000000 | |
| 分布式训练超时设置。 | |
| --include_num_input_tokens_seen True | |
| 在日志中统计累计输入 token 数。 | |
| --optim adamw_torch | |
| 优化器(AdamW PyTorch 实现)。 | |
| --lora_rank 8 | |
| LoRA 秩(低秩矩阵维度)。 | |
| --lora_alpha 16 | |
| LoRA 缩放因子,影响权重更新幅度。 | |
| --lora_dropout 0 | |
| LoRA dropout(0 表示不使用)。 | |
| --lora_target all | |
| 对所有可训练层应用 LoRA。 | |
DPO 特有参数详解 :
| 参数 | |
| 说明 | |
| --pref_beta 0.1 | |
| β | |
| 是 DPO 损失函数中的温度/强度系数,控制"奖励差距"对梯度的影响。β 越小,优化越温和。常见范围:0.1~0.5。 | |
| --pref_ftx 0 | |
| 是否混合监督损失(FTX)。 | |
| 0 | |
| 表示纯 DPO 损失; | |
| 1 | |
| 表示在 DPO 中加入部分 SFT loss(混合训练)。 | |
| --pref_loss sigmoid | |
| DPO 损失函数形式。 | |
| sigmoid | |
| 使用 logistic sigmoid 计算偏好概率(原论文形式);也可设为 | |
| hinge | |
| 。 | |
训练结果分析
损失曲线解读
坐标轴说明 :
- 横轴(X) :训练步数(step)
- 纵轴(Y) :损失值(loss)
曲线说明 :
- 浅蓝线(original) :原始训练 loss(每步)
- 深蓝线(smoothed) :平滑后的 loss 曲线(移动平均)
曲线特征 :
- 初始 loss ≈ 0.68(接近 log(2),DPO 随机输出的典型水平)
- 前 40 步迅速下降至 0.1 以下
- 80 步后趋于平稳
- 100 步后基本收敛在 0.05 左右波动
训练质量评估
- 收敛性优秀
Loss 从 ~0.7 平稳降至接近 0,无震荡或爆炸,说明:
- ✅ 学习率设置合理( 1e-5 适中稳定)
- ✅ 数据质量良好
- ✅ 梯度累积/batch 配置平衡
- ✅ 无梯度爆炸或欠拟合问题
结论 :模型成功学习了偏好方向,DPO 损失优化顺利。
- 收敛速度适中
前 40 步下降最快,属于正常现象:
- DPO 损失在早期快速下降,表明模型快速区分 preferred 与 rejected
- 后期趋稳表明已掌握偏好趋势,继续训练收益递减
结论 :模型进入稳定对齐阶段。
- 后期低波动,训练稳定
曲线后半段震荡极小(0.05 左右浮动),表示:
- ✅ 训练进入收敛区
- ✅ 无过拟合迹象(过拟合时 loss 会反复上升或剧烈波动)
结论 :稳定良性收敛。
DPO 训练阶段 Loss 参考值
| 训练阶段 | ||
| 典型 Loss 区间 | ||
| 含义 | ||
| 初始阶段 | ||
| 0.65~0.7 | ||
| 模型随机偏好(未区分) | ||
| 中期(20–50 步) | ||
| 0.2~0.1 | ||
| 模型逐渐学会区分 preferred / rejected | ||
| 收敛期(100 步后) | ||
| 0.05~0.1 以下 | ||
| 模型稳定对齐,可停止训练 | ||
| 震荡或上升 | ||
0.2 回弹 | 学习率过高或过拟合问题 |
参数配置合理性分析
结合本次训练配置:
- learning_rate=1e-5 → 温和,不易震荡
- pref_beta=0.1 → β 较小,梯度平滑,损失曲线下降平稳
- pref_loss=sigmoid → 损失函数平滑,数值变化连续
- num_train_epochs=2 → 对偏好任务通常足够
结论 :从配置到结果,整体设计科学合理。
