Agentic RL 环境和代码学习:以HGPO为例

12 阅读4分钟

1 前言

HGPO(Hierarchy-of-Groups Policy Optimization)通过step-wise GRPO进行Agentic RL,其将处于相同状态的rollout step聚集,对它们进行Group-wise优势计算,实现了更加细粒度的奖励分配,缓解只在rollout结束时获得奖励的稀疏问题。

论文在ALFWorld 和 WebShop 上验证了方法的有效性。因此,这里会学习一下ALFWorld的环境构建,以及如何在verl里实现HGPO。

2 ALFWorld

2.1 ALFWorld 简介

ALFWorld模拟了一个家庭场景(厨房、浴室、卧室、客厅等),Agent 需要通过文本指令与环境交互,完成类似"把洗干净的苹果放进冰箱"这样的任务。Agent 每步接收自然语言描述的当前状态,并从候选动作列表中选择一个执行,直到任务完成或超过最大步数。

ALFWorld包括六类环境,Pick & Place(拾取与放置)、Examine in Light(在光源下检查)、Clean & Place(清洁与放置)、Heat & Place(加热与放置)、Cool & Place(冷却与放置)、Pick Two & Place(拾取两个物体并放置)。

在LLM Agentic RL中,一般使用纯文本模式,每个 step 的输入输出均为字符串。

2.2 ALFWorld 数据集格式

在HGPO项目的Readme里提供了ALFWorld的下载方案,完成后得到以下格式文件。

$ALFWORLD_DATA/json_2.1.1/
├── train/          # 2435 个任务场景(训练集)
├── valid_seen/     # 242 个(验证集,in-distribution,房间布局在训练集中出现过)
├── valid_unseen/   # 85 个(验证集,out-of-distribution,房间布局未见过)
└── valid_train/    # 训练集的子集验证用

$ALFWORLD_DATA/verl_data/
├── train.parquet   # 16 条 verl 格式训练数据(仅用于声明模态,实际任务由环境动态加载)
└── test.parquet    # 128 条 verl 格式测试数据

verl_data/ 中的 parquet 文件只是占位符,prompt 字段为空字符串,真正的任务由 ALFWorld 环境在 reset() 时随机加载。

同一个任务目录下通常有 2–3 个 trial_T... 子目录,代表同一任务、同一房间、不同人类标注员的演示轨迹,区别在于:

  • 物体摆放位置不同(同一类物体放在不同家具上)
  • Agent 初始站位不同
  • 任务描述语言不同(语义相同,措辞各异)

TextWorld 训练时从这些 trial 中随机选一个作为实际游戏场景。

每个 trial 目录包含:

trial_T.../
├── game.tw-pddl        # TextWorld 游戏文件(环境实际加载此文件)
├── initial_state.pddl  # PDDL 格式初始状态
└── traj_data.json      # 任务元数据(任务类型、物体位置、人类标注描述等)

3 HGPO in VeRL

项目路径:github.com/langfengq/v…

这里记录一下如何在VeRL里使用ALFWorld环境。

3.1 交互逻辑

首先看一下multi-turn交互怎么实现的。

交互循环(单 Episode):

reset()
  → 随机加载一个 game.tw-pddl 文件
  → 返回初始场景描述:
    "You are in the middle of a room. Looking quickly around you, you see ..."
    "Your task is to: put a hot apple in countertop."

for step in range(max_steps=50):
    1. build_text_obs()  构造完整 Prompt(含历史 + 任务 + 可用动作列表)
    2. LLM 生成响应:  <think>...推理过程...</think><action>go to fridge 1</action>
    3. alfworld_projection()  解析 <action> 标签内的动作文本
    4. TextWorld.step(action)  执行动作,返回新观测 + reward + done
    5. memory.store(obs, action)  写入历史记录
    if done: break

reward: 0(中间步)或 10.0(任务完成,won=True)

以上逻辑通过VeRL多轮交互Loop实现。

3.2 奖励设计

任务完成奖励:只在完成任务时给予奖励,完成+10分,否则为0分。为了将奖励传递到历史的step中,引入折扣因子0.95,越靠近最后step奖励越高。

无效惩罚:如果智能体生成了在当前环境中无效的动作(invalid action),则施加一个小的负奖励:-0.1。invalid action包括如下几个:

条件说明
输出中无 <action>...</action> 标签格式错误
输出中无 <think>...</think> 标签缺少推理过程
输出中含中文字符(\u4e00-\u9fff语言错误

3.3 环境构造

在Agentic RL任务,最重要的就是环境如何构建,这里的环境包括文本解析与处理、环境交互与反馈、奖励打分等。env包括以下几个部分:

动作解析

首先,模型被要求以先进行推理,再以输出动作。token在多轮交互loop被解码后传入env里。一条典型的 LLM 输出格式:

<think>
I need to heat the apple. I'm currently holding it and standing near the microwave.
The admissible actions include 'heat apple 1 with microwave 1', which is exactly what I need.
</think>
<action>heat apple 1 with microwave 1</action>

这条输出将会被送入env进行解析,解析出和的内容。

环境与奖励反馈

env会判断是否有无效动作,如果是无效动作,奖励会给予惩罚,参考以上的奖励系统部分。env也会判断llm是否完成了任务,如果llm最终完成了任务,环境会判断并给予+10分的分数。

如果是无效动作,observation会返回“"Nothing happens.”。如果是有效的动作,env会根据动作,生成下一步的observation,包括环境状态和可执行的动作。

游戏世界的状态是一组 PDDL 命题集合(纯符号),Fast Downward C++ 引擎负责执行动作(增删命题)枚举新的可行动作,而观测文本则完全由 game.tw-pddl 中内嵌的 CSG Grammar 根据当前命题集合实时拼装生成——本质上是一个符号逻辑系统外套了一层自然语言生成器。

并行环境

框架会为每一个rollout创建一个env,并分配num_cpus=0.1的资源。