Upload folder using huggingface_hub
Browse files- DOCKERFILE.dockerfile +111 -0
- batch_eval_lep.sh +99 -0
- eval_b1k.sh +39 -0
- eval_b1k_json.py +195 -0
- eval_openpi.sh +14 -0
- norm_stats.json +280 -0
- patch_comet_safetensors.sh +51 -0
- patch_walltime.sh +66 -0
- run_dual_eval.sh +72 -0
- tokenizer.model +3 -0
- tokenizer_config.json +7 -0
DOCKERFILE.dockerfile
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ARG COSMOS_RL_BUILD_MODE=efa
|
| 2 |
+
ARG COSMOS_RL_EXTRAS=""
|
| 3 |
+
|
| 4 |
+
ARG CUDA_VERSION=12.8.1
|
| 5 |
+
|
| 6 |
+
FROM nvcr.io/nvidia/cuda:${CUDA_VERSION}-devel-ubuntu22.04 AS no-efa-base
|
| 7 |
+
|
| 8 |
+
# System dependencies for eval
|
| 9 |
+
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
| 10 |
+
python3.10-dev python3-dev python3-distutils \
|
| 11 |
+
libgl1 libglib2.0-0 libglu1-mesa \
|
| 12 |
+
curl git ca-certificates \
|
| 13 |
+
tmux zip unzip vim \
|
| 14 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 15 |
+
|
| 16 |
+
# Install uv package manager
|
| 17 |
+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 18 |
+
ENV PATH="/root/.local/bin:$PATH"
|
| 19 |
+
|
| 20 |
+
# Install Miniconda
|
| 21 |
+
RUN curl -fsSL -o /tmp/miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
|
| 22 |
+
&& bash /tmp/miniconda.sh -b -p /opt/miniconda3 \
|
| 23 |
+
&& rm /tmp/miniconda.sh
|
| 24 |
+
ENV PATH="/opt/miniconda3/bin:$PATH"
|
| 25 |
+
|
| 26 |
+
ENV EVAL_ROOT=/opt/eval
|
| 27 |
+
|
| 28 |
+
# Clone b1k-eval-utils
|
| 29 |
+
RUN mkdir -p ${EVAL_ROOT} \
|
| 30 |
+
&& git clone https://github.com/littlespray/b1k-eval-utils.git ${EVAL_ROOT}/b1k-eval-utils
|
| 31 |
+
|
| 32 |
+
# Clone and setup openpi-comet
|
| 33 |
+
SHELL ["/bin/bash", "-c"]
|
| 34 |
+
RUN cd ${EVAL_ROOT} \
|
| 35 |
+
&& git clone https://github.com/mli0603/openpi-comet.git --depth=1 \
|
| 36 |
+
&& cd openpi-comet \
|
| 37 |
+
&& cp ${EVAL_ROOT}/b1k-eval-utils/eval_openpi.sh ${EVAL_ROOT}/openpi-comet/eval_openpi.sh \
|
| 38 |
+
&& cp ${EVAL_ROOT}/b1k-eval-utils/patch_comet_safetensors.sh ${EVAL_ROOT}/openpi-comet/patch_comet_safetensors.sh \
|
| 39 |
+
&& GIT_LFS_SKIP_SMUDGE=1 uv sync \
|
| 40 |
+
&& GIT_LFS_SKIP_SMUDGE=1 uv pip install -e . \
|
| 41 |
+
&& uv pip install transformers==4.53.2 \
|
| 42 |
+
&& cp -r ./src/openpi/models_pytorch/transformers_replace/* .venv/lib/python3.11/site-packages/transformers/ \
|
| 43 |
+
&& bash patch_comet_safetensors.sh
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
# Clone BEHAVIOR-1K and install bddl/OmniGibson into openpi-comet venv
|
| 47 |
+
RUN git clone -b v3.7.2 --single-branch --depth=1 \
|
| 48 |
+
https://github.com/StanfordVL/BEHAVIOR-1K.git ${EVAL_ROOT}/BEHAVIOR-1K
|
| 49 |
+
|
| 50 |
+
RUN cd ${EVAL_ROOT}/BEHAVIOR-1K \
|
| 51 |
+
&& source ${EVAL_ROOT}/openpi-comet/.venv/bin/activate \
|
| 52 |
+
&& uv pip install -e bddl3 \
|
| 53 |
+
&& uv pip install -e "OmniGibson[eval]" \
|
| 54 |
+
&& deactivate
|
| 55 |
+
|
| 56 |
+
# Prepare b1k environment
|
| 57 |
+
# RUN cd ${EVAL_ROOT}/BEHAVIOR-1K \
|
| 58 |
+
# && cp ${EVAL_ROOT}/b1k-eval-utils/patch_setup.sh patch_setup.sh \
|
| 59 |
+
# && bash patch_setup.sh \
|
| 60 |
+
|
| 61 |
+
WORKDIR ${EVAL_ROOT}/BEHAVIOR-1K
|
| 62 |
+
|
| 63 |
+
# Run b1k setup.sh (separate layer — most likely to fail, easy to retry)
|
| 64 |
+
ENV TORCH_CUDA_ARCH_LIST="8.0 9.0+PTX"
|
| 65 |
+
RUN cd ${EVAL_ROOT}/BEHAVIOR-1K \
|
| 66 |
+
&& source /opt/miniconda3/etc/profile.d/conda.sh \
|
| 67 |
+
&& conda deactivate \
|
| 68 |
+
&& ./setup.sh --new-env --omnigibson --bddl --joylo --eval --primitives \
|
| 69 |
+
--accept-conda-tos --accept-nvidia-eula
|
| 70 |
+
|
| 71 |
+
RUN source /opt/miniconda3/etc/profile.d/conda.sh \
|
| 72 |
+
&& conda activate behavior \
|
| 73 |
+
&& pip install scipy==1.11.4 \
|
| 74 |
+
&& pip uninstall -y numpy \
|
| 75 |
+
&& pip uninstall -y numpy \
|
| 76 |
+
&& pip install numpy==1.26.4 opencv-contrib-python==4.10.0.84
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
# RUN cd ${EVAL_ROOT}/BEHAVIOR-1K \
|
| 81 |
+
# && source /opt/miniconda3/etc/profile.d/conda.sh \
|
| 82 |
+
# && conda activate behavior \
|
| 83 |
+
# && python -c "from omnigibson.utils.asset_utils import download_omnigibson_robot_assets; download_omnigibson_robot_assets()"
|
| 84 |
+
# && python -c "from omnigibson.utils.asset_utils import download_behavior_1k_assets; download_behavior_1k_assets(accept_license=True)"
|
| 85 |
+
# && python -c "from omnigibson.utils.asset_utils import download_2025_challenge_task_instances; download_2025_challenge_task_instances()"
|
| 86 |
+
|
| 87 |
+
# Copy eval script
|
| 88 |
+
RUN cp ${EVAL_ROOT}/b1k-eval-utils/eval_b1k.sh ${EVAL_ROOT}/BEHAVIOR-1K/eval_b1k.sh
|
| 89 |
+
|
| 90 |
+
# Download HF models into the image for offline eval.
|
| 91 |
+
# Append new model repos here, separated by spaces.
|
| 92 |
+
|
| 93 |
+
# ENV HF_MODEL_REPOS="shangkuns/pt12-3w-comet2-20260204022222 shangkuns/pt12-2w-comet2-20260205151209 shangkuns/cosmos-pi05-sft-pt12-20260203145532 shangkuns/pt12-3w-20260204011934"
|
| 94 |
+
# RUN pip install --no-cache-dir "huggingface_hub[cli]" \
|
| 95 |
+
# && mkdir -p /opt/eval/models \
|
| 96 |
+
# && for repo in $HF_MODEL_REPOS; do \
|
| 97 |
+
# name="${repo#*/}"; \
|
| 98 |
+
# hf download "$repo" --repo-type model --local-dir "/opt/eval/models/$name"; \
|
| 99 |
+
# done
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
RUN cd ${EVAL_ROOT} \
|
| 103 |
+
&& cp -r openpi-comet/src/behavior/learning/* BEHAVIOR-1K/OmniGibson/omnigibson/learning/
|
| 104 |
+
|
| 105 |
+
#
|
| 106 |
+
ENV OPENPI_DATA_HOME=/opt/openpi-cache
|
| 107 |
+
RUN mkdir -p /opt/openpi-cache/big_vision \
|
| 108 |
+
&& cp ${EVAL_ROOT}/b1k-eval-utils/tokenizer.model /opt/openpi-cache/big_vision/paligemma_tokenizer.model
|
| 109 |
+
|
| 110 |
+
# Install huggingface-hub in the default Python environment
|
| 111 |
+
RUN python -m pip install huggingface-hub wandb
|
batch_eval_lep.sh
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
task_names=(
|
| 5 |
+
"turning_on_radio"
|
| 6 |
+
# "picking_up_trash"
|
| 7 |
+
# "picking_up_toys"
|
| 8 |
+
# "rearranging_kitchen_furniture"
|
| 9 |
+
# "putting_up_Christmas_decorations_inside"
|
| 10 |
+
# "sorting_vegetables"
|
| 11 |
+
# "putting_shoes_on_rack"
|
| 12 |
+
# "boxing_books_up_for_storage"
|
| 13 |
+
# "storing_food"
|
| 14 |
+
# "sorting_household_items"
|
| 15 |
+
# "wash_a_baseball_cap"
|
| 16 |
+
# "wash_dog_toys"
|
| 17 |
+
# "hanging_pictures"
|
| 18 |
+
# "attach_a_camera_to_a_tripod"
|
| 19 |
+
# "clean_a_trumpet"
|
| 20 |
+
# "spraying_for_bugs"
|
| 21 |
+
# "make_microwave_popcorn"
|
| 22 |
+
# "freeze_pies"
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
node_per_task=2
|
| 26 |
+
gpu_per_node=4
|
| 27 |
+
episodes_per_task=10
|
| 28 |
+
num_test_per_episode=2
|
| 29 |
+
ckpt_basename="pi05-b1kpt12-cs32"
|
| 30 |
+
|
| 31 |
+
total_work=$((episodes_per_task * num_test_per_episode))
|
| 32 |
+
base=$((total_work / node_per_task))
|
| 33 |
+
rem=$((total_work % node_per_task))
|
| 34 |
+
|
| 35 |
+
submitted=0
|
| 36 |
+
|
| 37 |
+
for task_name in "${task_names[@]}"; do
|
| 38 |
+
for (( node = 0; node < node_per_task; node++ )); do
|
| 39 |
+
if (( node < rem )); then
|
| 40 |
+
node_trials=$((base + 1))
|
| 41 |
+
node_start=$((node * (base + 1)))
|
| 42 |
+
else
|
| 43 |
+
node_trials=$base
|
| 44 |
+
node_start=$((rem * (base + 1) + (node - rem) * base))
|
| 45 |
+
fi
|
| 46 |
+
|
| 47 |
+
job_command="$(cat <<EOF
|
| 48 |
+
export TASK_NAME="${task_name}"
|
| 49 |
+
export CKPT_BASENAME="${ckpt_basename}"
|
| 50 |
+
export PATH_TO_CKPT=/tmp/\${CKPT_BASENAME}
|
| 51 |
+
export OPENPI_DATA_HOME=/opt/openpi-cache
|
| 52 |
+
export EPISODES_PER_TASK=${episodes_per_task}
|
| 53 |
+
export EVAL_START=${node_start}
|
| 54 |
+
export EVAL_COUNT=${node_trials}
|
| 55 |
+
export NUM_GPU=${gpu_per_node}
|
| 56 |
+
|
| 57 |
+
EVAL_ROOT=/opt/eval
|
| 58 |
+
|
| 59 |
+
cd \${EVAL_ROOT}/BEHAVIOR-1K
|
| 60 |
+
source /opt/miniconda3/etc/profile.d/conda.sh
|
| 61 |
+
conda activate behavior
|
| 62 |
+
python -c "from omnigibson.utils.asset_utils import download_omnigibson_robot_assets; download_omnigibson_robot_assets()"
|
| 63 |
+
python -c "from omnigibson.utils.asset_utils import download_behavior_1k_assets; download_behavior_1k_assets(accept_license=True)"
|
| 64 |
+
python -c "from omnigibson.utils.asset_utils import download_2025_challenge_task_instances; download_2025_challenge_task_instances()"
|
| 65 |
+
conda deactivate
|
| 66 |
+
|
| 67 |
+
hf download shangkuns/\${CKPT_BASENAME} --local-dir \${PATH_TO_CKPT}
|
| 68 |
+
mkdir -p \${PATH_TO_CKPT}/assets/behavior-1k/2025-challenge-demos
|
| 69 |
+
cp \${EVAL_ROOT}/b1k-eval-utils/norm_stats.json \${PATH_TO_CKPT}/assets/behavior-1k/2025-challenge-demos/
|
| 70 |
+
|
| 71 |
+
cd \${EVAL_ROOT}/b1k-eval-utils
|
| 72 |
+
bash patch_walltime.sh \${EVAL_ROOT}/BEHAVIOR-1K/OmniGibson/omnigibson/learning
|
| 73 |
+
bash run_dual_eval.sh
|
| 74 |
+
|
| 75 |
+
hf upload shangkuns/\${CKPT_BASENAME} /opt/eval/eval_output \${TASK_NAME} --repo-type dataset
|
| 76 |
+
EOF
|
| 77 |
+
)"
|
| 78 |
+
|
| 79 |
+
lep job create \
|
| 80 |
+
--resource-shape "my.${gpu_per_node}xl40s" \
|
| 81 |
+
--node-group oci-ord-lepton-001 \
|
| 82 |
+
--num-workers 1 \
|
| 83 |
+
--container-image littlespray/b1k-eval-light:v4 \
|
| 84 |
+
--command "${job_command}" \
|
| 85 |
+
--intra-job-communication=true \
|
| 86 |
+
--env NVIDIA_DRIVER_CAPABILITIES=all \
|
| 87 |
+
--env DEBIAN_FRONTEND=noninteractive \
|
| 88 |
+
--secret HUGGING_FACE_HUB_TOKEN=SHANGKUN_HF_NV.shangkuns \
|
| 89 |
+
--ttl-seconds-after-finished 259200 \
|
| 90 |
+
--log-collection true \
|
| 91 |
+
--queue-priority 8 \
|
| 92 |
+
--can-preempt \
|
| 93 |
+
--name "${task_name//_/-}-n${node}"
|
| 94 |
+
|
| 95 |
+
submitted=$((submitted + 1))
|
| 96 |
+
done
|
| 97 |
+
done
|
| 98 |
+
|
| 99 |
+
echo "Submitted ${submitted} jobs."
|
eval_b1k.sh
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export ROOT_DIR=${ROOT_DIR:-/opt/eval}
|
| 2 |
+
export OMNIGIBSON_HEADLESS=${OMNIGIBSON_HEADLESS:-1}
|
| 3 |
+
export NUM_GPU=${NUM_GPU:-1}
|
| 4 |
+
export BASE_PORT=${BASE_PORT:-8000}
|
| 5 |
+
export TASK_NAME=${TASK_NAME:-turning_on_radio}
|
| 6 |
+
export LOG_PATH=${LOG_PATH:-${ROOT_DIR}/eval_output}
|
| 7 |
+
mkdir -p "$LOG_PATH"
|
| 8 |
+
|
| 9 |
+
TOTAL=${EVAL_COUNT:-4}
|
| 10 |
+
START=${EVAL_START_IDX:-0}
|
| 11 |
+
|
| 12 |
+
BASE=$((TOTAL / NUM_GPU))
|
| 13 |
+
REM=$((TOTAL % NUM_GPU))
|
| 14 |
+
|
| 15 |
+
for ((gpu = 0; gpu < NUM_GPU; gpu++)); do
|
| 16 |
+
if ((gpu < REM)); then
|
| 17 |
+
count=$((BASE + 1))
|
| 18 |
+
s=$((START + gpu * (BASE + 1)))
|
| 19 |
+
else
|
| 20 |
+
count=$BASE
|
| 21 |
+
s=$((START + REM * (BASE + 1) + (gpu - REM) * BASE))
|
| 22 |
+
fi
|
| 23 |
+
(( count == 0 )) && continue
|
| 24 |
+
|
| 25 |
+
CUDA_VISIBLE_DEVICES="$gpu" \
|
| 26 |
+
python "${ROOT_DIR}/BEHAVIOR-1K/OmniGibson/omnigibson/learning/eval_custom.py" \
|
| 27 |
+
policy=websocket \
|
| 28 |
+
task.name=$TASK_NAME \
|
| 29 |
+
log_path=$LOG_PATH \
|
| 30 |
+
env_wrapper._target_=omnigibson.learning.wrappers.RGBWrapper \
|
| 31 |
+
save_rollout=false \
|
| 32 |
+
perturb_pose=false \
|
| 33 |
+
use_parallel_evaluator=true \
|
| 34 |
+
parallel_evaluator_start_idx=$s \
|
| 35 |
+
parallel_evaluator_end_idx=$((s + count)) \
|
| 36 |
+
model.port=$((BASE_PORT + gpu)) \
|
| 37 |
+
> "$LOG_PATH/${gpu}_stdout.log" 2>&1 &
|
| 38 |
+
done
|
| 39 |
+
wait
|
eval_b1k_json.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
统计 Hugging Face dataset 仓库中所有 exp 的逐轮成功率。
|
| 4 |
+
|
| 5 |
+
目录结构约定:task/exp/metrics/*.json
|
| 6 |
+
示例文件:
|
| 7 |
+
turning-on-radio/turning_on_radio_xxx_20260216085234/metrics/turning_on_radio_109_0.json
|
| 8 |
+
|
| 9 |
+
规则:
|
| 10 |
+
1. 对同一个 episode id,收集所有 exp 中对应 json;
|
| 11 |
+
2. 按 exp 目录末尾时间戳升序排序;
|
| 12 |
+
3. 第 i 轮平均值 = 所有 episode 各自第 i 个结果的 q_score.final 平均;
|
| 13 |
+
4. 当任一 episode 不足第 i 个结果时停止;
|
| 14 |
+
5. 输出每轮平均值,以及这些平均值的平均值。
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
from __future__ import annotations
|
| 18 |
+
|
| 19 |
+
import argparse
|
| 20 |
+
import json
|
| 21 |
+
import re
|
| 22 |
+
from collections import defaultdict
|
| 23 |
+
from dataclasses import dataclass
|
| 24 |
+
from statistics import mean
|
| 25 |
+
from typing import DefaultDict, Dict, List, Tuple
|
| 26 |
+
|
| 27 |
+
from huggingface_hub import HfApi, hf_hub_download
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
EXP_TIMESTAMP_RE = re.compile(r"_(\d{14})$")
|
| 31 |
+
EPISODE_ID_RE = re.compile(r"_(\d+)_\d+\.json$")
|
| 32 |
+
METRICS_JSON_RE = re.compile(r"^[^/]+/[^/]+/metrics/[^/]+\.json$")
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@dataclass(frozen=True)
|
| 36 |
+
class EpisodeEval:
|
| 37 |
+
task: str
|
| 38 |
+
episode_id: str
|
| 39 |
+
timestamp: str
|
| 40 |
+
q_score: float
|
| 41 |
+
wall_time: float | None
|
| 42 |
+
path: str
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def parse_args() -> argparse.Namespace:
|
| 46 |
+
parser = argparse.ArgumentParser(
|
| 47 |
+
description="计算 HF dataset 仓库中逐轮 episode 成功率均值。"
|
| 48 |
+
)
|
| 49 |
+
parser.add_argument(
|
| 50 |
+
"repo_id",
|
| 51 |
+
help="HF dataset 仓库名,例如 shangkuns/pt12-3w-comet2-20260204022222",
|
| 52 |
+
)
|
| 53 |
+
parser.add_argument(
|
| 54 |
+
"--repo-type",
|
| 55 |
+
default="dataset",
|
| 56 |
+
choices=["dataset", "model", "space"],
|
| 57 |
+
help="HF 仓库类型,默认 dataset。",
|
| 58 |
+
)
|
| 59 |
+
return parser.parse_args()
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def extract_timestamp_from_exp(exp_name: str) -> str | None:
|
| 63 |
+
match = EXP_TIMESTAMP_RE.search(exp_name)
|
| 64 |
+
return match.group(1) if match else None
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def extract_episode_id_from_filename(filename: str) -> str | None:
|
| 68 |
+
match = EPISODE_ID_RE.search(filename)
|
| 69 |
+
return match.group(1) if match else None
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def collect_episode_evals(
|
| 73 |
+
repo_id: str, repo_type: str
|
| 74 |
+
) -> Dict[Tuple[str, str], List[EpisodeEval]]:
|
| 75 |
+
api = HfApi()
|
| 76 |
+
repo_files = api.list_repo_files(repo_id=repo_id, repo_type=repo_type)
|
| 77 |
+
|
| 78 |
+
episode_to_evals: DefaultDict[Tuple[str, str], List[EpisodeEval]] = defaultdict(list)
|
| 79 |
+
|
| 80 |
+
for path in repo_files:
|
| 81 |
+
if not METRICS_JSON_RE.match(path):
|
| 82 |
+
continue
|
| 83 |
+
|
| 84 |
+
parts = path.split("/")
|
| 85 |
+
# task / exp / metrics / xxx.json
|
| 86 |
+
if len(parts) != 4:
|
| 87 |
+
continue
|
| 88 |
+
|
| 89 |
+
task_name = parts[0]
|
| 90 |
+
exp_name = parts[1]
|
| 91 |
+
file_name = parts[3]
|
| 92 |
+
|
| 93 |
+
timestamp = extract_timestamp_from_exp(exp_name)
|
| 94 |
+
if timestamp is None:
|
| 95 |
+
continue
|
| 96 |
+
|
| 97 |
+
episode_id = extract_episode_id_from_filename(file_name)
|
| 98 |
+
if episode_id is None:
|
| 99 |
+
continue
|
| 100 |
+
|
| 101 |
+
local_path = hf_hub_download(repo_id=repo_id, repo_type=repo_type, filename=path)
|
| 102 |
+
with open(local_path, "r", encoding="utf-8") as f:
|
| 103 |
+
content = json.load(f)
|
| 104 |
+
|
| 105 |
+
q_score = float(content["q_score"]["final"])
|
| 106 |
+
wall_time = None
|
| 107 |
+
if isinstance(content.get("time"), dict) and "wall_time" in content["time"]:
|
| 108 |
+
wall_time = float(content["time"]["wall_time"])
|
| 109 |
+
|
| 110 |
+
episode_to_evals[(task_name, episode_id)].append(
|
| 111 |
+
EpisodeEval(
|
| 112 |
+
task=task_name,
|
| 113 |
+
episode_id=episode_id,
|
| 114 |
+
timestamp=timestamp,
|
| 115 |
+
q_score=q_score,
|
| 116 |
+
wall_time=wall_time,
|
| 117 |
+
path=path,
|
| 118 |
+
)
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
return dict(episode_to_evals)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def compute_round_means(
|
| 125 |
+
episode_to_evals: Dict[Tuple[str, str], List[EpisodeEval]]
|
| 126 |
+
) -> Tuple[List[float], List[EpisodeEval]]:
|
| 127 |
+
if not episode_to_evals:
|
| 128 |
+
return [], []
|
| 129 |
+
|
| 130 |
+
for evals in episode_to_evals.values():
|
| 131 |
+
evals.sort(key=lambda x: x.timestamp)
|
| 132 |
+
|
| 133 |
+
max_rounds = min(len(evals) for evals in episode_to_evals.values())
|
| 134 |
+
if max_rounds == 0:
|
| 135 |
+
return [], []
|
| 136 |
+
|
| 137 |
+
round_means: List[float] = []
|
| 138 |
+
used_evals: List[EpisodeEval] = []
|
| 139 |
+
episode_keys = sorted(episode_to_evals.keys(), key=lambda x: (x[0], int(x[1])))
|
| 140 |
+
for round_idx in range(max_rounds):
|
| 141 |
+
this_round = [episode_to_evals[key][round_idx] for key in episode_keys]
|
| 142 |
+
values = [item.q_score for item in this_round]
|
| 143 |
+
used_evals.extend(this_round)
|
| 144 |
+
round_means.append(mean(values))
|
| 145 |
+
return round_means, used_evals
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def compute_wall_time_stats(used_evals: List[EpisodeEval]) -> Tuple[Dict[str, float], float | None]:
|
| 149 |
+
task_to_times: DefaultDict[str, List[float]] = defaultdict(list)
|
| 150 |
+
for item in used_evals:
|
| 151 |
+
if item.wall_time is not None:
|
| 152 |
+
task_to_times[item.task].append(item.wall_time)
|
| 153 |
+
|
| 154 |
+
task_means = {task: mean(times) for task, times in task_to_times.items() if times}
|
| 155 |
+
if not task_means:
|
| 156 |
+
return task_means, None
|
| 157 |
+
overall_task_mean = mean(task_means.values())
|
| 158 |
+
return task_means, overall_task_mean
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def main() -> None:
|
| 162 |
+
args = parse_args()
|
| 163 |
+
|
| 164 |
+
episode_to_evals = collect_episode_evals(args.repo_id, args.repo_type)
|
| 165 |
+
if not episode_to_evals:
|
| 166 |
+
print("未找到符合 task/exp/metrics/*.json 结构且可解析 episode/timestamp 的文件。")
|
| 167 |
+
return
|
| 168 |
+
|
| 169 |
+
round_means, used_evals = compute_round_means(episode_to_evals)
|
| 170 |
+
if not round_means:
|
| 171 |
+
print("没有可计算的轮次(可能某些 episode 无有效结果)。")
|
| 172 |
+
return
|
| 173 |
+
|
| 174 |
+
print(f"repo: {args.repo_id}")
|
| 175 |
+
print(f"episode 数量: {len(episode_to_evals)}")
|
| 176 |
+
print(f"可计算轮次: {len(round_means)}")
|
| 177 |
+
for idx, value in enumerate(round_means, start=1):
|
| 178 |
+
print(f"第{idx}轮平均成功率: {value:.6f}")
|
| 179 |
+
|
| 180 |
+
overall = mean(round_means)
|
| 181 |
+
print(f"各轮平均值的平均值: {overall:.6f}")
|
| 182 |
+
|
| 183 |
+
task_means, overall_task_mean = compute_wall_time_stats(used_evals)
|
| 184 |
+
if not task_means:
|
| 185 |
+
print("参与 q-score 统计的样本中未找到 time.wall_time,跳过用时统计。")
|
| 186 |
+
return
|
| 187 |
+
|
| 188 |
+
print("各 task 平均 episode 用时:")
|
| 189 |
+
for task in sorted(task_means.keys()):
|
| 190 |
+
print(f"- {task}: {task_means[task]:.6f}")
|
| 191 |
+
print(f"所有 task 平均用时: {overall_task_mean:.6f}")
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
if __name__ == "__main__":
|
| 195 |
+
main()
|
eval_openpi.sh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
TASK_NAME="${TASK_NAME:-cook_hot_dogs}"
|
| 5 |
+
CONFIG="${CONFIG:-pi05_b1k-base}"
|
| 6 |
+
PATH_TO_CKPT="${PATH_TO_CKPT:-/workspace/comet-pi05-b1k-pt50-ptm}"
|
| 7 |
+
PORT="${PORT:-8000}"
|
| 8 |
+
|
| 9 |
+
exec uv run scripts/serve_b1k.py \
|
| 10 |
+
--task_name "$TASK_NAME" \
|
| 11 |
+
--port "$PORT" \
|
| 12 |
+
policy:checkpoint \
|
| 13 |
+
--policy.config "$CONFIG" \
|
| 14 |
+
--policy.dir "$PATH_TO_CKPT"
|
norm_stats.json
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"norm_stats": {
|
| 3 |
+
"state": {
|
| 4 |
+
"mean": [
|
| 5 |
+
-0.0007269753236491301,
|
| 6 |
+
0.0005871853206764299,
|
| 7 |
+
-0.00037458819335587837,
|
| 8 |
+
1.1220268708249688,
|
| 9 |
+
-1.6177487234510692,
|
| 10 |
+
-0.7037017488819726,
|
| 11 |
+
5.178331679376605e-6,
|
| 12 |
+
-0.3819930547932975,
|
| 13 |
+
0.0636385481520187,
|
| 14 |
+
-0.036330391163538304,
|
| 15 |
+
-0.5923406613420917,
|
| 16 |
+
0.27300850717924735,
|
| 17 |
+
0.06392431067313378,
|
| 18 |
+
-0.23112970703914087,
|
| 19 |
+
-0.4207707978561216,
|
| 20 |
+
-0.06831169401385709,
|
| 21 |
+
0.0243751039006989,
|
| 22 |
+
-0.6469659968323186,
|
| 23 |
+
-0.12143957181667113,
|
| 24 |
+
0.14976853360672077,
|
| 25 |
+
0.130979475995902,
|
| 26 |
+
0.08751846492897486,
|
| 27 |
+
0.07864204959670715,
|
| 28 |
+
0.0,
|
| 29 |
+
0.0,
|
| 30 |
+
0.0,
|
| 31 |
+
0.0,
|
| 32 |
+
0.0,
|
| 33 |
+
0.0,
|
| 34 |
+
0.0,
|
| 35 |
+
0.0,
|
| 36 |
+
0.0
|
| 37 |
+
],
|
| 38 |
+
"std": [
|
| 39 |
+
0.02199286521964398,
|
| 40 |
+
0.01975387071601238,
|
| 41 |
+
0.027931866359868447,
|
| 42 |
+
0.43276966334356803,
|
| 43 |
+
0.7793389811993767,
|
| 44 |
+
0.4685643576682486,
|
| 45 |
+
0.00007484946359270099,
|
| 46 |
+
0.3495479212084949,
|
| 47 |
+
0.14741056781059605,
|
| 48 |
+
0.4086500808617923,
|
| 49 |
+
0.45792477411954097,
|
| 50 |
+
0.4472871307419175,
|
| 51 |
+
0.4255421558256086,
|
| 52 |
+
0.5117453304941143,
|
| 53 |
+
0.3626599950258924,
|
| 54 |
+
0.14969143472339538,
|
| 55 |
+
0.3820732235768937,
|
| 56 |
+
0.5161227600903063,
|
| 57 |
+
0.42373140636873546,
|
| 58 |
+
0.4839893318550682,
|
| 59 |
+
0.4912556634102691,
|
| 60 |
+
0.026452244464230175,
|
| 61 |
+
0.03343202113475432,
|
| 62 |
+
0.0,
|
| 63 |
+
0.0,
|
| 64 |
+
0.0,
|
| 65 |
+
0.0,
|
| 66 |
+
0.0,
|
| 67 |
+
0.0,
|
| 68 |
+
0.0,
|
| 69 |
+
0.0,
|
| 70 |
+
0.0
|
| 71 |
+
],
|
| 72 |
+
"q01": [
|
| 73 |
+
-0.2613118174761534,
|
| 74 |
+
-0.25247000222802163,
|
| 75 |
+
-0.29782283776104446,
|
| 76 |
+
0.4487143921405077,
|
| 77 |
+
-2.5600294193029405,
|
| 78 |
+
-1.8321708536148071,
|
| 79 |
+
-0.0007136256152298301,
|
| 80 |
+
-2.105691260957718,
|
| 81 |
+
-0.17450003325939178,
|
| 82 |
+
-2.230193532180786,
|
| 83 |
+
-1.6330286006212233,
|
| 84 |
+
-1.411822907948494,
|
| 85 |
+
-1.0471969878673553,
|
| 86 |
+
-1.5708000659942627,
|
| 87 |
+
-1.91510467287302,
|
| 88 |
+
-0.849857434040308,
|
| 89 |
+
-1.6666959735155105,
|
| 90 |
+
-1.6168319140672684,
|
| 91 |
+
-2.3132422157287595,
|
| 92 |
+
-1.0375005970597269,
|
| 93 |
+
-1.570798397064209,
|
| 94 |
+
0.0,
|
| 95 |
+
6.501830672824839e-8,
|
| 96 |
+
0.0,
|
| 97 |
+
0.0,
|
| 98 |
+
0.0,
|
| 99 |
+
0.0,
|
| 100 |
+
0.0,
|
| 101 |
+
0.0,
|
| 102 |
+
0.0,
|
| 103 |
+
0.0,
|
| 104 |
+
0.0
|
| 105 |
+
],
|
| 106 |
+
"q99": [
|
| 107 |
+
0.2542599085897208,
|
| 108 |
+
0.2542742739796637,
|
| 109 |
+
0.30030812568068505,
|
| 110 |
+
1.716256618249416,
|
| 111 |
+
-0.3974635741829872,
|
| 112 |
+
0.1548894247069954,
|
| 113 |
+
0.0005543326894694459,
|
| 114 |
+
0.37031316382586876,
|
| 115 |
+
0.9278406740725034,
|
| 116 |
+
1.91316024565696,
|
| 117 |
+
0.09516809616684914,
|
| 118 |
+
2.356194269657135,
|
| 119 |
+
1.0472097456455232,
|
| 120 |
+
1.517247679293155,
|
| 121 |
+
0.36055924194753,
|
| 122 |
+
0.17450004816055298,
|
| 123 |
+
1.6652137512683844,
|
| 124 |
+
0.0914144726134836,
|
| 125 |
+
1.6950346724390943,
|
| 126 |
+
1.0471995235800744,
|
| 127 |
+
1.56818338637352,
|
| 128 |
+
0.10000000149011612,
|
| 129 |
+
0.10000000149011612,
|
| 130 |
+
0.0,
|
| 131 |
+
0.0,
|
| 132 |
+
0.0,
|
| 133 |
+
0.0,
|
| 134 |
+
0.0,
|
| 135 |
+
0.0,
|
| 136 |
+
0.0,
|
| 137 |
+
0.0,
|
| 138 |
+
0.0
|
| 139 |
+
]
|
| 140 |
+
},
|
| 141 |
+
"actions": {
|
| 142 |
+
"mean": [
|
| 143 |
+
0.04972944409549112,
|
| 144 |
+
0.003690394849812747,
|
| 145 |
+
-0.0029349690138718285,
|
| 146 |
+
1.122085165280863,
|
| 147 |
+
-1.6180965905064797,
|
| 148 |
+
-0.7043162896930203,
|
| 149 |
+
0.0,
|
| 150 |
+
-0.382348926450185,
|
| 151 |
+
0.06370661786532403,
|
| 152 |
+
-0.03661990100703703,
|
| 153 |
+
-0.5924590200206378,
|
| 154 |
+
0.2750886004936484,
|
| 155 |
+
0.06431002005410705,
|
| 156 |
+
-0.23144970536531229,
|
| 157 |
+
0.4210819724256232,
|
| 158 |
+
-0.4212541587202455,
|
| 159 |
+
-0.06839742236782122,
|
| 160 |
+
0.024488948505712194,
|
| 161 |
+
-0.6468751837828239,
|
| 162 |
+
-0.12300583051861715,
|
| 163 |
+
0.1507738855467879,
|
| 164 |
+
0.13119771996817328,
|
| 165 |
+
0.20474606868389103,
|
| 166 |
+
0.0,
|
| 167 |
+
0.0,
|
| 168 |
+
0.0,
|
| 169 |
+
0.0,
|
| 170 |
+
0.0,
|
| 171 |
+
0.0,
|
| 172 |
+
0.0,
|
| 173 |
+
0.0,
|
| 174 |
+
0.0
|
| 175 |
+
],
|
| 176 |
+
"std": [
|
| 177 |
+
0.13018670744434768,
|
| 178 |
+
0.07378928098443516,
|
| 179 |
+
0.11732054405741633,
|
| 180 |
+
0.4326509056935839,
|
| 181 |
+
0.7791573756824512,
|
| 182 |
+
0.46843066554707175,
|
| 183 |
+
0.0,
|
| 184 |
+
0.34964716759678244,
|
| 185 |
+
0.14751595777952248,
|
| 186 |
+
0.41012746451839815,
|
| 187 |
+
0.4580261645466588,
|
| 188 |
+
0.4486994719029271,
|
| 189 |
+
0.4276847015578234,
|
| 190 |
+
0.5130942257930428,
|
| 191 |
+
0.9070220542734125,
|
| 192 |
+
0.3626863499954174,
|
| 193 |
+
0.14981404106277435,
|
| 194 |
+
0.3835292477509873,
|
| 195 |
+
0.5164924719696999,
|
| 196 |
+
0.4256839962396164,
|
| 197 |
+
0.48620749808715086,
|
| 198 |
+
0.49307611404915425,
|
| 199 |
+
0.9788150111676108,
|
| 200 |
+
0.0,
|
| 201 |
+
0.0,
|
| 202 |
+
0.0,
|
| 203 |
+
0.0,
|
| 204 |
+
0.0,
|
| 205 |
+
0.0,
|
| 206 |
+
0.0,
|
| 207 |
+
0.0,
|
| 208 |
+
0.0
|
| 209 |
+
],
|
| 210 |
+
"q01": [
|
| 211 |
+
-0.34868216374218464,
|
| 212 |
+
-0.3418492655992508,
|
| 213 |
+
-0.2999999523162842,
|
| 214 |
+
0.44999998807907104,
|
| 215 |
+
-2.560204291343689,
|
| 216 |
+
-1.8325998783111572,
|
| 217 |
+
0.0,
|
| 218 |
+
-2.1070283545494077,
|
| 219 |
+
-0.1745000034570694,
|
| 220 |
+
-2.230065962147713,
|
| 221 |
+
-1.6336875317335129,
|
| 222 |
+
-1.4130705307483673,
|
| 223 |
+
-1.0471980571746826,
|
| 224 |
+
-1.5707999467849731,
|
| 225 |
+
-1.0,
|
| 226 |
+
-1.9151124985814094,
|
| 227 |
+
-0.8498951392710209,
|
| 228 |
+
-1.6674389212727547,
|
| 229 |
+
-1.616815806877613,
|
| 230 |
+
-2.3132428766012194,
|
| 231 |
+
-1.0385202980041504,
|
| 232 |
+
-1.5707999467849731,
|
| 233 |
+
-1.0,
|
| 234 |
+
0.0,
|
| 235 |
+
0.0,
|
| 236 |
+
0.0,
|
| 237 |
+
0.0,
|
| 238 |
+
0.0,
|
| 239 |
+
0.0,
|
| 240 |
+
0.0,
|
| 241 |
+
0.0,
|
| 242 |
+
0.0
|
| 243 |
+
],
|
| 244 |
+
"q99": [
|
| 245 |
+
0.34921015488803386,
|
| 246 |
+
0.34948091855645175,
|
| 247 |
+
0.2999999523162842,
|
| 248 |
+
1.7161086392402647,
|
| 249 |
+
-0.4000000059604645,
|
| 250 |
+
0.1548384608328342,
|
| 251 |
+
0.0,
|
| 252 |
+
0.3706086640655987,
|
| 253 |
+
0.9287866185903546,
|
| 254 |
+
1.9131654405593803,
|
| 255 |
+
0.09510681201517582,
|
| 256 |
+
2.3561956882476807,
|
| 257 |
+
1.0471980571746826,
|
| 258 |
+
1.5173104754924756,
|
| 259 |
+
1.0,
|
| 260 |
+
0.3605582716763002,
|
| 261 |
+
0.1745000034570694,
|
| 262 |
+
1.6659219603061668,
|
| 263 |
+
0.09357282519340515,
|
| 264 |
+
1.6951719859242371,
|
| 265 |
+
1.0471980571746826,
|
| 266 |
+
1.5707999467849731,
|
| 267 |
+
1.0,
|
| 268 |
+
0.0,
|
| 269 |
+
0.0,
|
| 270 |
+
0.0,
|
| 271 |
+
0.0,
|
| 272 |
+
0.0,
|
| 273 |
+
0.0,
|
| 274 |
+
0.0,
|
| 275 |
+
0.0,
|
| 276 |
+
0.0
|
| 277 |
+
]
|
| 278 |
+
}
|
| 279 |
+
}
|
| 280 |
+
}
|
patch_comet_safetensors.sh
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 5 |
+
ROOT_DIR="${ROOT_DIR:-$SCRIPT_DIR}"
|
| 6 |
+
|
| 7 |
+
POLICY_CONFIG_FILE="${ROOT_DIR}/src/openpi/policies/policy_config.py"
|
| 8 |
+
MODEL_FILE="${ROOT_DIR}/src/openpi/models/model.py"
|
| 9 |
+
|
| 10 |
+
python3 - "$POLICY_CONFIG_FILE" "$MODEL_FILE" <<'PY'
|
| 11 |
+
import pathlib
|
| 12 |
+
import sys
|
| 13 |
+
|
| 14 |
+
policy_config_file = pathlib.Path(sys.argv[1])
|
| 15 |
+
model_file = pathlib.Path(sys.argv[2])
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def replace_or_exit(path: pathlib.Path, old: str, new: str, label: str) -> None:
|
| 19 |
+
text = path.read_text()
|
| 20 |
+
if new in text:
|
| 21 |
+
print(f"[skip] {path.name}: {label} already applied")
|
| 22 |
+
return
|
| 23 |
+
if old not in text:
|
| 24 |
+
raise SystemExit(f"[error] Could not find expected block for {label} in {path}")
|
| 25 |
+
path.write_text(text.replace(old, new))
|
| 26 |
+
print(f"[ok] {path.name}: {label}")
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
replace_or_exit(
|
| 30 |
+
policy_config_file,
|
| 31 |
+
""" # Check if this is a PyTorch model by looking for model.safetensors\n weight_path = os.path.join(checkpoint_dir, "model.safetensors")\n is_pytorch = os.path.exists(weight_path)\n""",
|
| 32 |
+
""" # Check if this is a PyTorch model by looking for either a monolithic\n # safetensors file or a sharded safetensors index.\n single_weight_path = os.path.join(checkpoint_dir, "model.safetensors")\n sharded_index_path = os.path.join(checkpoint_dir, "model.safetensors.index.json")\n if os.path.exists(single_weight_path):\n weight_path = single_weight_path\n elif os.path.exists(sharded_index_path):\n weight_path = sharded_index_path\n else:\n weight_path = single_weight_path\n is_pytorch = os.path.exists(single_weight_path) or os.path.exists(sharded_index_path)\n""",
|
| 33 |
+
"detect sharded safetensors checkpoints",
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
replace_or_exit(
|
| 37 |
+
model_file,
|
| 38 |
+
"""import abc\nfrom collections.abc import Sequence\nimport dataclasses\nimport enum\nimport logging\nimport pathlib\nfrom typing import Generic, TypeVar\n""",
|
| 39 |
+
"""import abc\nfrom collections.abc import Sequence\nimport dataclasses\nimport enum\nimport json\nimport logging\nimport pathlib\nfrom typing import Generic, TypeVar\n""",
|
| 40 |
+
"add json import",
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
replace_or_exit(
|
| 44 |
+
model_file,
|
| 45 |
+
""" def load_pytorch(self, train_config, weight_path: str):\n logger.info(f"train_config: {train_config}")\n model = pi0_pytorch.PI0Pytorch(config=train_config.model)\n safetensors.torch.load_model(model, weight_path)\n return model\n""",
|
| 46 |
+
""" def load_pytorch(self, train_config, weight_path: str):\n logger.info(f"train_config: {train_config}")\n model = pi0_pytorch.PI0Pytorch(config=train_config.model)\n\n weight_path_obj = pathlib.Path(weight_path)\n if weight_path_obj.name == "model.safetensors.index.json":\n if not weight_path_obj.exists():\n raise FileNotFoundError(f"Sharded index file not found at {weight_path_obj}")\n\n with weight_path_obj.open("r", encoding="utf-8") as f:\n index_data = json.load(f)\n\n weight_map = index_data.get("weight_map", {})\n if not isinstance(weight_map, dict) or not weight_map:\n raise ValueError(\n f"Invalid sharded checkpoint index at {weight_path_obj}: missing non-empty weight_map"\n )\n\n shard_names = sorted(set(weight_map.values()))\n missing_shards = [\n shard_name for shard_name in shard_names if not (weight_path_obj.parent / shard_name).exists()\n ]\n if missing_shards:\n raise FileNotFoundError(\n f"Missing safetensors shards under {weight_path_obj.parent}: {missing_shards}"\n )\n\n state_dict = {}\n for shard_name in shard_names:\n shard_path = weight_path_obj.parent / shard_name\n shard_state = safetensors.torch.load_file(str(shard_path))\n duplicated_keys = set(state_dict).intersection(shard_state)\n if duplicated_keys:\n raise ValueError(\n f"Duplicated tensor keys detected across shards: {sorted(duplicated_keys)[:10]}"\n )\n state_dict.update(shard_state)\n\n missing_keys, unexpected_keys = model.load_state_dict(state_dict, strict=False)\n if unexpected_keys:\n raise ValueError(\n f"Unexpected checkpoint keys when loading sharded safetensors: {unexpected_keys[:10]}"\n )\n if missing_keys:\n logger.warning(\n "Missing model keys when loading sharded safetensors (showing first 10): %s",\n missing_keys[:10],\n )\n else:\n safetensors.torch.load_model(model, str(weight_path_obj))\n\n return model\n""",
|
| 47 |
+
"load sharded safetensors index",
|
| 48 |
+
)
|
| 49 |
+
PY
|
| 50 |
+
|
| 51 |
+
echo "Patch applied successfully."
|
patch_walltime.sh
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
# Usage:
|
| 5 |
+
# bash apply_eval_custom_wall_time_patch.sh /path/to/dir/containing/eval_custom.py
|
| 6 |
+
# bash apply_eval_custom_wall_time_patch.sh /path/to/eval_custom.py
|
| 7 |
+
|
| 8 |
+
TARGET="${1:-.}"
|
| 9 |
+
if [[ -d "$TARGET" ]]; then
|
| 10 |
+
FILE="$TARGET/eval_custom.py"
|
| 11 |
+
else
|
| 12 |
+
FILE="$TARGET"
|
| 13 |
+
fi
|
| 14 |
+
|
| 15 |
+
if [[ ! -f "$FILE" ]]; then
|
| 16 |
+
echo "[ERROR] eval_custom.py not found: $FILE"
|
| 17 |
+
exit 1
|
| 18 |
+
fi
|
| 19 |
+
|
| 20 |
+
python3 - "$FILE" <<'PY'
|
| 21 |
+
import re
|
| 22 |
+
import sys
|
| 23 |
+
from pathlib import Path
|
| 24 |
+
|
| 25 |
+
path = Path(sys.argv[1])
|
| 26 |
+
text = path.read_text()
|
| 27 |
+
original = text
|
| 28 |
+
|
| 29 |
+
if 'metrics["time"]["wall_time"]' in text:
|
| 30 |
+
print(f"[INFO] Already patched: {path}")
|
| 31 |
+
sys.exit(0)
|
| 32 |
+
|
| 33 |
+
# 1) Initialize wall_time once per instance loop.
|
| 34 |
+
pat1 = r"(\n\s*done = False\n)(\s*if config\.write_video:)"
|
| 35 |
+
rep1 = r"\1 wall_time = 0.0\n\2"
|
| 36 |
+
text, n1 = re.subn(pat1, rep1, text, count=1)
|
| 37 |
+
|
| 38 |
+
# 2) Accumulate per-step wall time.
|
| 39 |
+
pat2 = (
|
| 40 |
+
r"(\n\s*time_start = time\.time\(\)\n"
|
| 41 |
+
r"\s*terminated, truncated, info = evaluator\.step\(\)\n"
|
| 42 |
+
r"\s*time_step = time\.time\(\) - time_start\n)"
|
| 43 |
+
)
|
| 44 |
+
rep2 = r"\1 wall_time += time_step\n"
|
| 45 |
+
text, n2 = re.subn(pat2, rep2, text, count=1)
|
| 46 |
+
|
| 47 |
+
# 3) Persist wall_time in metrics["time"].
|
| 48 |
+
pat3 = (
|
| 49 |
+
r"(\n\s*for metric in evaluator\.metrics:\n"
|
| 50 |
+
r"\s*metrics\.update\(metric\.gather_results\(\)\)\n)"
|
| 51 |
+
)
|
| 52 |
+
rep3 = r'\1 metrics["time"]["wall_time"] = wall_time\n'
|
| 53 |
+
text, n3 = re.subn(pat3, rep3, text, count=1)
|
| 54 |
+
|
| 55 |
+
if not (n1 == 1 and n2 == 1 and n3 == 1):
|
| 56 |
+
print("[ERROR] Patch failed: target code pattern not found (file may differ from expected).")
|
| 57 |
+
print(f"[DEBUG] replacements: n1={n1}, n2={n2}, n3={n3}")
|
| 58 |
+
sys.exit(2)
|
| 59 |
+
|
| 60 |
+
if text == original:
|
| 61 |
+
print(f"[INFO] No changes made: {path}")
|
| 62 |
+
sys.exit(0)
|
| 63 |
+
|
| 64 |
+
path.write_text(text)
|
| 65 |
+
print(f"[OK] Patched: {path}")
|
| 66 |
+
PY
|
run_dual_eval.sh
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
TASK_NAME="${TASK_NAME:-turning_on_radio}"
|
| 5 |
+
PATH_TO_CKPT="${PATH_TO_CKPT:-/opt/eval/models/cosmos-pi05-sft-pt12-20260203145532}"
|
| 6 |
+
CONDA_ROOT="${CONDA_ROOT:-/opt/miniconda3}"
|
| 7 |
+
CONDA_ENV="${CONDA_ENV:-behavior}"
|
| 8 |
+
OPENPI_DATA_HOME="${OPENPI_DATA_HOME:-/opt/openpi-cache}"
|
| 9 |
+
BASE_PORT="${BASE_PORT:-8000}"
|
| 10 |
+
EPISODES_PER_TASK="${EPISODES_PER_TASK:-10}"
|
| 11 |
+
EVAL_START="${EVAL_START:-0}"
|
| 12 |
+
EVAL_COUNT="${EVAL_COUNT:-10}"
|
| 13 |
+
NUM_GPU="${NUM_GPU:-1}"
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
LOG_DIR="${LOG_DIR:-/opt/eval/eval_output}"
|
| 17 |
+
mkdir -p "$OPENPI_DATA_HOME" "$LOG_DIR"
|
| 18 |
+
export OPENPI_DATA_HOME
|
| 19 |
+
|
| 20 |
+
echo "[INFO] task=$TASK_NAME gpus=$NUM_GPU eval_start=$EVAL_START eval_count=$EVAL_COUNT"
|
| 21 |
+
|
| 22 |
+
# Launch one openpi policy server per GPU
|
| 23 |
+
OPENPI_PIDS=()
|
| 24 |
+
for ((gpu = 0; gpu < NUM_GPU; gpu++)); do
|
| 25 |
+
(
|
| 26 |
+
cd /opt/eval/openpi-comet
|
| 27 |
+
CUDA_VISIBLE_DEVICES="$gpu" \
|
| 28 |
+
TASK_NAME="$TASK_NAME" \
|
| 29 |
+
PATH_TO_CKPT="$PATH_TO_CKPT" \
|
| 30 |
+
PORT="$((BASE_PORT + gpu))" \
|
| 31 |
+
bash /opt/eval/openpi-comet/eval_openpi.sh
|
| 32 |
+
) >"$LOG_DIR/openpi_gpu${gpu}.log" 2>&1 &
|
| 33 |
+
OPENPI_PIDS+=("$!")
|
| 34 |
+
done
|
| 35 |
+
|
| 36 |
+
# Run eval with episode wrapping
|
| 37 |
+
(
|
| 38 |
+
source "$CONDA_ROOT/etc/profile.d/conda.sh"
|
| 39 |
+
conda activate "$CONDA_ENV"
|
| 40 |
+
cd /opt/eval/BEHAVIOR-1K
|
| 41 |
+
|
| 42 |
+
_remaining=$EVAL_COUNT
|
| 43 |
+
_cursor=$EVAL_START
|
| 44 |
+
|
| 45 |
+
while (( _remaining > 0 )); do
|
| 46 |
+
_s=$((_cursor % EPISODES_PER_TASK))
|
| 47 |
+
_chunk=$((EPISODES_PER_TASK - _s))
|
| 48 |
+
(( _chunk > _remaining )) && _chunk=$_remaining
|
| 49 |
+
|
| 50 |
+
echo "[INFO] eval chunk: episodes ${_s}..$((_s + _chunk - 1)) (${_chunk} trials)"
|
| 51 |
+
|
| 52 |
+
TASK_NAME="$TASK_NAME" \
|
| 53 |
+
LOG_PATH="$LOG_DIR" \
|
| 54 |
+
NUM_GPU="$NUM_GPU" \
|
| 55 |
+
BASE_PORT="$BASE_PORT" \
|
| 56 |
+
EVAL_START_IDX="$_s" \
|
| 57 |
+
EVAL_COUNT="$_chunk" \
|
| 58 |
+
bash /opt/eval/BEHAVIOR-1K/eval_b1k.sh
|
| 59 |
+
|
| 60 |
+
_cursor=$((_cursor + _chunk))
|
| 61 |
+
_remaining=$((_remaining - _chunk))
|
| 62 |
+
done
|
| 63 |
+
) >"$LOG_DIR/behavior_eval.log" 2>&1 &
|
| 64 |
+
B1K_PID=$!
|
| 65 |
+
|
| 66 |
+
wait "$B1K_PID" || true
|
| 67 |
+
for pid in "${OPENPI_PIDS[@]}"; do
|
| 68 |
+
kill "$pid" 2>/dev/null || true
|
| 69 |
+
wait "$pid" || true
|
| 70 |
+
done
|
| 71 |
+
|
| 72 |
+
echo "[INFO] done."
|
tokenizer.model
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8986bb4f423f07f8c7f70d0dbe3526fb2316056c17bae71b1ea975e77a168fc6
|
| 3 |
+
size 4264023
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"tokenizer_class": "PaligemmaTokenizer",
|
| 3 |
+
"max_len": 200,
|
| 4 |
+
"auto_map": {
|
| 5 |
+
"AutoTokenizer": ["tokenizer_pi05.PaligemmaTokenizer", null]
|
| 6 |
+
}
|
| 7 |
+
}
|