Skip to main content

AWS SageMaker RLVR — 用 GRPO 训练 Tool Calling Agent 实战笔记

原文:Accelerate agentic tool calling with serverless model customization in Amazon SageMaker AI

这篇文章基于 AWS 官方博客原文深度扩写。我以第一视角重新梳理了用 SageMaker AI Serverless + RLVR + GRPO 把 Qwen2.5-7B-Instruct 训成可靠 Tool Calling Agent 的完整过程,补充了大量原文没展开的细节和工程直觉。


这篇文章说了什么

团队用 AWS SageMaker AI 的 Serverless Model Customization 平台,通过 RLVR(Reinforcement Learning with Verifiable Rewards)+ GRPO,把 Qwen2.5-7B-Instruct 训成了一个能在三种场景下正确决策的 Tool Calling Agent:该调工具时调工具、缺参数时主动澄清、超出能力时礼貌拒绝

基座模型的问题很典型:经常幻觉出不存在的工具名、参数传错格式、该拒绝时不拒绝。用 SFT 修这些问题需要大量标注数据覆盖所有行为,而且泛化能力差。RLVR + GRPO 不需要人工逐条标注——只需要定义好奖励函数,模型自己生成候选、自己试探、自己优化,最终 tool call reward 提升 57%。

更重要的是,这个方案跑在 SageMaker AI 的 serverless 平台上,不需要自己管 GPU、不需要搭 rollout pipeline、不需要搞 checkpoint 和监控,选模型、配数据、写奖励函数、点一下训练按钮就行。从配置到训练完成大约 40 分钟。

核心结论:Tool Calling 天然适合 RLVR——因为"调对工具没有"是可验证的客观事实。关键不是算法,是奖励函数能不能区分"完全对""差不多对""完全错"。


有效的实验就这几招

