尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AReaL 多轮数学 Agent 训练实战:基于 ArealOpenAI 与 concat 模式的 GSM8K 多轮 GRPO 全流程解析

AReaL 多轮数学 Agent 训练实战:基于 ArealOpenAI 与 concat 模式的 GSM8K 多轮 GRPO 全流程解析 AReaL 多轮数学 Agent 训练实战基于 ArealOpenAI 与 concat 模式的 GSM8K 多轮 GRPO 全流程解析【免费下载链接】AReaLThe RL Bridge for LLM-based Agent Applications. Made Simple Flexible.项目地址: https://gitcode.com/GitHub_Trending/are/AReaL导读本文以 AReaL 开源仓库中的 examples/multi_turn_math 示例为核心完整讲解如何从Qwen/Qwen2.5-1.5B-Instruct出发训练一个具备多轮纠错能力的 GSM8K 数学解题 Agent。你将掌握 AReaL 中ArealOpenAI客户端、concat训练数据组织模式、回合间奖励折扣reward discount与对话树导出等核心机制并能够把单轮 GRPO 配置改造成多轮 Agent 训练配置直接复现与二次开发。示例概览用不到两行配置实现多轮训练在 AReaL 中单轮 GSM8K 数学 RL 训练的标准配置位于 examples/math/gsm8k_grpo.yaml。多轮版本 examples/multi_turn_math/gsm8k_grpo_mt.yaml与单轮配置相比只额外增加了两段配置export_style: concat agent_run_args: max_turns: 2export_style: concat指定训练数据的导出风格为concat拼接模式。该模式下Agent 多轮对话的所有交互会被组织成一棵对话树conversation tree并以叶子节点作为最终导出样本同时为每个 token 计算正确的loss_mask与turn_ids保证多轮轨迹可以在 GRPO 训练中正确计算损失与优势。agent_run_args.max_turns: 2限定 Agent 最多进行 2 轮交互若第 1 轮答案正确则提前终止否则追加一条纠错提示进入第 2 轮。这两项配置由自定义配置类MultiTurnGRPOConfig承接定义见 examples/multi_turn_math/config.py它在 AReaL 基础配置GRPOConfig之上新增了两个字段dataclass class MultiTurnGRPOConfig(GRPOConfig): agent_run_args: dict field( default_factorydict, metadata{help: Arguments for running the agent.}, ) export_style: str field( defaultconcat, metadata{ help: Export style for the completions. By default export_styleconcat. }, )从源码结构看agent_run_args目前只消费其中的max_turns键在gsm8k_rl_mt.py中通过config.agent_run_args.get(max_turns, 2)读取这种通用 dict 具体消费的设计便于后续扩展更多 Agent 运行参数而不改动配置基类。运行方式与命令行参数示例的运行入口与单轮 GSM8K 示例完全一致复用 AReaL 的表达式配置加载机制python3 examples/multi_turn_math/gsm8k_rl_mt.py \ --config examples/multi_turn_math/gsm8k_grpo_mt.yaml \ scheduler.typeray \ experiment_namegsm8k-grpo-multiturn trial_nametrial0命令行要点--config指定 YAML 配置文件scheduler.typeray通过键值覆盖语法把调度器切换为 Ray对应 areal/infra/launcher/ray.py 的 Ray 启动路径多机场景下这是推荐选择experiment_name、trial_name用于标识实验与尝试会贯穿 rollout、actor、saver、recover、evaluator、stats_logger 等所有组件YAML 中以${experiment_name}、${trial_name}引用。配置文件中的完整 GRPO 训练参数与单轮示例保持同一套体系例如区块关键参数示例值说明clustern_nodes/n_gpus_per_node1/8单机 8 卡rolloutbackendsglang:d4p1t1使用 SGLang 推理后端数据并行 4 × TP 1rolloutmax_concurrent_rollouts256最大并发 rollout 数gconfign_samples4每个 prompt 采样 4 条轨迹gconfigtemperature1.0采样温度actorbackendfsdp:d4p1t1使用 FSDP 训练数据并行 4 × TP 1actorlr/eps_clip1.70e-5/0.4学习率与 PPO 裁剪系数actorkl_ctl0.0关闭 KL 惩罚由 loss_mask 天然截断 prompt 部分actoruse_decoupled_losstrue使用解耦损失decoupled lossrefscheduling_strategycolocation → target: actor参考模型与 actor 同卡共置train_datasetbatch_size256训练 batch 大小注意rollout.dump_to_file: true该选项会把 rollout 结果落盘便于调试多轮轨迹的导出是否正确。训练脚本结构奖励函数、Agent 与 Workflow 三层训练脚本 examples/multi_turn_math/gsm8k_rl_mt.py 清晰地划分为三个层次1. 奖励函数gsm8k_reward_fndef gsm8k_reward_fn(result, answer): try: worker get_math_verify_worker() return worker.verify(str(result), str(answer)) except Exception: return 0.0奖励函数直接复用了 AReaL 的MathVerifyWorker实现在 areal/reward/init.py它内部基于math_verify库完成答案解析与比对提取配置同时使用ExprExtractionConfig(try_extract_without_anchor...)与LatexExtractionConfig既能提取显式锚定如answer 1的答案也能解析无锚定表达式比对精度precision6即 6 位有效数字一致即判对单次 verify 调用有 5 秒线程级超时超时或异常一律返回0.0避免个别难解析样本拖慢整个 rollout。该 worker 被设计为进程级单例get_math_verify_worker缓存全局实例配合AsyncRewardWrapper在子进程池中异步执行。2. 多轮 AgentMultiTurnMathAgentclass MultiTurnMathAgent: def __init__(self, gconfig, reward_fn, max_turns2): self.gconfig gconfig self.max_turns max_turns self.async_reward_fn AsyncRewardWrapper(reward_fn) async def run_agent(self, data, client: ArealOpenAI): messages data[messages].copy() for _ in range(self.max_turns): response: ChatCompletion await client.chat.completions.create( messagesmessages, **self.gconfig.to_openai_args_dict(), ) message response.choices[0].message messages.append(message) reward await self.async_reward_fn( resultmessage.content, answerdata[answer] ) client.set_reward(response.id, reward) if reward 1: break else: messages.append({ role: user, content: Your answer is either wrong or not parsable to the reward function. You may misunderstand the original question. Please carefully read the original question, check the previous errors, and try to answer it again., }) return reward关键机制逐条拆解OpenAI 兼容调用通过client.chat.completions.create发起生成采样参数由gconfig.to_openai_args_dict()转换而来。这里的client是ArealOpenAI一个继承自官方AsyncOpenAI的客户端但其底层请求被路由到 AReaL 自己的推理引擎详见 areal/experimental/openai/client.py。逐轮奖励绑定client.set_reward(response.id, reward)把本轮生成结果与即时奖励绑定。set_reward的实现见client.py会把奖励写入InteractionCache中对应交互对象并同步更新total_reward累计值。提前终止一旦奖励为1答案正确立即跳出循环避免无效的后续轮次。纠错提示答案错误或不可解析时追加一条固定英文提示要求模型仔细重读原题、检查之前的错误并重新作答这正是多轮 RL 训练中让模型学会自我修正self-correction的关键信号来源。3. 自定义 Rollout WorkflowMultiturnRLVRWorkflowclass MultiturnRLVRWorkflow(RolloutWorkflow): def __init__(self, reward_fn, gconfig, tokenizer, export_styleconcat, max_turns2): ... self.chat_template_type concat if export_style concat else hf self.agent MultiTurnMathAgent( gconfiggconfig.new(n_samples1), reward_fnreward_fn, max_turnsmax_turns, ) async def arun_episode(self, engine, data): client ArealOpenAI( engineengine, tokenizerself.tokenizer, chat_template_typeself.chat_template_type, ) reward await self.agent.run_agent(datadata, clientclient) stats_tracker.get(workflow_context.stat_scope()).scalar(rewardreward) client.apply_reward_discount(turn_discount0.9) completions_with_reward client.export_interactions(styleself.export_style) return completions_with_rewardWorkflow 是 AReaL 中一集 rollout的抽象arun_episode定义单个数据样本的完整展开过程注意三个关键点chat_template_type的选择export_style concat时客户端必须以chat_template_typeconcat初始化构造逻辑见client.py中的AsyncCompletionsWithReward此时提示词构造走_concat_prompt_token_ids_with_parent路径——即子轮 prompt 由父轮完整 token 序列 新增消息渲染的 token 增量拼接而成并通过 EOS 计数对齐实现跨轮 token 精确拼接。apply_reward_discount(turn_discount0.9)多轮场景下最后一轮的成败实际上反映了整条轨迹的质量。该方法按创建顺序倒序遍历缓存交互把后续轮次的奖励以reward[i] reward[i1] * turn_discount的几何折扣方式向前传播实现见 areal/experimental/openai/cache.py。示例取0.9即第 1 轮会获得第 2 轮奖励 90% 的信用让中间轮次也能收到远端成败信号。export_interactions(styleconcat)以concat风格导出时InteractionCache会依据输入消息列表严格前缀关系构造对话树采用最长前缀规则确定父节点最终只返回叶子节点交互见cache.py的export_interactions。也就是说一次多轮交互最终产出 12 个训练样本第 1 轮答对的只有一个叶子样本答错后走完 2 轮的则以第 2 轮叶子为样本但样本内通过turn_ids区分两轮输出。concat 模式的底层原理从对话树到训练张量concat模式并非简单地把多轮文本拼在一起而是有一套完整的 token 级处理逻辑其核心实现在 areal/experimental/openai/types.py 的InteractionWithTokenLogpReward.to_tensor_dict()与 areal/experimental/openai/client.py 的_concat_prompt_token_ids_with_parent。父链 token 拼接与对齐_concat_prompt_token_ids_with_parent采用如下方案保证跨 tokenizer 兼容父交互的 token 序列由input_tokens output_tokens_without_stop组成并人为补一个 EOS父轮若因长度截断而缺 EOS则补上的 EOS 会在训练时被loss_mask掩盖不参与损失计算对父消息 父输出 本轮新增消息整体套用 chat template得到all_tokens统计父 token 中 EOS 的数量在all_tokens中找到第 N 个 EOS 的位置作为截断点最终子轮 prompt 父 tokens all_tokens[截断点1:]实现父前缀精确复用、仅增量渲染新消息。从源码注释可以确认该方案的目的不同模型的 chat template 在追加消息时可能增删 token如 think token直接重算全量 prompt 会破坏前缀一致性而 EOS 对齐法保证拼接结果与逐轮独立渲染等价。训练张量的构造to_tensor_dict()负责把交互树展开成 GRPO 训练所需的张量行。对concat模式且有父节点的子交互它会递归取父节点的logprobs / loss_mask / versions / turn_ids再与本轮的输出拼接loss_mask父轮与新增增量部分为 0本轮输出 token 为 1保证损失只算模型真正生成的 tokenturn_ids父轮 turn 为历史值本轮输出 token 的 turn 为max(父turn_ids) 1从而在一条样本内区分不同轮次的输出供轮次相关的统计与 mask 使用logprobs父轮部分直接继承父节点在生成时记录的输出 logprob中间 padding 区域填 0。这些张量随后通过concat_tensor_interactions聚合为批次types.py再交给 areal/trainer/ppo 中的 GRPO 损失计算。两种导出风格对比维度concat多轮 Agent 推荐individual样本组织构造对话树只导出叶子导出全部交互轮次区分turn_ids区分每条独立样本奖励传播依赖apply_reward_discount先回传同样依赖 discount 为每轮赋奖励适用场景多轮对话、工具调用、Agent 轨迹单轮 RLVRexport_style合法值校验在MultiturnRLVRWorkflow.__init__中完成非法值会直接抛出ValueError。此外cache.py对concat导出还有一道保护只有当所有交互的chat_template_type concat时才允许按concat导出否则报错并提示改用individual——原因是某些 tokenizer 的 template 会增删 think 等 token无法可靠构造前缀一致的对话树。奖励的异步化与容错AsyncRewardWrapper多轮场景下奖励计算发生在 rollout 热路径中MultiTurnMathAgent将同步奖励函数包装为AsyncRewardWrapper实现在 areal/api/reward_api.py它提供了三层保障进程池隔离奖励函数通过ProcessPoolExecutor在子进程中执行max_workers默认取(CPU 数 / GPU 数) // 2避免math_verify等解析逻辑阻塞事件循环超时控制单次奖励计算默认 15 秒超时超时后自动重试最多 3 次全部失败返回0.0进程池自愈检测到BrokenProcessPool时自动重建执行器并重试最后一次失败则上抛异常。此外AsyncRewardWrapper的进程池按max_workers键全局共享并通过atexit注册清理钩子避免子进程泄漏。运行与验证reward 曲线与统计示例目录下提供了训练过程的奖励曲线图 reward_curve.png用于直观观察多轮训练的收敛情况。训练过程中arun_episode会通过stats_tracker.get(workflow_context.stat_scope()).scalar(rewardreward)把每条轨迹的最终奖励上报到统计系统最终由 areal/utils/stats_logger.py 负责输出可配置接入 wandb 或本地日志。关于本地复现需注意以下几点前提配置文件默认单机 8 卡 FSDP SGLang 推理实际运行时需按本机 GPU 资源调整cluster.n_gpus_per_node与 rollout/actor 的d4p1t1并行度模型权重通过actor.path: Qwen/Qwen2.5-1.5B-Instruct从 Hugging Face 拉取AReaL 也提供hf_utils.load_hf_tokenizer统一加载 tokenizer见 areal/utils/hf_utils.py若要在其他规模模型上训练只需替换actor.path、ref.path、sglang.model_path、vllm.model与tokenizer_path五处模型引用。从本示例出发扩展方向examples/multi_turn_math是 AReaL Agentic RL 能力的最小完整演示它清晰展示了OpenAI 兼容 Agent 循环 对话树导出 回合折扣奖励这条技术主线。基于同样的机制仓库中还有更复杂的 Agent 化示例可以对照学习examples/search_agent引入搜索工具的 Agent其concat导出同样依赖对话树examples/scaffoldingRLVR 脚手架展示了基于工具的复杂轨迹构造docs/en/tutorial/agentic_rl.mdAReaL 官方 Agentic RL 指南对奖励归一化group 级 vs batch 级与concat模式的适用边界有更系统的说明。小结本文完整覆盖了 AReaL 多轮 GSM8K 数学 Agent 训练的五个层次配置项差异export_style与agent_run_args.max_turns、训练脚本结构奖励函数 / Agent / Workflow 三层、ArealOpenAI 客户端逐轮奖励绑定与交互缓存、concat 模式原理EOS 对齐拼接、对话树叶子导出、turn_ids 训练张量、奖励工程进程池异步化与回合折扣。其中每一步都能在仓库源码中找到精确实现client.py、cache.py、types.py、reward_api.py读者可循着这些路径深入阅读将其改造为适合自己任务的多轮 Agent 训练方案。【免费下载链接】AReaLThe RL Bridge for LLM-based Agent Applications. Made Simple Flexible.项目地址: https://gitcode.com/GitHub_Trending/are/AReaL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表