From 56a8daf814c706621c0930c05194536ad1bed327 Mon Sep 17 00:00:00 2001 From: AIWintremuteAI Date: Tue, 7 Jul 2026 23:16:42 +0200 Subject: [PATCH 1/2] eval in docker --- docs/DOCKER.md | 189 ++++++++++++++++++++++++++++++++++++++++ eval/Dockerfile.client | 126 +++++++++++++++++++++++++++ eval/docker-compose.yml | 78 +++++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 docs/DOCKER.md create mode 100644 eval/Dockerfile.client create mode 100644 eval/docker-compose.yml diff --git a/docs/DOCKER.md b/docs/DOCKER.md new file mode 100644 index 0000000..efda53b --- /dev/null +++ b/docs/DOCKER.md @@ -0,0 +1,189 @@ +# Docker evaluation workflow for vla.cpp + +This document describes the Docker Compose evaluation stack, which runs the +vla.cpp inference server and the Python simulation client in separate +containers. + +| Container | Image | Purpose | +|-----------|-------|---------| +| `server` | upstream `Dockerfile` | C++ `vla-server` daemon (CUDA or CPU) | +| `client` | `eval/Dockerfile.client` | Python simulation environment (MuJoCo, robosuite, lerobot) | + +--- + +## Quick start + +### Prerequisites + +- [Docker Compose](https://docs.docker.com/compose/) v2.24+ +- NVIDIA GPU with proprietary driver ≥ 535. GPU access uses **CDI** + (`devices: - nvidia.com/gpu=all`) — no `nvidia-container-toolkit` needed. + See [CUDA GPU access](#cuda-gpu-access) for details. + +### 1. Download model GGUF files + +```bash +docker compose -f eval/docker-compose.yml build client +docker compose -f eval/docker-compose.yml run --no-deps --rm client \ + huggingface-cli download vrfai/smolvla-libero-gguf --local-dir /models +``` + +> `--no-deps` skips building the server image, which isn't needed for downloads. + +Models are mounted into both containers at `/models`. + +### 2. Build the images + +```bash +docker compose -f eval/docker-compose.yml build +``` + +Build args accepted by the server `Dockerfile`: + +| Arg | Default | Notes | +|-----|---------|-------| +| `BACKEND` | `cuda` | `cuda` or `cpu` | +| `CUDA_ARCH` | `120` | Blackwell; `89` for RTX40, `87` for Orin, `86` for RTX30 | +| `BASE_IMAGE` | `nvidia/cuda:12.9.1-devel-ubuntu24.04` | — | +| `JOBS` | `nproc` | Lower if nvcc segfaults on flash-attn kernels | + +Override via e.g. `docker compose -f eval/docker-compose.yml build --build-arg CUDA_ARCH=89 server`. + +### 3. Start the server + +```bash +docker compose -f eval/docker-compose.yml up -d server +docker compose -f eval/docker-compose.yml logs server +# … vla-server: bound to tcp://*:5555. ready. +``` + +The default `command` in `eval/docker-compose.yml` starts SmolVLA for LIBERO. +For other models (e.g. GR00T-N1.7, no mmproj needed): + +```bash +docker compose -f eval/docker-compose.yml run --rm server \ + --bind tcp://*:5555 /models/gr00tn1d7-libero.gguf +``` + +### 4. Run an evaluation episode + +```bash +docker compose -f eval/docker-compose.yml run --rm client \ + python eval/client/run_sim_client_direct.py \ + --task libero_object --task-id 0 --n-episodes 1 \ + --output-dir /tmp/libero_outputs --arch smolvla \ + --vla-addr tcp://server:5555 +``` + +Or drop into an interactive shell: + +```bash +docker compose -f eval/docker-compose.yml run --rm client +root@...:/workspace/vla.cpp# python eval/client/run_sim_client_direct.py \ + --task libero_object --task-id 0 --n-episodes 1 \ + --output-dir /tmp/libero_outputs --arch smolvla \ + --vla-addr tcp://server:5555 +``` + +Results (videos, summary) are written to `/tmp/libero_outputs` on the host. + +**Example output (RTX 5060 Ti, CUDA arch 120):** + +``` +vla-cpp-direct[arch=smolvla]: connected to tcp://server:5555 +- Step 220: reward=1.00, done=True, truncated=False +- Episode finished after 220 steps. Final reward: 1.00 +- Success rate: 100.00% (1/1) +- Average inference time per step: 116.45 ms +``` + +--- + +## Configuration reference + +### Volumes + +| Host / Volume | Container mount | Purpose | +|---------------|----------------|---------| +| `/tmp/smolvla-models` | `client:/models` (rw), `server:/models:ro` | GGUF model files | +| `/tmp/libero_outputs` | `client:/tmp/libero_outputs` | Eval videos & summaries | +| `hf-cache` (named) | `client:/root/.cache/huggingface` | HuggingFace tokenizer cache | + +### Ports + +| Service | Host | Container | +|---------|------|-----------| +| server | `5555` | `5555` | + +### Network + +Both services share the default Compose network. The client reaches the server +via hostname `server`. + +### CUDA GPU access + +The server uses CDI (`devices: - nvidia.com/gpu=all`). This works without +`nvidia-container-toolkit` as long as: +1. The NVIDIA proprietary driver is installed (≥ 535). +2. A CDI-enabled container runtime is available (containerd ≥ 1.7, + cri-o ≥ 1.29, or Docker with `nvidia-ctk` from `nvidia-container-toolkit` + ≥ 1.15 to generate `/etc/cdi/nvidia.yaml`). + +--- + +## Running without Docker Compose + +### Server only + +```bash +docker build -t vla-cpp-server \ + --build-arg BACKEND=cuda --build-arg CUDA_ARCH=120 . + +# CDI +docker run --rm --device nvidia.com/gpu=all -p5555:5555 \ + -v /tmp/smolvla-models:/models:ro \ + vla-cpp-server --bind tcp://*:5555 /models/model.gguf + +# nvidia-container-toolkit +docker run --rm --gpus all -p5555:5555 \ + -v /tmp/smolvla-models:/models:ro \ + vla-cpp-server --bind tcp://*:5555 /models/model.gguf +``` + +### Client only + +```bash +docker build -t vla-cpp-client -f eval/Dockerfile.client . +docker run --rm -it --network host \ + -v /tmp/libero_outputs:/tmp/libero_outputs \ + vla-cpp-client +# Inside: connect to server at localhost:5555 +``` + +--- + +## Known issues + +| Issue | Workaround | +|-------|-----------| +| `Unsupported gpu architecture 'compute_120'` with CUDA < 12.8 | Use CUDA 12.8+ for `sm_120`, or set `CUDA_ARCH=89` for RTX40-series compatibility | +| NumPy 2.x: `module 'numpy' has no attribute 'core'` | `Dockerfile.client` pins `numpy==1.26.4` and patches accelerate | +| `lerobot` pulls GPU torch | `Dockerfile.client` re-pins `torch==2.5.1` (CPU) after installing lerobot | +| LIBERO data files not found | Editable install (`-e`) keeps `bddl_files/` / `init_files/` / `assets/` accessible at runtime | +| LIBERO hangs on first import (dataset path prompt) | `echo "N" \| python3 -c "import libero.libero"` pre-seeds `~/.libero/config.yaml` | +| `pandas` segfaults on import | Pin `pandas==2.0.3` (last NumPy 1.x-compatible release) | +| MuJoCo 3.x: robosuite init fails | Pin `mujoco<3.0` (2.3.7 known-good) | +| `nvidia-container-toolkit` not installed | Use CDI (`devices: - nvidia.com/gpu=all`) instead of `runtime: nvidia` | + +--- + +## Summary + +The Docker Compose evaluation stack provides a reproducible two-container +workflow for vla.cpp: + +1. **Server** — upstream `Dockerfile`, compiles `vla-server` with GPU support. +2. **Client** — `eval/Dockerfile.client`, Python simulation stack with pinned + dependency versions (NumPy 1.x, MuJoCo 2.x, Pandas 2.0.x). +3. **CDI** eliminates the `nvidia-container-toolkit` dependency for GPU access. +4. **First-step overhead** (~35 s CUDA graph warmup) occurs once per process. diff --git a/eval/Dockerfile.client b/eval/Dockerfile.client new file mode 100644 index 0000000..379ec1d --- /dev/null +++ b/eval/Dockerfile.client @@ -0,0 +1,126 @@ +# vla.cpp evaluation client container. +# +# Contains the Python simulation environment (MuJoCo, robosuite, lerobot) and +# the eval scripts needed to drive vla-server from a LIBERO / SimplerEnv +# episode. No CUDA, no C++ build — this is purely a Python runtime. +# +# Usage (with the upstream server Dockerfile): +# +# # Terminal 1 — build & start the server: +# docker build -t vla-cpp-server . # upstream Dockerfile +# docker run --gpus all -p5555:5555 -v $PWD/models:/models \ +# vla-cpp-server --bind tcp://*:5555 /models/model.gguf +# +# # Terminal 2 — build & run the client: +# docker build -t vla-cpp-client -f eval/Dockerfile.client . +# docker run --rm -it --network host \ +# -v /tmp/libero_outputs:/tmp/libero_outputs \ +# vla-cpp-client +# root@...:/workspace/vla.cpp# python eval/client/run_sim_client_direct.py \ +# --task libero_object --task-id 0 --n-episodes 1 \ +# --output-dir /tmp/libero_outputs --arch smolvla \ +# --vla-addr tcp://localhost:5555 +# +# Or with docker-compose (see eval/docker-compose.yml). + +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive \ + TZ=UTC \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python \ + VLA_CPP_PROTO=/workspace/vla.cpp/src/serving/vla.proto + +# System dependencies: build tools, protobuf, ZMQ, EGL (for MuJoCo offscreen) +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + git \ + curl \ + ca-certificates \ + libzmq3-dev \ + libprotobuf-dev \ + protobuf-compiler \ + python3.10 \ + python3.10-venv \ + python3.10-dev \ + python3-pip \ + libegl-dev \ + && rm -rf /var/lib/apt/lists/* + +# Make python3.10 the default +RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1 && \ + ln -sf /usr/bin/python3 /usr/local/bin/python +RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10 + +WORKDIR /workspace/vla.cpp +COPY . . + +# --------------------------------------------------------------------------- +# Python dependencies — order matters to avoid version conflicts +# --------------------------------------------------------------------------- + +# Pin foundational deps first so nothing pulls numpy 2.x or mujoco 3.x +RUN pip3 install --no-cache-dir numpy==1.26.4 +RUN pip3 install --no-cache-dir "mujoco<3.0" + +# PyTorch CPU-only (the server handles GPU inference) +RUN pip3 install --no-cache-dir torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu +RUN pip3 install --no-cache-dir torchvision==0.20.1 --index-url https://download.pytorch.org/whl/cpu + +# LIBERO — clone and install. +# We use editable install (following eval/sim/libero/setup_libero.sh) so that +# the source tree with bddl_files/, init_files/, assets/ stays accessible at +# runtime. The first import seeds ~/.libero/config.yaml via the script's +# "echo N" trick, avoiding the interactive dataset-path prompt. +# +# The CMAKE_POLICY_VERSION_MINIMUM env-var is needed by egl-probe (a transitive +# dep of robomimic/robosuite) which requests cmake_minimum_required < 3.5. +RUN CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install --no-cache-dir --upgrade pip setuptools && \ + git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git /tmp/LIBERO && \ + pip3 install --no-cache-dir -r /tmp/LIBERO/requirements.txt && \ + CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install --no-cache-dir \ + -e /tmp/LIBERO --config-settings editable_mode=compat && \ + rm -rf /root/.libero && \ + echo "N" | python3 -c "import libero.libero" 2>/dev/null || true + +# lerobot — install with dependencies but immediately re-pin torch so it is +# not upgraded from our pinned CPU-only version. +RUN pip3 install --no-cache-dir lerobot==0.4.3 && \ + pip3 install --no-cache-dir torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu && \ + pip3 install --no-cache-dir torchvision==0.20.1 --index-url https://download.pytorch.org/whl/cpu + +# Remaining client dependencies +RUN pip3 install --no-cache-dir \ + transformers==4.51.3 \ + gymnasium==0.29.1 \ + zmq \ + msgpack==1.1.0 \ + msgpack-numpy==0.4.8 \ + pillow \ + imageio \ + tqdm \ + pydantic \ + av \ + tianshou==0.5.1 \ + tyro \ + pandas==2.0.3 \ + dm_tree \ + einops==0.8.1 \ + albumentations==1.4.18 \ + pyarrow==12.0.1 \ + diffusers==0.30.1 \ + huggingface-hub + +# Re-pin numpy to 1.x — later deps (albumentations, tianshou, etc.) pull in 2.x +RUN pip3 install --no-cache-dir numpy==1.26.4 + +# Apply the accelerate monkey-patch for numpy compat +RUN sed -i 's/np_core = np._core if is_numpy_available("2.0.0") else np.core/np_core = np.core/' \ + /usr/local/lib/python3.10/dist-packages/accelerate/utils/other.py 2>/dev/null || true + +# Clean up +RUN rm -rf /root/.cache/pip + +CMD ["bash"] diff --git a/eval/docker-compose.yml b/eval/docker-compose.yml new file mode 100644 index 0000000..30a2816 --- /dev/null +++ b/eval/docker-compose.yml @@ -0,0 +1,78 @@ +# vla.cpp two-container evaluation stack. +# +# server — vla-server (built with the upstream Dockerfile) +# client — Python simulation environment (eval/Dockerfile.client) +# +# Usage: +# docker compose -f eval/docker-compose.yml build # builds both images +# docker compose -f eval/docker-compose.yml up -d server # start server +# docker compose -f eval/docker-compose.yml run --rm client # interactive shell +# +# Inside the client shell: +# python eval/client/run_sim_client_direct.py \ +# --task libero_object --task-id 0 --n-episodes 1 \ +# --output-dir /tmp/libero_outputs --arch smolvla \ +# --vla-addr tcp://server:5555 +# +# The server is reachable at hostname "server" (Docker Compose DNS). + +services: + + # -------------------------------------------------------------------------- + # vla-server — C++ inference daemon (upstream Dockerfile) + # Build args: + # BACKEND=cuda|cpu (default: cuda) + # CUDA_ARCH (default: 120, use 89 for RTX40, 87 for Orin, etc.) + # -------------------------------------------------------------------------- + server: + build: + context: .. + dockerfile: Dockerfile + args: + BACKEND: cuda + CUDA_ARCH: "120" + image: vla-cpp-server + container_name: vla-cpp-server + devices: + - nvidia.com/gpu=all # CDI + volumes: + # Mount GGUF model files (read-only) + - /tmp/smolvla-models:/models:ro + environment: + - CUDA_VISIBLE_DEVICES=0 + ports: + - "5555:5555" + # For SmolVLA / π0 pass mmproj + model GGUF. + # For baked-in-vision models (BitVLA, GR00T, Evo-1) omit mmproj. + command: + - --bind + - tcp://*:5555 + - /models/mmproj-smolvla-libero.gguf + - /models/smolvla-libero.gguf + + # -------------------------------------------------------------------------- + # Client — Python simulation environment (eval/Dockerfile.client) + # -------------------------------------------------------------------------- + client: + build: + context: .. + dockerfile: eval/Dockerfile.client + image: vla-cpp-client + container_name: vla-cpp-client + stdin_open: true + tty: true + depends_on: + - server + volumes: + # Output directory for eval videos / summaries + - /tmp/libero_outputs:/tmp/libero_outputs + # Model download destination (also used by server) + - /tmp/smolvla-models:/models + # Cache for HuggingFace tokenizers etc. + - hf-cache:/root/.cache/huggingface + environment: + - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python + - VLA_CPP_PROTO=/workspace/vla.cpp/src/serving/vla.proto + +volumes: + hf-cache: From df8e2db48c896930d24a774f5b5cc788c61a95e1 Mon Sep 17 00:00:00 2001 From: AIWintremuteAI Date: Thu, 16 Jul 2026 21:43:14 +0200 Subject: [PATCH 2/2] updated and optimized docker-compose.yml and DOCKER.md to reflect the changes --- .dockerignore | 6 ++- docs/DOCKER.md | 117 ++++++++++++++++++++++++++++++++++++---- eval/Dockerfile.client | 29 +++++----- eval/docker-compose.yml | 4 +- 4 files changed, 128 insertions(+), 28 deletions(-) diff --git a/.dockerignore b/.dockerignore index 9354afc..7e9ae1d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,5 +6,9 @@ build/ build-*/ outputs/ third_party/ -eval/sim/ +# Clone targets and venvs (large, runtime-only) +eval/sim/libero/LIBERO/ +eval/sim/libero/libero_uv/ +eval/sim/simpler/SimplerEnv/ +eval/sim/simpler/simpler_uv/ *.gguf diff --git a/docs/DOCKER.md b/docs/DOCKER.md index efda53b..80dd488 100644 --- a/docs/DOCKER.md +++ b/docs/DOCKER.md @@ -2,16 +2,20 @@ This document describes the Docker Compose evaluation stack, which runs the vla.cpp inference server and the Python simulation client in separate -containers. +containers. The stack supports both **CUDA GPU** and **CPU-only** deployments. | Container | Image | Purpose | |-----------|-------|---------| -| `server` | upstream `Dockerfile` | C++ `vla-server` daemon (CUDA or CPU) | -| `client` | `eval/Dockerfile.client` | Python simulation environment (MuJoCo, robosuite, lerobot) | +| `server` | root `Dockerfile` | C++ `vla-server` daemon (CUDA or CPU) | +| `client` | `eval/Dockerfile.client` | Python simulation environment (MuJoCo, LIBERO / SimplerEnv) | + +> **Source of truth**: For model details, supported architectures, and +> benchmark numbers, refer to the top-level [README.md](../README.md). +> This document covers the Docker-specific evaluation workflow only. --- -## Quick start +## Quick start (CUDA GPU) ### Prerequisites @@ -25,10 +29,11 @@ containers. ```bash docker compose -f eval/docker-compose.yml build client docker compose -f eval/docker-compose.yml run --no-deps --rm client \ - huggingface-cli download vrfai/smolvla-libero-gguf --local-dir /models + hf download vrfai/smolvla-libero-gguf --local-dir /models ``` > `--no-deps` skips building the server image, which isn't needed for downloads. +> Each model ships as a single self-contained GGUF — no separate `mmproj` file. Models are mounted into both containers at `/models`. @@ -44,7 +49,7 @@ Build args accepted by the server `Dockerfile`: |-----|---------|-------| | `BACKEND` | `cuda` | `cuda` or `cpu` | | `CUDA_ARCH` | `120` | Blackwell; `89` for RTX40, `87` for Orin, `86` for RTX30 | -| `BASE_IMAGE` | `nvidia/cuda:12.9.1-devel-ubuntu24.04` | — | +| `BASE_IMAGE` | `nvidia/cuda:12.9.1-devel-ubuntu24.04` | Overridden automatically for CPU | | `JOBS` | `nproc` | Lower if nvcc segfaults on flash-attn kernels | Override via e.g. `docker compose -f eval/docker-compose.yml build --build-arg CUDA_ARCH=89 server`. @@ -58,14 +63,18 @@ docker compose -f eval/docker-compose.yml logs server ``` The default `command` in `eval/docker-compose.yml` starts SmolVLA for LIBERO. -For other models (e.g. GR00T-N1.7, no mmproj needed): +For other models (e.g. GR00T-N1.7): ```bash docker compose -f eval/docker-compose.yml run --rm server \ --bind tcp://*:5555 /models/gr00tn1d7-libero.gguf ``` -### 4. Run an evaluation episode +> **π0 note**: π0 needs a separate `mmproj` vision GGUF. Pass both files: +> `--bind tcp://*:5555 /models/mmproj-....gguf /models/ckpt.gguf`. +> See the [README model table](../README.md#models) for details. + +### 4. Run a LIBERO evaluation episode ```bash docker compose -f eval/docker-compose.yml run --rm client \ @@ -99,6 +108,77 @@ vla-cpp-direct[arch=smolvla]: connected to tcp://server:5555 --- +## Quick start (CPU-only, no GPU) + +On machines without an NVIDIA GPU, +build and run the server image with `BACKEND=cpu`: + +### 1. Build the server image for CPU + +```bash +docker build -t vla-cpp-cpu \ + --build-arg BACKEND=cpu \ + --build-arg BASE_IMAGE=ubuntu:24.04 . +``` + +### 2. Download the model + +```bash +docker build -t vla-cpp-client -f eval/Dockerfile.client . +docker run --rm -v /tmp/smolvla-models:/models vla-cpp-client \ + hf download vrfai/smolvla-libero-gguf --local-dir /models +``` + +### 3. Start the server + +```bash +docker run -d --name vla-cpp-server -p 5555:5555 \ + -v /tmp/smolvla-models:/models:ro \ + vla-cpp-cpu --bind tcp://*:5555 /models/smolvla-libero.gguf +``` + +Verify with `docker logs vla-cpp-server` — look for `vla-server: bound to tcp://*:5555. ready.` + +### 4. Run a LIBERO evaluation episode + +```bash +docker run --rm --network host \ + -v /tmp/smolvla-models:/models \ + -v /tmp/libero_outputs:/tmp/libero_outputs \ + vla-cpp-client \ + python eval/client/run_sim_client_direct.py \ + --task libero_object --task-id 0 --n-episodes 1 \ + --output-dir /tmp/libero_outputs --arch smolvla \ + --vla-addr tcp://localhost:5555 +``` + +> CPU inference is significantly slower than GPU (e.g. ~888 ms/step on Apple M4 +> vs ~113 ms/step on RTX 3090 for SmolVLA). Expect multi-minute episodes. + +--- + +## Supported simulators + +The Docker client image supports both simulators wired through the eval scaffold: + +| Simulator | Supported arches | Setup script | +|-----------|-----------------|-------------| +| **LIBERO** | smolvla, pi0, pi05, gr00t_n1_5, gr00t_n1_6, gr00t_n1_7, bitvla, evo1, openvla_oft, vla_adapter, vla_jepa | `eval/sim/libero/setup_libero.sh` | +| **SimplerEnv** | gr00t_n1_6 | `eval/sim/simpler/setup_SimplerEnv.sh` | + +### SimplerEnv example + +```bash +docker compose -f eval/docker-compose.yml run --rm client \ + python eval/client/run_simpler_client_direct.py \ + --arch gr00t_n1_6 \ + --task-id oxe_widowx/widowx_spoon_on_towel --n-episodes 1 \ + --embodiment oxe_widowx --image-size 252 \ + --stats-json /models/dataset_statistics.json +``` + +--- + ## Configuration reference ### Volumes @@ -133,7 +213,7 @@ The server uses CDI (`devices: - nvidia.com/gpu=all`). This works without ## Running without Docker Compose -### Server only +### Server only (GPU) ```bash docker build -t vla-cpp-server \ @@ -150,11 +230,24 @@ docker run --rm --gpus all -p5555:5555 \ vla-cpp-server --bind tcp://*:5555 /models/model.gguf ``` +### Server only (CPU) + +```bash +docker build -t vla-cpp-cpu \ + --build-arg BACKEND=cpu \ + --build-arg BASE_IMAGE=ubuntu:24.04 . + +docker run --rm -p5555:5555 \ + -v /tmp/smolvla-models:/models:ro \ + vla-cpp-cpu --bind tcp://*:5555 /models/model.gguf +``` + ### Client only ```bash docker build -t vla-cpp-client -f eval/Dockerfile.client . docker run --rm -it --network host \ + -v /tmp/smolvla-models:/models \ -v /tmp/libero_outputs:/tmp/libero_outputs \ vla-cpp-client # Inside: connect to server at localhost:5555 @@ -174,6 +267,7 @@ docker run --rm -it --network host \ | `pandas` segfaults on import | Pin `pandas==2.0.3` (last NumPy 1.x-compatible release) | | MuJoCo 3.x: robosuite init fails | Pin `mujoco<3.0` (2.3.7 known-good) | | `nvidia-container-toolkit` not installed | Use CDI (`devices: - nvidia.com/gpu=all`) instead of `runtime: nvidia` | +| CPU-only: no GPU available | Use `BACKEND=cpu` build arg and `BASE_IMAGE=ubuntu:24.04` instead of CUDA base | --- @@ -182,8 +276,9 @@ docker run --rm -it --network host \ The Docker Compose evaluation stack provides a reproducible two-container workflow for vla.cpp: -1. **Server** — upstream `Dockerfile`, compiles `vla-server` with GPU support. +1. **Server** — upstream `Dockerfile`, compiles `vla-server` with GPU or CPU backend. 2. **Client** — `eval/Dockerfile.client`, Python simulation stack with pinned dependency versions (NumPy 1.x, MuJoCo 2.x, Pandas 2.0.x). 3. **CDI** eliminates the `nvidia-container-toolkit` dependency for GPU access. -4. **First-step overhead** (~35 s CUDA graph warmup) occurs once per process. +4. **CPU-only** mode works without any GPU — use `BACKEND=cpu` build arg. +5. **First-step overhead** (~35 s CUDA graph warmup) occurs once per process (GPU only). \ No newline at end of file diff --git a/eval/Dockerfile.client b/eval/Dockerfile.client index 379ec1d..6f6e86d 100644 --- a/eval/Dockerfile.client +++ b/eval/Dockerfile.client @@ -62,12 +62,13 @@ COPY . . # --------------------------------------------------------------------------- # Pin foundational deps first so nothing pulls numpy 2.x or mujoco 3.x -RUN pip3 install --no-cache-dir numpy==1.26.4 -RUN pip3 install --no-cache-dir "mujoco<3.0" +RUN pip3 install numpy==1.26.4 +RUN pip3 install "mujoco<3.0" # PyTorch CPU-only (the server handles GPU inference) -RUN pip3 install --no-cache-dir torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu -RUN pip3 install --no-cache-dir torchvision==0.20.1 --index-url https://download.pytorch.org/whl/cpu +# install it now to prevent later deps from pulling in a GPU version +RUN pip3 install torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu +RUN pip3 install torchvision==0.20.1 --index-url https://download.pytorch.org/whl/cpu # LIBERO — clone and install. # We use editable install (following eval/sim/libero/setup_libero.sh) so that @@ -77,22 +78,22 @@ RUN pip3 install --no-cache-dir torchvision==0.20.1 --index-url https://download # # The CMAKE_POLICY_VERSION_MINIMUM env-var is needed by egl-probe (a transitive # dep of robomimic/robosuite) which requests cmake_minimum_required < 3.5. -RUN CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install --no-cache-dir --upgrade pip setuptools && \ - git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git /tmp/LIBERO && \ - pip3 install --no-cache-dir -r /tmp/LIBERO/requirements.txt && \ - CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install --no-cache-dir \ +RUN CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install --upgrade pip setuptools +RUN git clone --depth 1 https://github.com/Lifelong-Robot-Learning/LIBERO.git /tmp/LIBERO +RUN CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install -r /tmp/LIBERO/requirements.txt +RUN CMAKE_POLICY_VERSION_MINIMUM=3.5 pip3 install \ -e /tmp/LIBERO --config-settings editable_mode=compat && \ rm -rf /root/.libero && \ echo "N" | python3 -c "import libero.libero" 2>/dev/null || true # lerobot — install with dependencies but immediately re-pin torch so it is # not upgraded from our pinned CPU-only version. -RUN pip3 install --no-cache-dir lerobot==0.4.3 && \ - pip3 install --no-cache-dir torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu && \ - pip3 install --no-cache-dir torchvision==0.20.1 --index-url https://download.pytorch.org/whl/cpu +RUN pip3 install lerobot==0.4.3 && \ + pip3 install torch==2.5.1 --index-url https://download.pytorch.org/whl/cpu && \ + pip3 install torchvision==0.20.1 --index-url https://download.pytorch.org/whl/cpu # Remaining client dependencies -RUN pip3 install --no-cache-dir \ +RUN pip3 install \ transformers==4.51.3 \ gymnasium==0.29.1 \ zmq \ @@ -114,13 +115,13 @@ RUN pip3 install --no-cache-dir \ huggingface-hub # Re-pin numpy to 1.x — later deps (albumentations, tianshou, etc.) pull in 2.x -RUN pip3 install --no-cache-dir numpy==1.26.4 +RUN pip3 install numpy==1.26.4 # Apply the accelerate monkey-patch for numpy compat RUN sed -i 's/np_core = np._core if is_numpy_available("2.0.0") else np.core/np_core = np.core/' \ /usr/local/lib/python3.10/dist-packages/accelerate/utils/other.py 2>/dev/null || true -# Clean up +# Clean up pip cache to keep image size small RUN rm -rf /root/.cache/pip CMD ["bash"] diff --git a/eval/docker-compose.yml b/eval/docker-compose.yml index 30a2816..cf7d5be 100644 --- a/eval/docker-compose.yml +++ b/eval/docker-compose.yml @@ -42,12 +42,12 @@ services: - CUDA_VISIBLE_DEVICES=0 ports: - "5555:5555" - # For SmolVLA / π0 pass mmproj + model GGUF. + # For SmolVLA the single GGUF is enough. + # For π0 pass mmproj + model GGUF. # For baked-in-vision models (BitVLA, GR00T, Evo-1) omit mmproj. command: - --bind - tcp://*:5555 - - /models/mmproj-smolvla-libero.gguf - /models/smolvla-libero.gguf # --------------------------------------------------------------------------