Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c8d8b1d
Add Env EB-Alfred
YaningDylan Mar 1, 2026
1ef03b9
Update eb_alfred: capacity queuing, thread-safe GPU display, close ti…
Mar 9, 2026
14c67f1
update readme and env logic
Mar 16, 2026
1ff784c
update service logic
Mar 17, 2026
e27fbe4
fix service semaphore event loop bug; set max_inflight=0; simplify RE…
Mar 17, 2026
7ad072d
add start_server.sh and xorg confs; simplify README
Mar 17, 2026
7327cfc
Update eb_alfred serve.py to use GymService class API
Mar 17, 2026
64ff6f9
Auto-detect GPUs and start Xorg in eb_alfred serve.py
Mar 17, 2026
5b458c8
Rewrite eb_alfred README to match navigation style
Mar 18, 2026
068dede
Trim eb_alfred README: remove Prompt Formats, move dataset into setup…
Mar 18, 2026
24d5de4
Remove Checklist section from eb_alfred README
Mar 18, 2026
ef9dd73
update service and scripts
Mar 18, 2026
d5e0c64
update prompt logic
YaningDylan Mar 19, 2026
f3723e4
tmp
Mar 19, 2026
ea2ae53
Align action format to ERA [id, 'action_name'] style
YaningDylan Mar 19, 2026
c5c08f1
update prompt logic
YaningDylan Mar 20, 2026
1ce537e
update script
YaningDylan Mar 20, 2026
b767361
update script
YaningDylan Mar 20, 2026
698a3f4
udpate parse logic
YaningDylan Mar 20, 2026
fcdb7e9
fix
YaningDylan Mar 20, 2026
9639f0b
tmp
Mar 22, 2026
f869c15
tmp
Mar 22, 2026
137a9d6
update reset logic
YaningDylan Mar 24, 2026
192fa72
add preload logic
YaningDylan Mar 25, 2026
39c31b1
support dynamic eval_set per reset for env pooling
YaningDylan Mar 25, 2026
39f8373
fix preload via lifespan, support dynamic eval_set per reset
YaningDylan Mar 25, 2026
545e1d5
delta temp
YaningDylan Mar 27, 2026
793b952
tmp: free SGLang memory before critic/actor update on <=2 GPU configs
Apr 7, 2026
a101871
fix: graceful fallback when env reset fails in no_concat agent loop
Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions examples/evaluate/eb_alfred/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
fileroot: ${oc.env:HOME}/projects/vagen

envs:
- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_val_common
seed: [0, 50, 1]
max_turns: 6
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: common_sense
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0
chat_config:
temperature: 0
max_tokens: 2048
top_p: 1.0

- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_val_spatial
seed: [0, 50, 1]
max_turns: 6
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: spatial
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0
chat_config:
temperature: 0
max_tokens: 2048
top_p: 1.0

experiment:
dump_dir: ${fileroot}/rollouts/eval_eb_alfred
default_max_turns: 6

run:
backend: "openai"
base_seed: 0
max_concurrent_jobs: 4
resume: skip_completed
live_summary: true

backends:
openai:
api_key: "" # or env OPENAI_API_KEY
base_url: null
model: "gpt-4o-mini"
max_concurrency: 2
max_retries: 6
min_backoff: 0.5
max_backoff: 8.0

sglang:
base_url: "http://127.0.0.1:30000/v1"
api_key: "EMPTY"
model: "Qwen/Qwen2.5-VL-7B-Instruct"
max_concurrency: 2
max_retries: 6
min_backoff: 0.5
max_backoff: 8.0

claude:
api_key: ""
base_url: null
model: "claude-3-5-sonnet-latest"
max_concurrency: 2
max_retries: 6
min_backoff: 0.5
max_backoff: 8.0
14 changes: 14 additions & 0 deletions examples/evaluate/eb_alfred/run_eval.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail

# Before running, start the eb_alfred server in another terminal:
# python -m vagen.envs.eb_alfred.serve

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG="${1:-$SCRIPT_DIR/config.yaml}"
shift 2>/dev/null || true

LOG_FILE="run.log"

python -m vagen.evaluate.run_eval --config "$CONFIG" "$@" \
2>&1 | tee "${LOG_FILE}"
66 changes: 66 additions & 0 deletions examples/train/eb_alfred/train_eb_alfred_vision.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
envs:
- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_train_base
seed: [0, 200, 1]
max_turns: 6
response_length_per_turn: 512
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: base
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0

- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_train_complex
seed: [0, 200, 1]
max_turns: 6
response_length_per_turn: 512
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: complex_instruction
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0

- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_train_visual
seed: [0, 200, 1]
max_turns: 6
response_length_per_turn: 512
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: visual_appearance
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0
Comment on lines +2 to +66

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

tag_id is not accepted by EnvSpec here either.

The env-spec loader in vagen/gym_agent_dataset.py:15-43 instantiates each entry with EnvSpec(**OmegaConf.to_container(...)), and that dataclass does not define tag_id. Training will fail with TypeError before the dataset is even built unless this field is added to the schema or moved to a supported location.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/train/eb_alfred/train_eb_alfred_vision.yaml` around lines 2 - 66,
The YAML includes an unsupported field tag_id which causes EnvSpec construction
to raise a TypeError because EnvSpec (instantiated via
EnvSpec(**OmegaConf.to_container(...)) in the loader) doesn’t define tag_id; fix
by either removing/moving tag_id from each RemoteEnv entry (e.g., put it inside
config or another supported field) or add tag_id to the EnvSpec dataclass
definition so EnvSpec accepts it—update the EnvSpec dataclass (and any related
type annotations/serializers) or relocate tag_id in the YAML accordingly.

86 changes: 86 additions & 0 deletions examples/train/eb_alfred/train_ppo_no_concat_qwen25vl3b.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/bin/bash

set -x

Comment on lines +1 to +4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Enable -euo pipefail before piping trainer output to tee.

As written, python3 -m vagen.main_ppo ... | tee ... can fail while the script still exits 0, because only set -x is enabled. That makes failed runs easy to miss in schedulers and CI.

Proposed fix
-#!/bin/bash
-
-set -x
+#!/bin/bash
+set -euo pipefail
+set -x

Also applies to: 85-86

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/train/eb_alfred/train_ppo_no_concat_qwen25vl3b.sh` around lines 1 -
4, The script enables only set -x so pipeline failures can be masked; update the
shell initialization in train_ppo_no_concat_qwen25vl3b.sh to enable strict
failure handling (set -euo pipefail) before the pipeline that runs python3 -m
vagen.main_ppo ... | tee ..., and apply the same change to the other invocation
around lines 85-86; ensure the strict flags are declared at the top of the
script so any failed command in the pipeline causes the script to exit nonzero.

PROJECT_NAME="vagen_experiments"
EXPERIMENT_NAME="ppo_eb_alfred_no_concat"

BASEDIR=$(pwd)
SCRIPTDIR=$(dirname "$0")
EXPERIMENT_DIR=${BASEDIR}/exps/${PROJECT_NAME}/${EXPERIMENT_NAME}
SAVE_CHECKPOINT_DIR=${EXPERIMENT_DIR}/verl_checkpoints
DATASET_TRAIN=${SCRIPTDIR}/train_eb_alfred_vision.yaml
DATASET_VAL=${SCRIPTDIR}/val_eb_alfred_vision.yaml
agent_loop_config_path=${BASEDIR}/vagen/configs/agent_no_concat.yaml
REF_MODEL_PATH=Qwen/Qwen2.5-VL-3B-Instruct

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Stop deriving repo paths from the caller's working directory.

DATASET_TRAIN and DATASET_VAL are anchored to the script location, but --config-path and agent_loop_config_path are anchored to $PWD. Running this launcher from anywhere but the repo root points those paths at the wrong files.

