p-doom/crowd-code-dataset-0.2 huggingface dataset:
[tab] slurm/jobs/mihir/horeka/lam/coinrun/coinrun_lam_400M.sbatch (shellscript)
#!/usr/bin/env bash

#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --time=2-00:00:00
#SBATCH --partition=accelerated
#SBATCH --cpus-per-task=5
#SBATCH --gres=gpu:1
#SBATCH --output=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/logs/logs_mihir/coinrun/lam/%x_%j.log
#SBATCH --error=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/logs/logs_mihir/coinrun/lam/%x_%j.log
#SBATCH --job-name=train_lam_coinrun_400M
#SBATCH --requeue
#SBATCH --signal=b:usr1@300 # 5 min before timeout

# --- signal trap to requeue job before timeout ---
requeue_job() {
    echo "[$(date)] caught sigusr1 (timeout warning), requeueing slurm job $SLURM_JOB_ID..."
    # optional: trigger checkpoint saving here
    # e.g., touch $checkpoint_dir/requeue_trigger
    scontrol requeue $SLURM_JOB_ID
    exit 0
}

trap requeue_job sigusr1

# set checkpoint flag based on restart count
restart_count=$(scontrol show job $SLURM_JOB_ID | grep -o 'Restarts=[0-9]*' | cut -d'=' -f2)

if [ $restart_count -eq 0 ]; then
    restore_ckpt_flag="--no-restore-ckpt"
else
    restore_ckpt_flag="--restore-ckpt"
fi

# Log the sbatch script
cat $0

module unload mpi/openmpi/5.0
module unload devel/cuda/12.4
source .venv/bin/activate

job_name=$SLURM_JOB_NAME
slurm_job_id=$SLURM_JOB_ID

CHECKPOINT_DIR=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/checkpoints/mihir/coinrun/lam/$job_name/$slurm_job_id
mkdir -p $CHECKPOINT_DIR

array_records_dir=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/data_coinrun/coinrun_episodes_10m_gt_actions_split/train
array_records_dir_val=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/data_coinrun/coinrun_episodes_10m_gt_actions_split/val

env | grep SLURM

srun python train_lam.py \
    --save_ckpt \
    $restore_ckpt_flag \
    --wandb_id $SLURM_JOB_ID \
    --ckpt_dir $CHECKPOINT_DIR \
    --batch_size=24 \
    --image_height=64 \
    --image_width=64 \
    --max_lr=3e-6 \
    --log_image_interval=1000 \
    --log_checkpoint_interval=1000 \
    --log \
    --name="${job_name}_${slurm_job_id}" \
    --tags "coinrun lam_ablation modelsize" \
    --entity instant-uv \
    --project jafar \
    --lr_schedule wsd \
    --model_dim=1024 \
    --num_blocks=12 \
    --num_heads=16 \
    --latent_dim=64 \
    --ffn_dim=4096 \
    --val_data_dir $array_records_dir_val \
    --data_dir $array_records_dir &

child_pid=$!

wait $child_pid
[tab] generate_dataset_chunk.py (python)
"""
Generates a dataset of random-action CoinRun episodes.
Episodes are saved individually as memory-mapped files for efficient loading.
"""

from dataclasses import dataclass
from pathlib import Path

from gym3 import types_np
import numpy as np
from procgen import ProcgenGym3Env
import tyro
import pickle
import json
from array_record.python.array_record_module import ArrayRecordWriter 



@dataclass
class Args:
    num_episodes: int = 10000
    output_dir: str = "data/coinrun_episodes"
    min_episode_length: int = 50
    max_episode_length: int = 1000
    chunk_size: int = 160


args = tyro.cli(Args)
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)

