SWE-Lego-RL

Getting Started

Set up SWE-Lego-RL and launch your first training run

Every workload — training, evaluation, or batch inference — follows the same five steps:

1. build the venv        bash scripts/setup_env.sh              (once per machine)
2. describe the cluster  cp lib/site.example.env lib/site.env   (once per cluster)
3. copy a template       cp train/templates/X.env train/configs/mine.env
4. validate              PREFLIGHT_ONLY=1  then  DRY_RUN=1   (checks only, nothing launches)
5. launch                bash scripts/train/train.sh train/configs/mine.env

Replace train with eval (score a checkpoint) or infer (batch trajectory generation) for the other two workloads.

Launch paths

Steps 1–3 are identical either way. Steps 4–5 have two equivalent paths: run the runner by hand, or pass the config to the agent plugin (/rl:* skills for Claude Code), which validates it, requires an explicit confirmation, and launches the same runner.

ManualThrough the agent
ValidatePREFLIGHT_ONLY=1 bash scripts/train/train.sh <config>/rl:check <config>
Launchbash scripts/train/train.sh <config>/rl:run <config>
Watchtail -F logs/<exp>.log/rl:status
Serve the dashboardbash webui/start_dashboard.sh/rl:dashboard

Both paths run the same scripts/lib/preflight.sh. The agent adds live-machine checks — a run already in flight, foreign GPUs, a taken port — and a structured verdict; see Agent Plugin.

Prerequisites

  • 8× GPU (A100/H100-class) on the training node — on the single-node path vLLM serves the policy and verl runs the trainer on the same host.
  • A sandbox backend — a reachable Kubernetes cluster (production) or a Docker daemon (local or remote) for Harbor to run each trial in.
  • uv — used by scripts/setup_env.sh to build the training venv.
  • A policy checkpoint — e.g. an SFT-trained Qwen3 model on local disk.
  • Train/val task indexes: thin parquet pointer tables the trainer samples from — build one with utils/create_task_index.py, or produce a difficulty-filtered one with batch inference.
  • Task environment images, prebuilt and pushed to a registry the cluster can reach. An unreachable image source is the most common cause of a first run that produces nothing but env_setup_failed — see Site variables.

Run inside tmux

A training run lasts hours. Launch it in a tmux session, or with nohup setsid, so it survives a shell disconnect.

1. Venv

scripts/setup_env.sh builds the venv at .venv via uv, and clones + editably installs harbor and verl (plus pinned vllm / flash_attn / transformers / cupy). It is idempotent:

bash scripts/setup_env.sh

Key overrides (env vars): VENV_PATH, HARBOR_DIR / VERL_DIR (clone locations), HARBOR_REF / VERL_REF (branches), PYTHON_VERSION (default 3.12.3), and the SKIP_CLONE / SKIP_FLASH_ATTN / SKIP_CUPY flags. Confirm the editable installs resolve to the trees you expect:

.venv/bin/python -c "import harbor, verl, verl_patch; print(harbor.__file__)"

2. Site config

Everything cluster-specific lives in one file, never in a run config:

cp scripts/lib/site.example.env scripts/lib/site.env
$EDITOR scripts/lib/site.env

Set at least MODEL_ROOT (checkpoint location) and K8S_KUBECONFIG, plus HARBOR_OPENSWE_IMAGE_REGISTRY if a prebuilt-image registry exists. An empty value is legal and falls back to the portable, slower path. Site variables lists the full surface.

Once per cluster

Every runner sources site.env automatically. No file below this step holds a cluster address, so a run config is portable to a colleague's cluster once they write their own site.env.

3. Run config

Templates are named by their axes: <mode>_<backend>_<scaffold>_<model>.env. Copy the one matching the run into configs/:

ls scripts/train/templates/
#   async_k8s_ohsdk_qwen35a3b.env    sync_k8s_ohsdk_qwen35a3b.env
#   async_k8s_cc_qwen3-30b-a3b.env   sync_docker_oh_qwen3-30b-a3b.env   ...

cp scripts/train/templates/sync_k8s_ohsdk_qwen35a3b.env \
   scripts/train/configs/my_first_run.env

Edit only the CHANGEME lines — experiment name, data indexes, topology:

PROJECT_NAME=my-project
EXP_TAG=first-run
MODEL_PRESET=qwen35a3b            # fills MODEL_PATH / TOOL_PARSER / ENGINE / SP_SIZE / window
TRAIN_INDEX=/data/harbor_indexes/train.parquet
VAL_INDEX=/data/harbor_indexes/val.parquet
NNODES=1

Everything else has a default. A knob the template does not mention takes one KEY=VALUE line — see parameter tiers.

Smoke first

On a new model, scaffold, or cluster, start from a smoke config (TRAIN_BSZ=8 N_RESP=4): ~8× faster per step, and it exercises the whole path. Its gradients are noisy and its reward groups degenerate, so it is a plumbing check only, never a learning-quality signal.

4. Validation

Every runner understands two switches. Both resolve the config, print a report, and exit without touching a GPU or a cluster. Run them in this order:

# 1. config validation — 9 classes of fatal assertion, no cluster needed
PREFLIGHT_ONLY=1 bash scripts/train/train.sh train/configs/my_first_run.env

# 2. print the fully expanded launch command without running it
DRY_RUN=1 bash scripts/train/train.sh train/configs/my_first_run.env

Preflight stops on any ✗ FATAL. It catches the mistakes that otherwise cost a multi-hour run: a tool_parser that does not match the model × scaffold pair, node counts that do not add up, an SP_SIZE that does not divide the training world, R3 without the new verl tree, no reachable image source. Preflight lists all nine assertion classes.

The agent equivalent is /rl:check <config>: the same assertions plus live-machine checks.

5. Launch

bash scripts/train/train.sh train/configs/my_first_run.env

The agent equivalent is /rl:run train/configs/my_first_run.env, which launches in the background after an explicit confirmation.

The runner brings up Ray, boots vLLM, starts the in-process proxy, and drives the PPO/GRPO/GSPO loop. On a 30B MoE at TP=4, vLLM CUDA-graph capture takes 10–20 minutes before the first replica registers; this is expected. If a previous run left Ray or vLLM processes behind, clear them first with bash scripts/cleanup_before_run.sh.

6. Monitoring

tail -F logs/<exp>.log
bash webui/start_dashboard.sh            # http://<host>:8090 (+ public tunnel)

Checkpoints land under checkpoints/<project>/<exp>/global_step_N/. See Results & Artifacts and Dashboard.

Other workloads

The other two workloads use the same contract: copy a template, fill the CHANGEME lines, validate, run.

GoalRunnerGuide
Train a policyscripts/train/train.shthis page
Score a checkpoint on a held-out setscripts/eval/eval.shEvaluation
Batch-generate trajectories over an indexscripts/infer/infer.shBatch Inference

When one host is no longer enough — large MoE policies, ~131k contexts, or rollout-bound throughput — switch to an async_* template and add nodes; see Scaling Up.

On this page