Skip to content

Commit dce4e6b

Browse files
dwhiteddsoftclaude
andcommitted
fix(gpu-offload): replace LeRobot git submodule with pinned PyPI dependency
Address PR review feedback that the vendored LeRobot submodule costs ~403 MiB to initialize (git history + worktree) while the Docker build never patches the source. Since lerobot==0.6.1 is published on PyPI with all required entry points, depend on it directly via pyproject.toml/uv.lock instead of vendoring the repository. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 7cab2c6 commit dce4e6b

11 files changed

Lines changed: 3329 additions & 121 deletions

File tree

.gitmodules

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
.git
2-
.gitmodules
32
**/.git
43
**/.git/**
54
**/__pycache__
65
**/*.pyc
76
data
87
outputs
9-
upstream/.venv
10-
upstream/docs
11-
upstream/tests
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
LEROBOT_REPO=https://github.com/huggingface/lerobot.git
2-
LEROBOT_REF=v0.6.1
1+
LEROBOT_VERSION=0.6.1

gpu-offload/examples/so101-real-hardware/README.md

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,10 @@ ms.date: 2026-08-26
55
---
66

77
This example packages a pinned
8-
[LeRobot](https://github.com/huggingface/lerobot) checkout for SO-101 episode
8+
[LeRobot](https://github.com/huggingface/lerobot) release for SO-101 episode
99
collection, fine-tuning, evaluation, and rollout. The image builds for both
1010
`linux/amd64` and `linux/arm64` and includes the Xavier remoting runtime.
1111

12-
## 📋 Initialize
13-
14-
Initialize the pinned LeRobot submodule after cloning:
15-
16-
```bash
17-
git submodule update --init --recursive \
18-
gpu-offload/examples/so101-real-hardware/upstream
19-
```
20-
21-
The exact commit is stored by the Git submodule reference. `.lerobot-version` records
22-
the requested upstream tag, branch, or commit used by image tags and scripts.
23-
2412
## 📦 Build the image
2513

2614
Build and load an image for the host architecture:
@@ -42,19 +30,21 @@ The amd64 image uses the CUDA-enabled PyTorch version from LeRobot's lock file.
4230
The arm64 image replaces it with CUDA 13 wheels required by NVIDIA Thor. The
4331
build reads the remoting package directly from `gpu-offload/runtime` through a
4432
BuildKit named context, so the image always contains the runtime from the same
45-
checkout.
33+
checkout. LeRobot itself is installed from the pinned
34+
[`lerobot`](https://pypi.org/project/lerobot/) PyPI package declared in
35+
`pyproject.toml` and locked in `uv.lock`.
4636

4737
## 🔄 Update LeRobot
4838

49-
Update only to an explicit reviewed tag, branch, or commit:
39+
Update only to an explicit reviewed release:
5040

5141
```bash
52-
./scripts/update_upstream.sh v0.6.2
42+
./scripts/update_lerobot_version.sh 0.6.2
5343
```
5444

55-
The script updates `upstream/` and `.lerobot-version`. Review the upstream
56-
release notes, rebuild both architectures, run the workflows you use, and then
57-
commit both changed paths.
45+
The script updates `pyproject.toml`, `uv.lock`, and `.lerobot-version`. Review
46+
the release notes, rebuild both architectures, run the workflows you use, and
47+
then commit the changed paths.
5848

5949
## ⚙️ Configure SO-101
6050

@@ -199,7 +189,7 @@ Move image conversion and the policy processor pipeline to the offload server:
199189
This mode sends compact `uint8` camera tensors instead of normalized `float32`
200190
tensors. The example-layer implementation in
201191
`docker/raw_observation_inference.py` moves image preparation and the policy
202-
processor pipeline to the server without changing the pinned LeRobot submodule.
192+
processor pipeline to the server without changing the pinned LeRobot package.
203193
It demonstrates an optional optimization that requires only a small integration
204194
wrapper when transparent method offload does not provide enough throughput.
205195
This mode applies only to synchronous inference and is disabled by default.

gpu-offload/examples/so101-real-hardware/docker/Dockerfile

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
4141

4242
WORKDIR /opt/lerobot
4343

44-
COPY --chown=lerobot:lerobot upstream/setup.py upstream/pyproject.toml \
45-
upstream/uv.lock upstream/README.md upstream/MANIFEST.in ./
44+
COPY --chown=lerobot:lerobot pyproject.toml uv.lock ./
4645

4746
RUN chown lerobot:lerobot /opt/lerobot
4847

4948
USER lerobot
5049

51-
RUN uv sync --locked \
52-
--extra core_scripts \
53-
--extra feetech \
54-
--extra training \
55-
--extra evaluation \
56-
--extra smolvla \
57-
--extra pusht \
58-
--no-install-project \
59-
--no-cache
60-
61-
COPY --chown=lerobot:lerobot upstream/ ./
62-
63-
RUN uv sync --locked \
64-
--extra core_scripts \
65-
--extra feetech \
66-
--extra training \
67-
--extra evaluation \
68-
--extra smolvla \
69-
--extra pusht \
70-
--no-cache
50+
RUN uv sync --locked --no-cache
7151

7252
USER root
7353

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[project]
2+
name = "lerobot-so101-runtime"
3+
version = "0.1.0"
4+
description = "Pinned LeRobot dependency lock for the SO-101 GPU-offload example image"
5+
requires-python = ">=3.12"
6+
dependencies = [
7+
"lerobot[core-scripts,feetech,training,evaluation,smolvla,pusht]==0.6.1",
8+
]

gpu-offload/examples/so101-real-hardware/scripts/common.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ require_positive_integer() {
6262

6363
pinned_version() {
6464
local version
65-
version="$(sed -n 's/^LEROBOT_REF=//p' "${LEROBOT_DIR}/.lerobot-version")"
66-
[[ -n "${version}" ]] || die "LEROBOT_REF is missing from ${LEROBOT_DIR}/.lerobot-version"
65+
version="$(sed -n 's/^LEROBOT_VERSION=//p' "${LEROBOT_DIR}/.lerobot-version")"
66+
[[ -n "${version}" ]] || die "LEROBOT_VERSION is missing from ${LEROBOT_DIR}/.lerobot-version"
6767
printf '%s\n' "${version#v}"
6868
}
6969

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env bash
2+
# Copyright (c) Microsoft Corporation.
3+
# SPDX-License-Identifier: MIT
4+
#
5+
# Update the pinned LeRobot PyPI package version.
6+
7+
set -euo pipefail
8+
9+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
10+
readonly SCRIPT_DIR
11+
# shellcheck source=common.sh
12+
source "${SCRIPT_DIR}/common.sh"
13+
14+
usage() {
15+
cat <<'EOF'
16+
Usage: update_lerobot_version.sh VERSION
17+
18+
Update the pinned LeRobot version in pyproject.toml and .lerobot-version,
19+
then re-lock dependencies. Review the release notes, rebuild both
20+
architectures, run the workflows you use, and then commit pyproject.toml,
21+
uv.lock, and .lerobot-version together.
22+
EOF
23+
}
24+
25+
main() {
26+
local version="${1:-}"
27+
local version_file="${LEROBOT_DIR}/.lerobot-version"
28+
local pyproject_file="${LEROBOT_DIR}/pyproject.toml"
29+
local temporary_file
30+
31+
if [[ "${version}" == "-h" || "${version}" == "--help" ]]; then
32+
usage
33+
return 0
34+
fi
35+
[[ -n "${version}" && $# -eq 1 ]] || {
36+
usage >&2
37+
return 2
38+
}
39+
40+
require_command uv
41+
42+
temporary_file="$(mktemp)"
43+
sed -E "s/^( \"lerobot\[[^]]*\])==[^\"]+(\",)\$/\1==${version}\2/" \
44+
"${pyproject_file}" >"${temporary_file}"
45+
if diff -q "${pyproject_file}" "${temporary_file}" &>/dev/null; then
46+
rm -f "${temporary_file}"
47+
die "no lerobot dependency line matched in ${pyproject_file}"
48+
fi
49+
mv "${temporary_file}" "${pyproject_file}"
50+
51+
temporary_file="$(mktemp)"
52+
sed "s|^LEROBOT_VERSION=.*|LEROBOT_VERSION=${version}|" "${version_file}" >"${temporary_file}"
53+
mv "${temporary_file}" "${version_file}"
54+
55+
(cd "${LEROBOT_DIR}" && uv lock)
56+
57+
printf 'Updated LeRobot to %s\n' "${version}"
58+
git -C "${LEROBOT_REPO_ROOT}" status --short \
59+
"${LEROBOT_DIR#"${LEROBOT_REPO_ROOT}/"}/.lerobot-version" \
60+
"${LEROBOT_DIR#"${LEROBOT_REPO_ROOT}/"}/pyproject.toml" \
61+
"${LEROBOT_DIR#"${LEROBOT_REPO_ROOT}/"}/uv.lock"
62+
}
63+
64+
main "$@"

gpu-offload/examples/so101-real-hardware/scripts/update_upstream.sh

Lines changed: 0 additions & 67 deletions
This file was deleted.
Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)