# --- Generate episodes ---
i = 0
episode_metadata = []
while i < args.num_episodes:
    seed = np.random.randint(0, 10000)
    env = ProcgenGym3Env(num=1, env_name="coinrun", start_level=seed)
    observations_seq = []

    # --- Run episode ---
    for j in range(args.max_episode_length):
        env.act(types_np.sample(env.ac_space, bshape=(env.num,)))
        rew, obs, first = env.observe()
        observations_seq.append(obs["rgb"])
        if first:
            break

    # --- Save episode ---
    if len(observations_seq) >= args.min_episode_length:
        observations_data = np.concatenate(observations_seq, axis=0).astype(np.uint8)
        episode_path = output_dir / f"episode_{i}.array_record"  

        file_chunks = []
        for start_idx in range(0, observations_data.shape[0] - args.chunk_size + 1, args.chunk_size):
            chunk = observations_data[start_idx : start_idx + args.chunk_size]

            chunk_record = {
                "raw_video": chunk.tobytes(),
                "sequence_length": args.chunk_size,
            }

            file_chunks.append(chunk_record)
        # --- Save as ArrayRecord ---
        chunks_per_file = 6
        for j in range(0, len(file_chunks), chunks_per_file):
            batch_chunks = file_chunks[j : j + chunks_per_file]

            writer = ArrayRecordWriter(str(episode_path), "group_size:1")
            for chunk in batch_chunks:
                writer.write(pickle.dumps(chunk))
            writer.close()

            episode_metadata.append({"path": episode_path, "length": args.chunk_size})
            print(f"Created {episode_path} with {len(batch_chunks)} video chunks")
        # episode_metadata.append({"path": str(episode_path), "length": len(observations_seq)})
        print(f"Episode {i} completed, length: {len(observations_seq)}")
        i += 1
    else:
        print(f"Episode too short ({len(observations_seq)}), resampling...")

# --- Save metadata ---
metadata = {
    "env": "coinrun",
    "num_episodes": args.num_episodes,
    "avg_episode_len": np.mean([ep["length"] for ep in episode_metadata]),
    "episode_metadata": episode_metadata,
}
with open(output_dir / "metadata.json", "w") as f:
    json.dump(metadata, f)

print(f"Dataset generated with {len(episode_metadata)} valid episodes")
[tab] slurm/jobs/mihir/horeka/preprocessing/preprocess_minecraft_single_chunk.sbatch (shellscript)
#!/usr/bin/env bash

#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --time=48:00:00
#SBATCH --partition=cpuonly
#SBATCH --cpus-per-task=16
#SBATCH --output=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/logs/logs_mihir/preprocess/minecraft/%x_%j.log
#SBATCH --error=/hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/logs/logs_mihir/preprocess/minecraft/%x_%j.log
#SBATCH --job-name=preprocess_minecraft_single_chunk

source .venv/bin/activate

python input_pipeline/preprocess/video_to_array_records.py \
        --input_path /hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/data_new/open_ai_minecraft \
        --output_path /hkfs/work/workspace/scratch/tum_ind3695-jafa_ws_shared/data_new/tmp/single_chunk \
        --env_name minecraft \
        --chunk_size 16000 \
        --chunks_per_file 1
[tab] generate_dataset.py (python)
"""
Generates a dataset of random-action CoinRun episodes.
Episodes are saved individually as memory-mapped files for efficient loading.
"""

from dataclasses import dataclass
from pathlib import Path

from gym3 import types_np
import numpy as np
from procgen import ProcgenGym3Env
import tyro
import pickle
import json
from array_record.python.array_record_module import ArrayRecordWriter 



@dataclass
class Args:
    num_episodes: int = 10000
    output_dir: str = "data/coinrun_episodes"
    min_episode_length: int = 50
    max_episode_length: int = 1000


args = tyro.cli(Args)
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)

# --- Generate episodes ---
i = 0
episode_metadata = []
while i < args.num_episodes:
    seed = np.random.randint(0, 10000)
    env = ProcgenGym3Env(num=1, env_name="coinrun", start_level=seed)
    observations_seq = []

    # --- Run episode ---
    for j in range(args.max_episode_length):
        env.act(types_np.sample(env.ac_space, bshape=(env.num,)))
        rew, obs, first = env.observe()
        observations_seq.append(obs["rgb"])
        if first:
            break

    # --- Save episode ---
    if len(observations_seq) >= args.min_episode_length:
        observations_data = np.concatenate(observations_seq, axis=0).astype(np.uint8)
        episode_path = output_dir / f"episode_{i}.array_record"  

        # --- Save as ArrayRecord ---
        writer = ArrayRecordWriter(str(episode_path), "group_size:1")
        record = {"raw_video": observations_data.tobytes(), "sequence_length": len(observations_seq)}
        writer.write(pickle.dumps(record))
        writer.close()

        episode_metadata.append({"path": str(episode_path), "length": len(observations_seq)})
        print(f"Episode {i} completed, length: {len(observations_seq)}")
        i += 1
    else:
        print(f"Episode too short ({len(observations_seq)}), resampling...")

# --- Save metadata ---
metadata = {
    "env": "coinrun",
    "num_episodes": args.num_episodes,
    "avg_episode_len": np.mean([ep["length"] for ep in episode_metadata]),
    "episode_metadata": episode_metadata,
}
with open(output_dir / "metadata.json", "w") as f:
    json.dump(metadata, f)

print(f"Dataset generated with {len(episode_metadata)} valid episodes")