用猜词游戏跑通多轮强化学习训练
教程以 Wordle 为例,在 SageMaker AI 上按完整多步任务的结果训练模型。流程涵盖在 Bedrock AgentCore 部署智能体与奖励逻辑、准备数据、训练及按实际服务配置评估。
AI 深度解读
Agent 连续调用几次工具,最后把任务办成,和回答好一道问答题,是两种训练目标。AWS 这篇实操用 Wordle 展示了多轮强化学习:不给模型标准操作步骤,只让它尝试,再按整局结果打分。
作者把 gpt-oss-20b 在留出词集上的解题率从 61% 提到 84%,训练 token 费用约 339 美元。但更值得程序员看的,是奖励如何写错、验证曲线如何误导,以及认证故障为什么能让整次训练失败。
多轮训练学的是整条操作链
Wordle 要求玩家在六次机会内猜中一个五字母单词。每次猜测都会返回线索:绿色表示字母和位置都对,黄色表示字母存在但位置不对,灰色表示字母不在答案里。后续动作必须利用前面的反馈。
这适合解释多轮强化学习(MTRL):一次完整尝试称为一个 episode,训练采样得到的过程称为 rollout。模型可以走不同路线,环境只需判断最后有没有完成任务。
作者把系统分成两部分。Amazon SageMaker AI 管训练任务和策略模型;Amazon Bedrock AgentCore 托管 Agent、游戏环境和奖励函数。每个 rollout 传入一个秘密单词,Strands Agent 通过 SageMaker Job Runtime 的 OpenAI-compatible endpoint 调用模型,再用 guess_word 提交猜测,结束时返回一个奖励。
GRPO,即组相对策略优化,会比较同一个单词下多次尝试的奖励,用差异更新模型的 LoRA 适配器。大白话理解:同一道题试几种走法,让训练更偏向得分高的路线。
下面这段入口代码把任务、工具和最终评分串在一起:
app = BedrockAgentCoreApp()
@app.entrypoint # 最外层:启动 AgentCore 调用的 HTTP 服务
@sagemaker_rft_handler # 将返回的奖励报告给 SageMaker AI
def handle_rollout(payload):
prompt, answer = parse_task(payload["prompt"])
game = WordleGame(answer)
@tool
def guess_word(guess: str) -> str:
"""Submit a 5-letter Wordle guess and get feedback."""
return game.guess(guess)
agent = Agent(model=build_model(), system_prompt=SYSTEM_PROMPT, tools=[guess_word])
agent(prompt)
return {"reward": game.final_reward()}
要看的是最上面的装饰器顺序。sagemaker_rft_handler 自己不会启动 HTTP 服务,必须由最外层的 @app.entrypoint 包起来,否则调用会在 30 秒后超时。
数据集也没有标准回答。每行只是一个任务字符串,包含 prompt、answer、id;服务原样转发,Agent 自己解析。answer 只给环境和评分函数使用,模型不能看到。作者用了 640 个训练词和 128 个无重叠验证词,随 Agent 打包的 SCOWL 词表只用于评分。
奖励函数先要保证「赢比输好」
这次实验最有借鉴价值的部分,是作者第一次把奖励写反了。
最初的方案把每次猜测的分数累加成整局奖励。结果,失败局能靠六轮过程奖励拿到约 +0.49;第一轮猜中只有 +0.99,第三轮猜中反而有 +1.61。模型如果按这个分数优化,就有理由多走几步。
奖励函数必须先保证结果排序正确,再奖励过程中的好习惯。
修正后的方案由结果分和一个受限的过程分组成。原文用下面的表达式描述它:
reward = outcome + w * clip(shaping, -1, 1), w = 0.04 if solved, else 0.15
要注意 w 的取值:成功局用 0.04,失败局用 0.15。这是公式式写法,不能直接当成一行可运行的 Python 赋值代码。
结果分规定:成功按速度获得 1.05–1.55,失败为 -0.5,从未提交有效猜测为 -1.5。过程分会惩罚违反已知线索、重复猜测和词典外单词,奖励有效开局、尝试新字母、缩小候选集合;累加后先裁剪到 [-1, 1]。
为什么成功局权重更小?相邻成功轮次只差 0.1 分。如果统一用 0.15,第三轮成功仍可能超过第二轮成功。改成 0.04 后,各档不再重叠,最差成功奖励仍有 +1.01,超过服务默认的 success_threshold=1.0。
过程分并非多余。GRPO 依赖组内奖励差异学习,两局都失败,遵守线索的那局仍应优于胡乱猜测的那局。前提是这些细节不能盖过任务结果。
37% 和 84%,为什么都能描述同一个模型
作者选择 GPT-OSS-20B,是因为它在文中提到的四个候选模型中 token 单价最低,而且可以逐请求控制推理力度;输入没有列出其余模型,不能据此补齐支持名单。
训练时,REASONING_EFFORT=low 设置请求的 reasoning_effort,REASONING_PROMPT_HINT=true 再向系统提示加入 Reasoning: low,配合 gpt-oss 的 Harmony 格式。作者评估发现,low 比 medium 每局少用 63%–83% 的 sample tokens。
训练参数有几个容易影响预算的细节:
sampling_max_tokens从默认 4096 提到服务上限 8192,因为模型经常还没第一次调用工具,就在推理中耗尽额度。max_epochs=20、max_steps=100;默认global_batch_size=128,640 行数据每轮对应 5 步。- 默认
group_size=8,每步运行 1,024 局。
100 步累计产生 105,486 个 rollout,用时 12 小时 40 分钟。prefill、sample、train 三类 token 分别为 491.6、159.7、643.3 百万,按当时 us-east-1 标价约 339 美元;AgentCore 的 vCPU 和内存另约 79 美元。DescribeJob 的 BillableTokenUsage 可以查到计费 token。
更长的轨迹会增加训练成本,多轮请求还会反复读取历史。少用推理 token 能省钱,但能否维持任务成功率,需要另外测。
作者在 MLflow 里观察 val/reward/pass_at_1。训练验证的解题率在第 90 步达到 48%,第 100 步却落到 37%。如果只看这条曲线,很容易低估训练效果。
独立评估换成实际服务设置后,medium effort、temperature 1.0 的训练模型达到 84%,基础模型是 61%;84% 是两次结果 80% 和 88% 的平均值。在训练使用的 low effort 下,文章报告解题率从 15% 提到 69%。
模型效果必须和推理力度、temperature 一起报告。
训练验证采用 temperature 0,而独立评估允许调整 temperature,不能直接横比。作者的评估 token 费用约 1.20 美元,总耗时约一小时;每组 128 词评估需要四到七分钟。他们没有测试继续增加训练步数,是否还能改善服务设置下的表现。
我的判断
这套案例最可信的贡献,是展示了可检查的训练闭环:环境给反馈,轨迹可追踪,奖励有明确排序,最后再按服务设置评估。相比只看平均 reward,这更容易发现「模型在刷分」。
但它没有证明一般业务 Agent 都值得上 MTRL。Wordle 的状态、规则和输赢非常清楚,真实工单或报销流程可能需要人工复核,奖励未必及时,也未必客观。原文没有提供这些业务场景的对照结果。
作者也没有给出与监督微调、改提示词、增强工具约束或普通搜索算法的同预算比较。84% 支持的是这次实验中适配器有效,不能推出 MTRL 总比这些办法划算。128 个验证词的规模有限,作者也承认曲线波动较大。
部署经验倒很具体:训练角色要信任 job.sagemaker.amazonaws.com,并允许 sts:AssumeRole 和 sts:TagSession。照搬通用的 sagemaker.amazonaws.com 会失败。运行中的 Agent 也不能重新部署,否则会中断 rollout,导致整个训练任务失败。
能拿来做什么
- 如果正在做能连续调用工具的业务 Agent,先挑一个结果可自动验收的流程,定义完成、失败和无有效动作的边界,再判断是否需要训练。
- 写奖励前,先人工构造快速成功、缓慢成功、部分完成和完全失败的轨迹,检查排序;尤其检查过程奖励能否把失败推到成功之上。
- 对现有模型先做推理设置对照,固定工具和测试集,分别记录成功率、token 和 temperature,避免把采样设置的收益误算成训练收益。
- 复现时先验证调用链:需要 Python 3.10+、Node 20+、uv 和 botocore 1.43.37+;训练任务、S3 和 runtime 必须同 Region。并发认证也要提前检查,作者在 32 个并发 rollout 下遇到凭证问题,最终使用自动刷新的 session、短期 token 缓存和遇到 403 重新签名。