方法做了什么效果
三层奖励分级工具名和参数全对给 1.0,工具对参数错给 0.5,工具全错给 0.0给 GRPO 提供了连续梯度,0.5 分让模型知道自己在"对的方向"
三种行为混合训练训练数据包含 Execute(60%)、Clarify(25%)、Refuse(15%) 三种场景模型学会了"什么时候调工具"vs"什么时候该问"
未见工具泛化评估评估集用了训练时没见过的工具(search_restaurantsget_stock_pricecalculate_standard_deviation确认模型学到的是"工具调用的通用模式",不是背训练集
GRPO 8 候选生成每个 prompt 生成 8 个不同 response,组内比较做 advantage 归一化不需要 Critic 网络,显存只需原来的一半
Serverless 训练基础设施训练跑在 SageMaker AI 托管平台,GPU 自动调度、rollout 和 training 内存自动协调省掉 GPU 采购、内存编排、checkpoint 管理,专注数据和 reward

一、先搞懂这些概念

1.1 Tool Calling 是什么

Tool Calling 就是让模型在生成文本的过程中,不只是"说",还能"做"——调用外部的 API 来完成用户任务。

比如用户说"帮我查旧金山的天气",模型不是自己编一个天气数据(那是幻觉),而是生成一个结构化的函数调用:

{"name": "get_weather_forecast", "arguments": {"city": "San Francisco"}}

系统拿到这个调用后,真的去调天气 API,把结果返回给模型,模型再组织成自然语言回复用户。

生产环境里,Agent 面对三种情况,难度完全不同:

场景用户输入模型应该做什么难点
Execute"Get weather for San Francisco"get_weather_forecast("San Francisco")参数提取准确
Clarify"Get the weather"反问"请问你想查哪个城市?"判断缺什么参数
Refuse"帮我写个病毒"礼貌拒绝识别越界请求

Tool Calling 的本质难点不是"学会调工具",而是"学会判断什么时候该调、什么时候不该调"。

1.2 RLVR 是什么

RLVR = Reinforcement Learning with Verifiable Rewards。

传统的 RLHF(人类反馈强化学习)需要训练一个 Reward Model 来模拟人类偏好——这个过程复杂、昂贵、不稳定。

RLVR 的思路更直接:如果"做得对不对"是客观上可以验证的,那就直接用规则来判断,不需要训练 Reward Model。

Tool Calling 恰好就是这种场景。模型调了 get_weather_forecast 还是 search_flights?参数传的是 "San Francisco" 还是 ""?——这些都是可以程序化验的。RLVR 的奖励函数不需要猜测模型输出"好不好",只需要比对"对不对"。

1.3 GRPO 在 Tool Calling 中的应用

GRPO 跟 RLVR 结合后,训练流程是这样的:

  1. 取一个 prompt(如 "Get weather for San Francisco")
  2. 模型生成 8 个不同的 response
  3. 奖励函数给每个 response 打分(工具名对+参数对=1.0,工具对+参数错=0.5,全错=0.0)
  4. 计算组内 mean 和 std,算 advantage
  5. 高于 mean 的 response 被强化,低于的被打压

比起纯 RLVR,GRPO 多了一层"跟同组其他人比"的机制——即使奖励函数的绝对分值不准(0.5 和 0.7 的差距有时候没有语义上的意义),组内相对排名仍然能给出有效的梯度方向。


二、任务定义:Tool Calling 的三种行为

2.1 为什么 Tool Calling 不能被 SFT 简单解决

SFT(监督微调)的思路是:给模型几千条"用户说 X → 你该输出 Y"的标准答案,模型照猫画虎学习。

SFT 能教会模型"格式"——比如输出 <TOOLCALL> 标签、JSON 不拼错。但它教不会"判断"——什么时候该调工具、什么时候该反问、什么时候该拒绝。

举个例子,SFT 数据里 60% 是 Execute、25% 是 Clarify、15% 是 Refuse。模型在训练集上学会了这些模式。但上线后,一个从来没见过的 prompt——"What time is it in Thailand?"——模型怎么样?答案是:它倾向于"像谁就学谁"。如果这个 prompt 的语言风格跟 Clarify 样本更像(短、模糊),它就反问"请问哪个时区?";如果跟 Execute 更像,它就调工具。这种泛化非常脆弱。

GRPO 的优势在于:它不学"答案",它学"策略"——什么样的输出能在奖励函数下拿到高分。遇到新 prompt,模型自己生成 8 个候选,有些调工具、有些反问,奖励函数逐个打分,最好的那个被强化。久而久之,模型学会了"判断规则"而不是"背答案"。

2.2 三种行为的训练数据

训练数据用 Kiro(Amazon AI IDE)合成生成,1500 条。提示词长这样:

生成 1500 条 RLVR Tool Calling 训练数据,覆盖 5 个工具 schema:
get_weather_forecast, search_flights, translate_text, currency_convert, get_statistics

每条格式:
{"prompt": [...], "reward_model": {"ground_truth": "..."}}

分布:
1. Execute (60%): 用户提供了所有参数 → ground_truth 是工具调用 JSON
2. Clarify (25%): 用户缺参数 → ground_truth 是反问
3. Refuse (15%): 越界请求 → ground_truth 是礼貌拒绝

合成数据的质量主要由两个因素决定:

  • 工具 schema 的准确度:如果 schema 里写了参数是 city: string,模型才知道该用 string 传城市名
  • 场景多样性:不只是"SF 天气"这种,还要有"3 月 15 日东京飞纽约"这种多参数复杂指令

用生产日志的团队效果会更好——真实用户不会像合成数据一样"规整",边缘情况更多。


三、奖励函数设计:三层分级的关键

3.1 为什么不能只给 0/1

直觉上,Tool Calling 的奖励函数很简单:调对工具给 1,调错给 0。

但实际上,这会导致一个严重问题——梯度稀疏

GRPO 训练初期,模型可能 8 个 response 全错(都调了不对的工具),8 个全是 0 分→ mean=0, std=0 → advantage=NaN → 这一步白训了。

如果把"工具名对了但参数错了"给 0.5 分,把"全错"给 0 分,就制造出了组内方差——0.5 分的 response 至少能拿到正 advantage,模型知道往这个方向挪。

3.2 核心评分逻辑

# 从模型输出和 ground_truth 中提取工具调用列表后:

pred_names = {tool.get('name', '') for tool in pred_tools}
gt_names = {tool.get('name', '') for tool in gt_tools}

if pred_names == gt_names:
# 工具名全对 — 再检查参数
perfect_match = True
for pred_tool in pred_tools:
for gt_tool in gt_tools:
if pred_tool.get('name') == gt_tool.get('name'):
if pred_tool.get('arguments') != gt_tool.get('arguments'):
perfect_match = False
score = 1.0 if perfect_match else 0.5

elif pred_names & gt_names:
# 有交集但不完全一致(调对了至少一个但多调了/少调了)
score = 0.5

else:
# 完全不同
score = 0.0

3.3 Clarify 和 Refuse 的评分

这两种情景下,ground_truth 是自然语言文本(不是工具调用 JSON),评分逻辑不同:

  • Clarify:模型应该反问用户,而不是调工具。如果模型调了工具 → 0.0;如果模型用自然语言回应 → 用文本相似度评分
  • Refuse:模型应该礼貌拒绝。如果模型尝试执行 → 0.0;如果模型拒绝 → 1.0

四、训练过程与结果

4.1 训练配置

参数
基座模型Qwen 2.5 7B Instruct
训练框架SageMaker AI Serverless Model Customization
算法RLVR + GRPO
训练数据1,500 synthetic prompts (hled-out)
评估数据300 prompts(含训练中没见过的 3 个工具)
Batch Size128
Learning Rate5e-6
Epochs3
Rollouts per Prompt8
训练时长~40 分钟

4.2 训练曲线解读

四个关键监控指标:

指标初始值最终值含义
Mean Reward~0.28~0.65-0.68奖励提升 2.3 倍
Policy Entropy持续下降模型越来越自信(不是瞎猜)
Gradient Norm波动大稳定收敛更新越来越精细
Mean Advantage Estimate波动→ 0策略趋于稳定,平均响应质量接近奖励基线

最大涨幅在前 10 步——模型在这阶段学会了基本的工具调用格式和决策结构。20 步之后趋于平缓,模型收敛。

4.3 评估结果

300 条 held-out 评估集(含训练时没见过的 3 个工具)上的结果:

指标基座模型微调后提升
Tool Call Reward0.350.55+57%
F1 Score Quasi--+14pp
Rouge1--+15pp
Exact Match11%21%+10pp

几个很有代表性的评估样本:

Prompt: "What's the stock price of AMZN?"
模型输出: [{"name": "get_stock_price", "arguments": {"ticker": "AMZN"}}]
结果: ✅ 完全正确 — get_stock_price 不在训练集里,模型泛化了

Prompt: "Find me a restaurant nearby"
模型输出: "I'd be happy to help you find a restaurant!
Could you please provide the cuisine type or location?"
结果: ✅ 正确判断缺参数,主动反问 — 行为模式泛化成功

Prompt: "What's the standard deviation of 10, 20, 30, 40, 50?"
模型输出: [{"name": "calculate_standard_deviation",
"arguments": {"numbers": "10, 20, 30, 40, 50"}}]
结果: ⚠️ 0.5 分 — 工具选对了,但参数类型错了(传了 string 而不是 array)

五、工程启示

5.1 Serverless 训练平台的价值

自己搭 RL 训练平台要解决什么问题:

  • GPU 采购和调度
  • Rollout(生成)和 Training(更新)阶段的内存协调(vLLM 和 PyTorch 抢显存)
  • 奖励函数执行的基础设施
  • Checkpoint 管理
  • 超参数敏感性的调试

SageMaker AI Serverless 把这些全托管了。你只需要选模型、写奖励函数、配数据。这对小团队的价值巨大——不是每个人都能维护一个 GRPO 训练集群。

5.2 数据量不需要很大

1500 条训练数据、300 条评估数据,就能让 Tool Call Reward 提升 57%。关键不是数据量,是数据的覆盖面——三种行为(Execute/Clarify/Refuse)都要有,否则模型学不会"什么情况下不调工具"。

5.3 评估时一定要用未见过的工具

这是验证泛化的金标准。如果模型只会在训练见过的工具上表现好,那就是背答案。训练集里 5 个工具(weather、flights、translation、currency、statistics),评估集加了 3 个全新工具(restaurants、stock_price、standard_deviation),结果模型迁移得很好——说明它学到的是"怎么判断该调哪个工具"而不是"这个 prompt 该调 weather"。

5.4 三层奖励分级是 GRPO 的标配

0/0.5/1.0 的分级奖励函数,本质上是在解决 GRPO 的"zero-std"问题——当所有候选分数相同时,advantage 全为零,训练白费。0.5 分制造了必要的组内方差,让梯度能流动。


六、跟其他 GRPO Agent 项目的对比

这篇文章跟我的其他 GRPO Agent 笔记有很强的互补性:

维度本文 (SageMaker RLVR)基金助手投标 Agent
业务场景通用 Tool Calling基金业务 API 选择电力设备标的匹配
Agent 类型单 Agent + 多工具SubAgent + 6 API8 Agent 协作
奖励函数三层分级 (0/0.5/1.0)复合维度加权多阶段规则匹配
泛化验证未见过的工具-未见过的规格书格式
基础设施Serverless 托管自建自建
数据量1500 条~1300 条~4 万条

共同点:奖励函数是灵魂,数据质量 > 算法选择,泛化到未见场景才是真本事。