Also applies to: 21-23

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/train/eb_alfred/train_ppo_no_concat_qwen25vl3b.sh` around lines 8 -
15, The script mixes PWD-based paths with script-relative paths so running it
outside the repo root breaks config resolution; replace usages that derive from
BASEDIR=$(pwd) (notably EXPERIMENT_DIR, SAVE_CHECKPOINT_DIR, and
agent_loop_config_path / any --config-path references) with paths computed
relative to the script location (use SCRIPTDIR=$(dirname "$0") and derive a repo
root or scripts root from that) so DATASET_TRAIN, DATASET_VAL,
agent_loop_config_path, and SAVE_CHECKPOINT_DIR all point to files under the
repository regardless of the caller's working directory.

mkdir -p ${EXPERIMENT_DIR}

export HF_HOME=/workspace/.hf_home
export PATH=/venv/vagen/bin:$PATH

PYTHONUNBUFFERED=1 python3 -m vagen.main_ppo \
--config-path=${BASEDIR}/vagen/configs \
--config-name='vagen_multiturn' \
data.train_files=${DATASET_TRAIN} \
data.val_files=${DATASET_VAL} \
data.train_batch_size=128 \
data.max_prompt_length=2048 \
data.max_response_length=512 \
+data.max_trajectory_length=7000 \
algorithm.adv_estimator=no_concat_gae_first \
algorithm.kl_ctrl.kl_coef=0.0 \
actor_rollout_ref.model.path=${REF_MODEL_PATH} \
actor_rollout_ref.model.use_remove_padding=True \
actor_rollout_ref.model.use_fused_kernels=True \
actor_rollout_ref.model.enable_gradient_checkpointing=True \
actor_rollout_ref.actor.optim.lr=1e-6 \
actor_rollout_ref.actor.ppo_mini_batch_size=32 \
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=1 \
actor_rollout_ref.actor.use_kl_loss=False \
actor_rollout_ref.actor.kl_loss_coef=0.0 \
actor_rollout_ref.actor.kl_loss_type=low_var_kl \
actor_rollout_ref.actor.entropy_coeff=0.0 \
actor_rollout_ref.actor.checkpoint.save_contents=['model','hf_model','optimizer','extra'] \
actor_rollout_ref.actor.ulysses_sequence_parallel_size=1 \
actor_rollout_ref.actor.fsdp_config.param_offload=True \
actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \
actor_rollout_ref.actor.freeze_vision_tower=True \
actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=1 \
actor_rollout_ref.rollout.tensor_model_parallel_size=1 \
actor_rollout_ref.rollout.name=sglang \
actor_rollout_ref.rollout.mode=async \
actor_rollout_ref.rollout.n=1 \
actor_rollout_ref.rollout.max_num_batched_tokens=10000 \
actor_rollout_ref.rollout.gpu_memory_utilization=0.6 \
actor_rollout_ref.rollout.enforce_eager=True \
actor_rollout_ref.rollout.free_cache_engine=True \
actor_rollout_ref.rollout.enable_chunked_prefill=True \
actor_rollout_ref.rollout.multi_turn.enable=True \
actor_rollout_ref.rollout.agent.agent_loop_config_path=$agent_loop_config_path \
actor_rollout_ref.rollout.disable_log_stats=False \
actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=1 \
actor_rollout_ref.ref.fsdp_config.param_offload=True \
critic.enable=True \
critic.optim.lr=1e-5 \
critic.model.use_remove_padding=True \
critic.model.path=${REF_MODEL_PATH} \
critic.model.enable_gradient_checkpointing=True \
critic.ppo_micro_batch_size_per_gpu=1 \
critic.model.fsdp_config.param_offload=True \
critic.model.fsdp_config.optimizer_offload=True \
trainer.critic_warmup=0 \
trainer.logger=['console','wandb'] \
trainer.val_before_train=True \
trainer.n_gpus_per_node=4 \
trainer.nnodes=1 \
trainer.save_freq=100 \
trainer.test_freq=20 \
trainer.project_name=${PROJECT_NAME} \
trainer.experiment_name=${EXPERIMENT_NAME} \
trainer.default_local_dir=${SAVE_CHECKPOINT_DIR} \
trainer.validation_data_dir=${EXPERIMENT_DIR}/validation \
trainer.rollout_data_dir=${EXPERIMENT_DIR}/rollout_data \
trainer.log_val_generations=32 \
+trainer.concat_multi_turn=False \
trainer.total_training_steps=400 2>&1 | \
tee ${EXPERIMENT_DIR}/${PROJECT_NAME}_${EXPERIMENT_NAME}.log >(tee ${BASEDIR}/${PROJECT_NAME}_${EXPERIMENT_NAME}.log >/dev/null)
44 changes: 44 additions & 0 deletions examples/train/eb_alfred/val_eb_alfred_vision.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
envs:
- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_val_common
seed: [0, 50, 1]
max_turns: 6
response_length_per_turn: 512
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: common_sense
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0

- name: RemoteEnv
n_envs: 50
data_source: eb_alfred
tag_id: eb_alfred_val_spatial
seed: [0, 50, 1]
max_turns: 6
response_length_per_turn: 512
config:
base_urls:
- "http://localhost:8000"
timeout: 600
eval_set: spatial
obs_image_size: 500
max_turns: 6
max_actions_per_step: 20
max_env_steps: 30
action_sep: ","
prompt_format: free_think
use_example_in_sys_prompt: true
format_reward: 0.1
success_reward: 1.0
Comment on lines +2 to +44

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

tag_id is not part of the EnvSpec schema.

load_envspecs() constructs each YAML entry as EnvSpec(**OmegaConf.to_container(...)), and the EnvSpec dataclass shown in vagen/gym_agent_dataset.py:15-43 has no tag_id field. This config will currently raise TypeError before any validation episode starts. Either add tag_id to EnvSpec or move it into a supported nested config field.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/train/eb_alfred/val_eb_alfred_vision.yaml` around lines 2 - 44, The
YAML uses an unsupported field tag_id which causes EnvSpec construction to fail;
update the dataclass EnvSpec (in vagen/gym_agent_dataset.py) to include a
tag_id: str | None field (and default to None) or move tag_id into an existing
nested config field (e.g., under config) and update load_envspecs() to map the
YAML key accordingly; ensure EnvSpec's __init__/type hints accept the new field
and any downstream code that references EnvSpec (or load_envspecs()) is adjusted
to read tag_id from the new location.

