HelloAgents 智能体强化学习实战:从 SFT 到 GRPO 构建 Agentic RL 训练流水线
HelloAgents 智能体强化学习实战:从 SFT 到 GRPO 构建 Agentic RL 训练流水线
本篇技术指南以 Datawhale hello-agents 开源教程的第十一章为骨架,系统讲解 Agentic RL(基于强化学习的智能体训练)的理论与实践。你会理解从 LLM 预训练到强化学习的完整演化路径,掌握在 HelloAgents 框架中基于 Qwen3-0.6B 与 TRL,从 GSM8K 数据准备、奖励函数设计、SFT 监督微调、GRPO 群组相对策略优化,到模型评估、超参数调优、分布式训练与生产部署的端到端实战方案。读完后,你可以独立训练出一个具备数学推理能力的智能体模型,并把同样的方法论迁移到工具使用、规划、记忆等更多 Agent 能力上。
一、从 LLM 训练到 Agentic RL
1.1 强化学习视角下的智能体
在第二章中,我们已经接触过基于强化学习(Reinforcement Learning,RL)的智能体概念。RL 是一种专注于解决序贯决策问题的学习范式,它通过智能体与环境的直接交互,在"试错"中学习如何最大化长期收益。将这套框架应用到 LLM 智能体上,一个数学求解智能体可以被映射为标准的强化学习组件:
- 智能体:基于 LLM 的推理系统;
- 环境:数学问题与验证系统;
- 状态:当前的问题描述和已有的推理步骤;
- 行动:生成下一步推理或最终答案;
- 奖励:答案是否正确(正确 +1,错误 0)。
例如求解 "Janet's ducks lay 16 eggs per day..." 这道多步应用题时,智能体需要先计算每天剩余鸡蛋数(16−3−4=9),再计算收入(9×2=18),整个过程天然就是一个多步决策问题。
传统的监督学习方法在这里存在三个核心局限:一是数据质量完全决定训练质量,模型只能模仿训练数据、难以超越;二是缺乏探索能力,只能被动学习人类提供的路径;三是难以优化长期目标,无法精确优化多步推理的中间过程。强化学习则通过让智能体自主生成多个候选答案并根据正确性获得奖励,帮助它学习哪些推理路径更优、哪些步骤是关键,甚至发现比人类标注更好的解题方法——这就是 Agentic RL 的核心思想:将 LLM 作为可学习策略,嵌入智能体的感知-决策-执行循环,通过强化学习优化多步任务表现。
1.2 LLM 训练全景:预训练与后训练
一个强大 LLM 的诞生通常经历两个阶段:预训练(Pretraining)和后训练(Post-training),docs/images/11-figures/11-1.png 展示了从"语言模型"到"对话助手"的完整演化路径。
预训练阶段使用数 TB 级别的海量文本,通过因果语言建模(下一个词预测)以自监督方式学习语言规律与世界知识。给定文本序列 ,目标是最小化负对数似然:
预训练模型虽然语言能力强大,但本质上只是一个"预测下一个词"的模型,不知道如何遵循指令、拒绝不当请求或以对话方式交互。后训练阶段通常包含三个步骤:
- 监督微调(SFT):使用(prompt, completion)对教会模型遵循指令和对话格式,损失函数为 ,特点是数据量小、需人工标注、快速见效。
- 奖励建模(RM):使用偏好对比数据(chosen/rejected 对)训练奖励模型 ,学习人类偏好排序。
- 强化学习微调:最经典的是 PPO,训练目标为 ,即最大化奖励同时用 KL 散度约束策略不要偏离参考模型太远。
传统 RLHF 需要大量人工标注,成本高昂;RLAIF 则用强大 AI 模型替代人类标注员来生成偏好数据,实验表明其效果接近甚至超过 RLHF,同时成本大幅降低。
1.3 Agentic RL 的核心理念与六大能力
传统后训练(本章称 PBRFT:Preference-Based Reinforcement Fine-Tuning)关注单轮对话质量:给定问题、生成回答、按质量给分。而 Agentic RL 将 LLM 视为可学习策略嵌入顺序决策循环:在多步行动中与外部世界交互、获得中间反馈、优化长期累积奖励。
以"分析 GitHub 仓库代码质量"为例:Agentic RL 智能体需要先调用 GitHub API 获取仓库信息(+0.1),再读取主要代码文件(+0.1),分析代码质量(+0.2),最后生成高质量报告(+0.6),总奖励是所有步骤的累积(1.0)。
用马尔可夫决策过程(MDP)五元组 可以清晰地对比两种范式(见下表 docs/images/11-figures/11-table-1.png):
| 维度 | PBRFT | Agentic RL |
|---|---|---|
| 状态 | ,时间跨度 | ,,状态随行动演化 |
| 行动 | 仅文本生成 | ,含工具调用等 |
| 转移 | 无状态转移 | 动态变化 |
| 奖励 | 单步奖励 ,任务结束才给 | ,可含稀疏/密集/混合奖励 |
| 目标 |
Agentic RL 旨在赋予 LLM 智能体六大核心能力(docs/images/11-figures/11-2.png):
- 推理(Reasoning):通过试错学习有效推理策略,发现训练数据中没有的推理路径,学会何时深度思考、何时快速回答;
- 工具使用(Tool Use):行动空间扩展为 ,学会何时用、用哪个、如何组合工具;
- 记忆(Memory):学会记忆管理策略——哪些信息值得记住、何时更新、何时删除;
- 规划(Planning):通过试错发现有效行动序列,权衡短期与长期收益;
- 自我改进(Self-Improvement):识别错误、分析失败原因、调整策略,无需人工干预持续改进;
- 感知(Perception):多模态理解,如视觉推理与视觉工具使用。
1.4 HelloAgents 的 Agentic RL 设计
在技术选型上,HelloAgents 集成了 Hugging Face 的 TRL(Transformer Reinforcement Learning) 框架,模型选择 Qwen3-0.6B(0.6B 参数、适合普通 GPU 训练、开源免费)。
Agentic RL 模块采用四层架构(上图 docs/images/11-figures/11-3.png):
- 数据集层:
GSM8KDataset类、create_sft_dataset()与create_rl_dataset()函数,负责数据加载与格式转换; - 奖励函数层:
MathRewardFunction基类、AccuracyReward准确率奖励、LengthPenaltyReward长度惩罚、StepReward步骤奖励,以及便捷创建函数create_*_reward(); - 训练器层:
SFTTrainerWrapper与GRPOTrainerWrapper,负责具体训练逻辑与 LoRA 支持; - 统一接口层:
RLTrainingTool统一训练工具,支持action="train"(训练)、action="load_dataset"(加载数据集)、action="create_reward"(创建奖励函数)、action="evaluate"(评估模型)四种操作。
1.5 快速上手示例
本章理论较多、实战调试繁琐,因此重点在于学会应用。首先安装框架:
# 安装HelloAgents框架(第11章版本)
pip install "hello-agents[rl]==0.2.5"
# 或者从源码安装
cd HelloAgents
pip install -e ".[rl]"
然后运行快速训练(对应仓库中的 code/chapter11/00_quick_test.py):
import sys
import json
from hello_agents.tools import RLTrainingTool
# 创建RL训练工具
rl_tool = RLTrainingTool()
# 1. 快速测试:SFT训练(10个样本,1个epoch)
sft_result_str = rl_tool.run({
"action": "train",
"algorithm": "sft",
"model_name": "Qwen/Qwen3-0.6B",
"output_dir": "./models/quick_test_sft",
"max_samples": 10, # 只用10个样本快速测试
"num_epochs": 1, # 只训练1轮
"batch_size": 2,
"use_lora": True # 使用LoRA加速训练
})
sft_result = json.loads(sft_result_str)
print(f"\n✓ SFT训练完成,模型保存在: {sft_result['output_dir']}")
# 2. GRPO训练(5个样本,1个epoch)
grpo_result_str = rl_tool.run({
"action": "train",
"algorithm": "grpo",
"model_name": "Qwen/Qwen3-0.6B", # 使用基础模型
"output_dir": "./models/quick_test_grpo",
"max_samples": 5,
"num_epochs": 1,
"batch_size": 2, # 必须能被num_generations(8)整除,使用2
"use_lora": True
})
grpo_result = json.loads(grpo_result_str)
print(f"\n✓ GRPO训练完成,模型保存在: {grpo_result['output_dir']}")
# 3. 评估模型
eval_result_str = rl_tool.run({
"action": "evaluate",
"model_path": "./models/quick_test_grpo",
"max_samples": 10,
"use_lora": True
})
eval_result = json.loads(eval_result_str)
print(f"\n✓ 评估完成: 准确率 {eval_result['accuracy']}, 平均奖励 {eval_result['average_reward']}")
这个示例展示了完整流程:SFT 让模型学习推理格式与对话模式,GRPO 通过强化学习优化推理策略,评估在测试集上验证效果。跑完后准确率很低是正常现象,因为模型只见过 0.7% 的训练样本且只运行了一轮。
二、数据集与奖励函数:Agentic RL 的两大基石
数据集定义智能体要学习的任务,奖励函数定义什么是好的行为,两者是强化学习训练的基石。
2.1 GSM8K 数学推理数据集
数学推理是评估 LLM 推理能力的理想任务:答案有明确对错可自动评估(无需人工标注或奖励模型)、需要分解问题逐步推导(典型多步推理)、学到的推理能力可泛化到其他领域。
GSM8K(Grade School Math 8K)是高质量小学数学应用题数据集,含 7,473 个训练样本和 1,319 个测试样本,难度为 2-8 年级,每题需要 2-8 步推理(docs/images/11-figures/11-table-2.png)。典型问题:
问题: Natalia sold clips to 48 of her friends in April, and then she sold half
as many clips in May. How many clips did Natalia sell altogether in April
and May?
答案: Natalia sold 48/2 = <<48/2=24>>24 clips in May.
Natalia sold 48+24 = <<48+24=72>>72 clips altogether in April and May.
#### 72
最终答案: 72
其中 <<48/2=24>> 是中间计算步骤标记,#### 72 标记最终答案。GSM8K 需要转换成三种格式(docs/images/11-figures/11-4.png、docs/images/11-figures/11-table-3.png):
原始格式:question + answer(含解题步骤),适合人类阅读。SFT 格式将问题转为对话格式 prompt、完整解答作为 completion:
{
"prompt": "<|im_start|>user\nNatalia sold clips to 48 of her friends...<|im_end|>\n<|im_start|>assistant\n",
"completion": "Let me solve this step by step.\n\nStep 1: ...\n\nFinal Answer: 72<|im_end|>"
}
关键点是使用模型对话模板(如 Qwen 的 <|im_start|> 标记),让模型学习输出格式与分步推理。RL 格式只提供问题与正确答案,不提供解题过程:
{
"prompt": "<|im_start|>user\nNatalia sold clips to 48 of her friends...<|im_end|>\n<|im_start|>assistant\n",
"ground_truth": "72"
}
这种设计迫使模型自主生成推理过程,而不是记忆答案。
通过 RLTrainingTool 加载数据集(仓库示例见 code/chapter11/01_dataset_loading.py):
from hello_agents.tools import RLTrainingTool
import json
rl_tool = RLTrainingTool()
# 1. 加载SFT格式数据集
sft_result = rl_tool.run({"action": "load_dataset", "format": "sft", "max_samples": 5})
sft_data = json.loads(sft_result)
print(f"数据集大小: {sft_data['dataset_size']}, 格式: {sft_data['format']}, 样本字段: {sft_data['sample_keys']}")
# 2. 加载RL格式数据集
rl_result = rl_tool.run({"action": "load_dataset", "format": "rl", "max_samples": 5})
rl_data = json.loads(rl_result)
print(f"数据集大小: {rl_data['dataset_size']}, 格式: {rl_data['format']}, 样本字段: {rl_data['sample_keys']}")
max_samples 控制加载样本数量,split 参数支持 "train"/"test" 及 "train[:1000]" 切片,max_samples=None 则使用全部数据。
2.2 奖励函数设计
奖励函数 为每个行动分配数值奖励,智能体最大化累积奖励 。对数学推理任务可简化为 。
好的奖励函数应清楚定义成功、能提供梯度信号、方差不过大、易于调整组合;糟糕的奖励函数可能只在任务结束时给奖励、存在奖励欺骗、多目标相互矛盾或方差过大导致不收敛。HelloAgents 提供三种内置奖励函数,可单独或组合使用(docs/images/11-figures/11-5.png)。
(1)准确率奖励(AccuracyReward)
实现时需要处理答案提取(查找 "Final Answer:" 或 "####" 后的数字、正则提取最后一个数字)与比较(数值精度 72.0 vs 72、单位、格式差异)。仓库中的 code/chapter11/02_reward_functions.py 展示了 MathRewardFunction 的 extract_answer 与 compare_answers 测试,支持容差比较(如 tolerance=0.01)。使用示例:
reward_result = rl_tool.run({"action": "create_reward", "reward_type": "accuracy"})
reward_data = json.loads(reward_result)
print(f"奖励类型: {reward_data['reward_type']}, 描述: {reward_data['description']}")
输出:预测 72 / 真实 72 → 奖励 1.0;预测 72.0 / 真实 72 → 1.0;预测 73 / 真实 72 → 0.0。优点是简单直接;缺点是奖励稀疏,无法区分"接近正确"与"完全错误"。
(2)长度惩罚(LengthPenaltyReward)
只有答案正确才应用惩罚(避免模型为减罚生成错误短答案)。例如目标长度 200、实际 500、,则奖励为 :
reward_result = rl_tool.run({
"action": "create_reward",
"reward_type": "length_penalty",
"max_length": 1024, # 最大长度
"penalty_weight": 0.001 # 惩罚权重
})
优点:鼓励简洁、控制推理成本;缺点:可能抑制详细推理,需仔细调整惩罚系数。
(3)步骤奖励(StepReward)
通过查找 "Step 1:"、"Step 2:" 等标记或换行符数量检测推理步骤。包含 3 个清晰步骤的正确答案奖励为 :
reward_result = rl_tool.run({"action": "create_reward", "reward_type": "step", "step_bonus": 0.1})
优点:鼓励可解释推理、答案易验证调试;缺点:可能导致模型生成冗余步骤,步骤检测可能不准确。
组合策略(docs/images/11-figures/11-table-4.png):
- 准确率 + 长度惩罚 :鼓励简洁正确,适合对话/问答系统;
- 准确率 + 步骤奖励 :鼓励详细推理,适合教育/可解释 AI;
- 三者平衡 :全面优化。需仔细调整 、 权重,避免单一目标过度主导。
2.3 自定义数据集与奖励函数
实际应用中通常需要自己的数据与特定奖励函数。两种训练格式的数据要求如下:
- SFT 格式:
prompt(输入提示,含 system 和 user 消息)、completion(期望输出)、text(完整对话文本,可选); - RL 格式:
question(原始问题)、prompt、ground_truth(正确答案)、full_answer(含推理过程的完整答案)。
方式一:使用 format_math_dataset 转换——准备含 question/answer 字段的原始数据,自动转换为训练格式:
from datasets import Dataset
from hello_agents.rl import format_math_dataset
custom_data = [
{"question": "What is 2+2?", "answer": "2+2=4. #### 4"},
{"question": "What is 5*3?", "answer": "5*3=15. #### 15"},
{"question": "What is 10+7?", "answer": "10+7=17. #### 17"}
]
raw_dataset = Dataset.from_list(custom_data)
sft_dataset = format_math_dataset(dataset=raw_dataset, format_type="sft", model_name="Qwen/Qwen3-0.6B")
rl_dataset = format_math_dataset(dataset=raw_dataset, format_type="rl", model_name="Qwen/Qwen3-0.6B")
方式二:直接传入 custom_dataset——在 rl_tool.run() 中通过 custom_dataset 参数传入。
方式三:注册使用(推荐)——rl_tool.register_dataset("my_math_dataset", rl_dataset) 后,训练时用 "dataset": "my_math_dataset" 引用。
自定义奖励函数需遵循签名 def fn(completions: List[str], **kwargs) -> List[float],从 kwargs 中取 ground_truth,返回 0.0-1.0 的奖励列表。可设计"带容差"的奖励(误差 <0.01 得 1.0、<5.0 得 0.5),并配合 register_reward_function("my_dataset", tolerant_reward) 注册后自动关联同名数据集使用(完整示例见文档 11.2.3 节)。
三、SFT 监督微调:让模型学会"格式化思考"
3.1 为什么需要 SFT
预训练模型的目标是预测下一个词,输出自由文本、没有任务相关数据。直接用预训练模型求解 GSM8K 问题的输出冗长、缺乏结构、无明确答案;而 SFT 后的模型会输出 "Step 1: ... / Step 2: ... / Final Answer: 72" 这样的结构化结果。SFT 教会模型:输出格式(Step/Final Answer 标记)、推理模式(分解问题、逐步推导)、基线能力(为 RL 提供合理起点)、减少探索空间(RL 无需从零开始)。预训练与 SFT 输出的对比可见 docs/images/11-figures/11-6.png。
3.2 LoRA:参数高效微调
直接全量微调 Qwen3-0.6B 需要约 12GB(FP16)或 24GB(FP32)显存,更大的模型几乎无法在消费级 GPU 上训练。LoRA(Low-Rank Adaptation)只训练少量额外参数而冻结原模型:假设权重变化 (,,),前向传播为 。
参数量从 降为 。以 为例:原参数 16,777,216,LoRA 仅 65,536,减少 256 倍。LoRA 优势:显存占用大幅降低、训练更快、易于部署、防过拟合;缺点是效果通常略逊于全量微调(对比见 docs/images/11-figures/11-table-5.png)。
关键超参数:秩 rank(表达能力与参数量,典型 4-64,默认 8);Alpha(缩放因子,实际更新为 ,通常等于 rank);target_modules(通常选注意力层 q/k/v/o_proj,也可含 MLP 层 gate/up/down_proj)。
3.3 SFT 训练实战
基础训练示例(仓库 code/chapter11/04_sft_training.py 提供最小配置、标准配置、显存优化等多套模板):
from hello_agents.tools import RLTrainingTool
rl_tool = RLTrainingTool()
result = rl_tool.run({
"action": "train",
"algorithm": "sft",
"model_name": "Qwen/Qwen3-0.6B",
"output_dir": "./models/sft_model",
"max_samples": 100, # 使用100个样本快速测试
"num_epochs": 3,
"batch_size": 4,
"learning_rate": 5e-5,
"use_lora": True,
"lora_rank": 8,
"lora_alpha": 16,
})
print(f"训练完成! 模型路径: {result['model_path']}, 最终损失: {result['final_loss']:.4f}")
训练参数详解:
- 数据参数:
max_samples快速测试用 100-1000,完整训练建议全部 7,473 个样本;split默认 "train",可 "train[:1000]" 切片; - 训练参数:
num_epochs建议从 3 轮开始,太少欠拟合、太多过拟合;batch_size按显存调整(4GB→1-2,8GB→4-8,16GB→8-16);learning_rateSFT 推荐 5e-5,LoRA 可稍大(1e-4); - LoRA 参数:
use_lora建议始终开启;lora_rank4-8 适合小任务、16-32 适合复杂任务;lora_alpha通常设为 rank 的 2 倍; - 优化器参数:
optimizer默认 "adamw";weight_decay默认 0.01(可试 0.001-0.1);warmup_ratio默认 0.1。
完整训练(适合 8GB 显存,预计 30-60 分钟):max_samples=None 使用全部数据、num_epochs=3、batch_size=8、learning_rate=5e-5、warmup_ratio=0.1、weight_decay=0.01、lora_rank=16、lora_alpha=32、lora_target_modules=["q_proj","k_proj","v_proj","o_proj"],并配置 save_steps=500、logging_steps=100、eval_steps=500。
训练监控三指标:Loss 应下降(不降→学习率太小或数据问题;降后升→过拟合);梯度范数应在 0.1-10(>100 梯度爆炸、<0.01 梯度消失);学习率按 warmup 策略变化。常见问题:显存不足→减小 batch_size/max_length、用梯度累积;训练慢→增大 batch_size、混合精度;过拟合→增大 weight_decay、减轮数、加数据。
3.4 模型评估
评估指标包括准确率(答案完全正确的比例,0-1)、平均奖励(综合准确率、长度、步骤等因素)、推理质量(需人工或专门评估模型):
eval_result = rl_tool.run({
"action": "evaluate",
"model_path": "./models/sft_full",
"max_samples": 100,
"use_lora": True,
})
eval_data = json.loads(eval_result)
print(f"准确率: {eval_data['accuracy']}, 平均奖励: {eval_data['average_reward']}, 样本数: {eval_data['num_samples']}")
对 Qwen3-0.6B 这样的小模型,SFT 后在 GSM8K 达到 40-50% 准确率是正常的,通过强化学习可进一步提升到 60-70%。可对比预训练模型(model_path="Qwen/Qwen3-0.6B", use_lora=False)与 SFT 模型的准确率验证训练效果(仓库 code/chapter11/07_model_evaluation.py 提供基线/SFT/GRPO 三方对比模板)。
四、GRPO 训练:让模型学会"思考"而非"模仿"
4.1 从 PPO 到 GRPO
PPO 是经典 RL 算法,通过限制策略更新幅度保证训练稳定,但在 LLM 训练中存在痛点:需要训练 Value Model(增加复杂度与显存)、需同时维护四个模型(Policy/Reference/Value/Reward)、训练不稳定易奖励崩塌。
GRPO(Group Relative Policy Optimization,出自 DeepSeekMath 论文)专为 LLM 设计:不需要 Value Model,使用组内相对奖励代替绝对奖励,只需 Policy Model 和 Reference Model,训练更简单稳定。PPO 的目标函数依赖优势函数 (需 Value Model 估计),而 GRPO 简化为:
关键区别:用 (组内相对奖励)代替优势函数、减少奖励方差、添加 KL 散度惩罚防止策略偏离太远。流程对比与详细对比分别见 docs/images/11-figures/11-7.png 与 docs/images/11-figures/11-table-6.png。
4.2 GRPO 训练实战
GRPO 训练的前提是已完成 SFT(需要一个合理的初始策略),从 "./models/sft_full" 开始:
result = rl_tool.run({
"action": "train",
"algorithm": "grpo",
"model_name": "./models/sft_full", # 从SFT模型开始
"output_dir": "./models/grpo_model",
"max_samples": 100,
"num_epochs": 3,
"batch_size": 4,
"learning_rate": 1e-5, # GRPO学习率通常比SFT小
"num_generations": 4, # 每个问题生成4个答案
"kl_coef": 0.05, # KL散度惩罚系数
"use_lora": True,
"lora_rank": 16,
"lora_alpha": 32,
"reward_type": "accuracy", # 使用准确率奖励
})
print(f"训练完成! 平均奖励: {result['average_reward']:.4f}")
GRPO 特定参数(仓库 code/chapter11/05_grpo_training.py 有完整模板):
- 生成参数:
num_generations每个问题生成答案数(典型 4-8,用于计算组内相对奖励、增加训练信号多样性);max_new_tokens建议 256-512;temperature建议 0.7-1.0 保持探索性; - 优化参数:
learning_rate建议 1e-6 到 1e-5(小模型上 5e-5 可能导致策略坍塌,必要时可调至 1e-6);kl_coef建议 0.05-0.1;clip_range建议 0.2; - 奖励参数:
reward_type可为 "accuracy"/"length_penalty"/"step"/"combined";reward_config配置组合奖励的权重与组件参数。
完整 GRPO 训练:num_generations=4、max_new_tokens=512、temperature=0.8、kl_coef=0.05、clip_range=0.2,组合奖励配置:
"reward_type": "combined",
"reward_config": {
"components": [
{"type": "accuracy", "weight": 1.0},
{"type": "length_penalty", "weight": 0.5, "target_length": 200},
{"type": "step", "weight": 0.3, "step_bonus": 0.1}
]
},
4.3 GRPO 训练过程解析
训练循环五步:①采样——每个问题用当前策略生成 num_generations 个答案构成"组";②奖励计算——对每个答案计算奖励 ;③相对奖励——计算组内均值 ,相对奖励 ,降低方差提升稳定性;④策略更新——用相对奖励更新策略并加 KL 惩罚;⑤重复直至完成所有轮次。
具体例子:为 "What is 48 + 24?" 生成 4 个答案,奖励为 [1.0, 1.0, 0.0, 0.8](第 4 个因冗长被惩罚),组内均值 0.7,相对奖励为 [0.3, 0.3, -0.7, 0.1]——策略更新增加前两个答案概率、减少第三个答案概率。相对奖励机制鼓励模型生成"比平均水平更好"的答案,而非简单地追求高奖励。
KL 散度惩罚:,防止策略偏离参考模型太远、"遗忘"SFT 学到的知识。kl_coef 太小(0.01)策略偏离太远导致格式混乱;太大(0.5)学习缓慢难以超越 SFT;建议 0.05-0.1。
训练监控:平均奖励应逐渐上升(不升→学习率太小/KL 惩罚太大/奖励函数不合理/ SFT 质量差,可增大学习率、减小 kl_coef、检查奖励函数);KL 散度应保持在 0.01-0.1(过大 >0.5 需增大 kl_coef 或降低学习率;过小 <0.001 需反向调整);准确率应逐渐提升;生成质量需人工抽检。
HelloAgents 集成三种监控方式:wandb(推荐,设置 WANDB_PROJECT 环境变量后自动记录 train/reward、train/kl、train/loss 等指标);TensorBoard(训练自动在 output_dir 生成日志,tensorboard --logdir=./models/grpo_tb 后访问 localhost:6006);离线日志(无需外部工具,直接观察 Epoch/Step/Reward/KL/Loss 输出)。
常见问题:奖励不上升→增大学习率或减小 kl_coef;KL 散度爆炸(格式混乱)→降低学习率、增大 kl_coef、用梯度裁剪;生成质量下降(准确率提升但格式乱)→用组合奖励、增大 kl_coef、减少轮数;显存 OOM(GRPO 比 SFT 更吃显存)→减小 num_generations/batch_size/max_new_tokens,或使用梯度检查点与混合精度。
五、模型评估与分析
5.1 评估指标体系
准确性指标:Accuracy(答案完全正确的比例,简单直观但无法区分接近/完全错误);Accuracy@K(生成 K 个答案任一正确即算对,反映模型"潜力");Numerical Error( 均值,区分"接近正确"与"完全错误")。
效率指标:Average Length(平均 token 数,更短意味着更低推理成本);Reasoning Steps(平均步骤数,2-5 步说明能系统分解问题,过多说明冗余);Inference Time(部署中影响用户体验)。
质量指标:Format Correctness(是否符合 "Step 1"/"Final Answer" 等格式);Reasoning Coherence(步骤逻辑连贯性,通常需人工或专门模型评估);Explainability(可解释性)。各指标对比见 docs/images/11-figures/11-table-7.png。
5.2 评估实战
result = rl_tool.run({
"action": "evaluate",
"model_path": "./models/grpo_full",
"max_samples": 200,
"use_lora": True,
"metrics": ["accuracy", "accuracy_at_k", "average_length", "average_steps", "format_correctness"],
"k": 3, # Top-3准确率
})
eval_data = json.loads(result)
可一次性对比预训练模型、SFT 模型、GRPO 模型(metrics 取 "accuracy"/"average_length"/"format_correctness"),用格式化表格打印三者差异。
5.3 错误分析
模型的错误可归为四类:计算错误(推理步骤正确但计算出错,如 "48/2=25");推理错误(解题思路不对,如先加后除);理解错误(没有正确理解问题);格式错误(答案正确但缺 "Final Answer:" 标记)。通过 "return_details": True 获取错误样本,按启发式规则分类统计,示例输出:
总错误数: 76
错误类型分布:
计算错误: 32 (42.1%)
推理错误: 18 (23.7%)
理解错误: 22 (28.9%)
格式错误: 4 (5.3%)
计算错误占比最高说明数值计算能力需加强;格式错误很少说明 SFT 效果良好。还可按真实答案的推理步骤数分组(简单 1-2 步 / 中等 3-4 步 / 困难 5+ 步)统计准确率,示例输出显示模型在简单问题 78.5%、中等 58.3%、困难 31.6%,说明多步推理能力有待提升。
5.4 改进方向
基于评估结果确定改进方向并循环迭代(docs/images/11-figures/11-8.png):训练模型 → 评估性能 → 分析错误 → 确定问题 → 选择改进方向 → 重新训练,多轮迭代后模型性能持续提升。
六、完整训练流程实战
6.1 端到端训练流程
完整流程含六个阶段(docs/images/11-figures/11-9.png):
文档 11.6.1 节给出完整的 AgenticRLPipeline 类实现(仓库 code/chapter11/06_complete_pipeline.py 为更新版):stage1_prepare_data 加载并检查数据集 → stage2_sft_training 用基础模型训练 → stage3_sft_evaluation 评估 SFT 模型 → stage4_grpo_training 以 SFT 模型为起点训练 → stage5_grpo_evaluation 评估 GRPO 模型 → stage6_save_results 保存结果到 training_results.json,run() 方法串起全部阶段并捕获异常。
配套配置文件 code/chapter11/config.json 定义了模型(base_model: Qwen/Qwen3-0.6B)、数据(max_samples: 100)、SFT(num_epochs: 2, batch_size: 4)、GRPO(num_epochs: 2, batch_size: 2)、评估(max_samples: 20, sft_accuracy_threshold: 0.4)与监控(use_wandb: false, use_tensorboard: true)等配置项。
运行小建议:①从小规模开始——先用 100-1000 个样本快速迭代验证流程与参数,确认效果后再扩大规模;②数据质量检查——训练前用文档提供的 check_data_quality 函数检查必需字段(prompt/completion)、空值与重复样本;③数据增强——改写问题、生成相似问题、反向翻译等,但要注意保持数据质量避免引入噪声。
6.2 超参数调优
三种常用方法(对比见 docs/images/11-figures/11-table-8.png):
- 网格搜索(Grid Search):遍历所有参数组合(如
learning_rate × lora_rank × kl_coef)选择最佳组合。优点是简单直接能找到全局最优;缺点是计算成本高,参数多时不可行。 - 随机搜索(Random Search):按分布随机采样参数组合(对数均匀采样学习率 1e-6~1e-4、
random.choice选 rank、均匀采样 kl_coef)。效率更高,适合参数空间大的情况,但可能错过最优解。 - 贝叶斯优化(Bayesian Optimization):使用 Optuna 的概率模型指导搜索,
trial.suggest_loguniform/suggest_categorical/suggest_uniform采样参数、study.optimize(objective, n_trials=20)最大化准确率。样本效率高,但实现复杂、需额外库。
6.3 分布式训练
HelloAgents 基于 TRL 和 Hugging Face Accelerate,天然支持多 GPU 与多节点训练。方案选择建议:**单机多卡(2-8 卡)**用 DDP 简单高效;**大模型(>7B)**用 DeepSpeed ZeRO-2 或 ZeRO-3;多节点集群用 ZeRO-3 + Offload。
配置 Accelerate:运行 accelerate config 交互式配置(选择 multi-GPU、GPU 数量、DeepSpeed 方案等),会生成 ~/.cache/huggingface/accelerate/default_config.yaml。
仓库 code/chapter11/accelerate_configs 目录提供了三套现成配置,README 中有详细参数说明与性能调优建议:
DDP 配置(multi_gpu_ddp.yaml):distributed_type: MULTI_GPU、num_processes: 4、mixed_precision: fp16,训练脚本完全不变,启动命令:
accelerate launch --config_file accelerate_configs/multi_gpu_ddp.yaml train_script.py
# 或直接指定参数
accelerate launch --num_processes 4 --mixed_precision fp16 train_script.py
DeepSpeed ZeRO-2(deepspeed_zero2.yaml):distributed_type: DEEPSPEED、zero_stage: 2,分片优化器状态与梯度,显存节省约 30%,适合 1B-7B 中等规模模型。
DeepSpeed ZeRO-3(deepspeed_zero3.yaml):zero_stage: 3、offload_optimizer_device: cpu、offload_param_device: cpu、zero3_init_flag: true,完整分片模型参数,显存节省约 50%,适合 >7B 大模型。
多节点训练:主节点 machine_rank: 0、num_machines: 4、num_processes: 16(4 节点 × 4 GPU)、指定 main_process_ip 与 main_process_port: 29500;工作节点修改 machine_rank 为 1/2/3,各节点运行 accelerate launch --config_file ... train_script.py。
最佳实践:总 batch size = per_device_batch_size × num_gpus × gradient_accumulation_steps(单 GPU batch=4 累积 4 与 4 GPU batch=4 累积 1 的总 batch 均为 16);学习率线性缩放 lr_new = lr_base × sqrt(total_batch_size_new / total_batch_size_base)(单 GPU batch=16, lr=5e-5 → 4GPU batch=64, lr=1e-4);调试时设置 ACCELERATE_LOG_LEVEL=INFO、NCCL_DEBUG=INFO、watch -n 1 nvidia-smi 检查 GPU 利用率。
6.4 生产部署
模型导出:用 PEFT 将 LoRA 权重合并到基础模型便于部署——PeftModel.from_pretrained(base_model, "./models/grpo_model") 加载后 merge_and_unload() 合并,save_pretrained 保存合并模型与 tokenizer。
推理优化:加载时用 8-bit 量化(load_in_8bit=True)与 device_map="auto" 自动分配设备,model.generate 时设 max_new_tokens=512、temperature=0.7、do_sample=True。
API 服务:使用 FastAPI 创建推理服务,定义 Question(text、max_tokens)与 Answer(text、confidence)请求/响应模型,@app.post("/generate") 接口内部构造 <|im_start|> 对话 prompt 并调用 model.generate,最后 uvicorn api:app --host 0.0.0.0 --port 8000 启动服务。
七、本章小结与学习路径
Agentic RL 的本质:将 LLM 作为可学习策略嵌入智能体的感知-决策-执行循环,通过强化学习优化多步任务表现。与 PBRFT 的核心区别体现在任务性质(单轮对话优化 → 多步序贯决策)、状态空间(静态提示 → 动态演化环境状态)、行动空间(纯文本 → 文本+工具+环境操作)、奖励设计(单步质量评估 → 长期累积回报)、优化目标(短期响应质量 → 长期任务成功)五个维度。
六大核心能力:推理、工具使用、记忆、规划、自我改进、感知。
训练流程:预训练(学习语言知识)→ SFT(学习任务格式与基础推理)→ RL(通过试错优化推理策略)。SFT 是基础,RL 是提升——没有 SFT 的基础 RL 很难成功;没有 RL 的优化模型只能模仿训练数据。
进阶学习路径:基础阶段掌握强化学习基础(MDP、策略梯度、PPO)、LLM 基础与 HelloAgents 实践;进阶阶段深入 TRL 实现细节、自定义数据集与奖励函数、系统调参;高级阶段研究多步推理、工具学习、多智能体协作与前沿论文。
参考文献
- [1] Schulman, J., et al. (2017). Proximal Policy Optimization Algorithms. arXiv:1707.06347.
- [2] Shao, Z., et al. (2024). DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. arXiv:2402.03300.
- [3] Hu, E. J., et al. (2021). LoRA: Low-Rank Adaptation of Large Language Models. arXiv:2106.09685.
- [4] Cobbe, K., et al. (2021). Training Verifiers to Solve Math Word Problems. arXiv:2110.14168.
- [5] Ouyang, L., et al. (2022). Training language models to follow instructions with human feedback. NeurIPS 35.
- [7] Lee, H., et al. (2023). RLAIF: Scaling Reinforcement Learning from Human Feedback with AI Feedback. arXiv:2309.00267.
- [8] Wei, J., et al. (2022). Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. NeurIPS 35.
- [9] von Werra, L., et al. (2020). TRL: Transformer Reinforcement Learning. Hugging Face 开源库。
- [10] Qwen Team. (2025). Qwen3 Technical Report. arXiv:2505.09388.
- [11] Bai, Y., et al. (2022). Training a Helpful and Harmless Assistant with Reinforcement Learning from Human Feedback. arXiv:2204.05862.
- [13] Christiano, P. F., et al. (2017). Deep Reinforcement Learning from Human Preferences. NeurIPS 30.
- [14] Stiennon, N., et al. (2020). Learning to summarize with human feedback. NeurIPS 33.
- [15] Ziegler, D. M., et al. (2019). Fine-Tuning Language Models from Human Preferences. arXiv:1909.08593.