93 changes: 93 additions & 0 deletions vagen/envs/eb_alfred/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# EB-ALFRED Environment

AI2-THOR based household robot task environment from [EmbodiedBench](https://github.com/EmbodiedBench/EmbodiedBench). The agent receives egocentric RGB images and executes multi-step tasks (cleaning, heating, slicing, storing objects).

## Running the Service

The environment runs on a **separate GPU machine** with a physical or virtual display. AI2-THOR requires X11 rendering (CloudRendering is not supported on ai2thor 2.1.0).

**One-time setup — create the conda environment:**

```bash
conda create -n embodiedbench python=3.9 -y
conda activate embodiedbench

git clone https://github.com/EmbodiedBench/EmbodiedBench.git /root/EmbodiedBench
touch /root/EmbodiedBench/embodiedbench/__init__.py
pip install -e /root/EmbodiedBench

pip install torch torchvision --index-url https://download.pytorch.org/whl/cu126
pip install "ai2thor==2.1.0" "gym==0.23.0" "numpy<2.0" \
scipy Pillow networkx revtok vocab h5py tqdm natsort pyquaternion
pip install "flask==1.1.4" "werkzeug==1.0.1" \
"markupsafe<2.1" "jinja2<3.0" "itsdangerous<2.0"
pip install "opencv-python-headless<4.9"
```

**Download dataset** (`eval_set` selects the split: `base` — standard tasks, `long` — longer horizon):

```bash
git clone https://huggingface.co/datasets/EmbodiedBench/EB-ALFRED
mv EB-ALFRED /root/EmbodiedBench/embodiedbench/envs/eb_alfred/data/json_2.1.0
```

**Start the server** (GPUs and Xorg are auto-detected and started):

```bash
conda activate embodiedbench
python -m vagen.envs.eb_alfred.serve
```

Key parameters:
- `devices`: GPU indices (default: auto-detect via `CUDA_VISIBLE_DEVICES` or `nvidia-smi`)
- `capacity`: max concurrent Unity environments (default: 16)
- `startup_concurrency`: max Unity processes starting simultaneously, prevents CPU spikes (default: 8)
- `session_timeout`: idle session cleanup in seconds (default: 3600)

```bash
# Example: 2 GPUs, higher capacity
python -m vagen.envs.eb_alfred.serve --devices='[0,1]' --capacity=90 --startup_concurrency=6 --port=8000
```

**SSH tunnel** (if training machine is remote):

```bash
# Run on the env server — forwards port 8000 to training machine
ssh -p <PORT> -R 8000:localhost:8000 \
-o ServerAliveInterval=30 -o ServerAliveCountMax=5 \
-N -f user@training-machine-ip

# On training machine, allow many tunnels — add to /etc/ssh/sshd_config:
# MaxSessions 200
# then: service ssh reload
```

## Evaluation

```bash
conda activate vagen

# Terminal 1 (env server): start service
python -m vagen.envs.eb_alfred.serve --devices='[0,1]' --capacity=90

# Terminal 2 (training machine): run eval
python -m vagen.evaluate.run_eval --config examples/evaluate/eb_alfred/config.yaml
```

Config: `examples/evaluate/eb_alfred/config.yaml`

## Training

```bash
conda activate vagen

# Terminal 1 (env server): start service
python -m vagen.envs.eb_alfred.serve --devices='[0,1]' --capacity=90

# Terminal 2 (training machine): run training
cd VAGEN
bash examples/train/eb_alfred/train_grpo_qwen25vl3b.sh
```

Configs: `examples/train/eb_alfred/`

Empty file.
Loading