Skip to content

Move to LeRobot v0.7.0 - #154

Merged
nicolas-rabault merged 12 commits into
mainfrom
chore/lerobot-0.7
Nov 6, 2026
Merged

nicolas-rabault merged 12 commits into
mainfrom
chore/lerobot-0.7

Conversation

@nicolas-rabault

@nicolas-rabault nicolas-rabault commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Moves LeLab onto LeRobot v0.7.0.

All 393 existing tests passed against v0.7.0 while three flows were broken, so most fixes come with a test that fails without them.

Broken on v0.7.0

  • Training: every run died at argument parsing on --wandb.enable. LeRobot replaced W&B with Trackio (refactor(utils): replace wandb with trackio lerobot#4954). The form now has a Trackio switch with a project field, and an optional Space under Advanced. Signed-in runs sync to a private <user>/lelab-trackio Space by default, which LeRobot requires on HF Jobs. Trackio also creates a private <user>/lelab-trackio-bucket to hold logs until the Space is up. The W&B install gate is gone, since Trackio ships with lerobot[training].
  • Calibration: homing raised a TypeError. The motors now go through a rustypot-backed SerialMotorsBus (refactor(motors): one rustypot-backed SerialMotorsBus for Feetech and Dynamixel lerobot#4672), whose _get_half_turn_homings() changed signature. It now uses set_half_turn_homings() and set_operating_mode("position").
  • Policy extras: WALL-OSS showed as missing even once installed, because its probe module (torchdiffeq) left the extra. The check now reads what lerobot[extra] requires from LeRobot's metadata, versions included.

Wrong without crashing

Cleanups

Tests

tests/test_lerobot_cli.py runs the training argv (local, HF Jobs, GR00T flags) and the rollout argv through the installed LeRobot's parsers. It also checks that every policy in the training form is a registered LeRobot policy type. Against the old train.py it fails on --wandb.enable.

I also ran short ACT trainings on lerobot/svla_so101_pickplace through JobRegistry, once per Trackio mode:

  • Signed out: the run stays in the local Trackio database.
  • Signed in: LeLab picked the default Space. Trackio created the Space and the bucket as private. LeLab captured the Space URL, and the run's metrics read back from the Space once it was running.

Hardware run

On SO-101 arms, against v0.7.0:

  • calibrate leader and follower, including stopping a calibration midway
  • teleoperate, and restart right after Stop, so the port is released
  • record a few episodes
  • replay an episode

The rollout did not run on the arms. tests/test_lerobot_cli.py covers its argv.

LeRobot replaced the Feetech SDK bus with a rustypot-backed SerialMotorsBus
(huggingface/lerobot#4672). Its _get_half_turn_homings() now takes the homing
offset sign of each motor, so the homing step raised a TypeError before the
range recording started. set_half_turn_homings() does the reset, the read and
the offset writes in one call, and also clamps the offsets the Feetech
register cannot hold (huggingface/lerobot#4940). The operating mode is set by
name, since the OperatingMode enum is deprecated.

rustypot serializes access to the port behind a mutex, so the "Port is in
use" error the retries matched on no longer exists.
The forced release reached into the Feetech SDK's port_handler, which
SerialMotorsBus does not have, so it silently did nothing. The new bus closes
the port in disconnect() even when disabling the torque fails, which is the
guarantee the fallback needs.
LeRobot now disables the torque before writing a kept calibration file, so
that Feetech motors store it (huggingface/lerobot#4867): with
SerialMotorsBus, disabling the torque also opens the Feetech EEPROM lock.
Recording, teleoperation and replay wrote the calibration right after
connecting, assuming the torque was already off.
LeRobot dropped its W&B integration for Trackio (huggingface/lerobot#4954),
so every training run died at argument parsing on the `--wandb.enable` flag
LeLab always sent.

- Send `--trackio.enable`, `--trackio.project` and `--trackio.space_id`.
  Entity, notes, run id and mode have no Trackio counterpart.
- Default the Space to a private `<user>/lelab-trackio` for a signed-in user:
  it gives the run a dashboard link, and LeRobot refuses HF Jobs without one.
  Signed out, a local run stays in this machine's Trackio database.
- Capture the Space URL from LeRobot's "Track this run -->" line. Jobs saved
  with a W&B link keep it.
- Stop sending `disable_artifact`: Trackio now skips checkpoint artifacts by
  default (huggingface/lerobot#5123), where LeLab's default would have copied
  every checkpoint into the Space.
- Drop the W&B install gate: Trackio ships with `lerobot[training]`.
@nicolas-rabault
nicolas-rabault marked this pull request as ready for review November 6, 2026 08:55
Copilot AI balanced review requested due to automatic review settings November 6, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Precision selection can use unsupported or inefficient BF16 on pre-Ampere GPUs and omit mixed precision for indexed CUDA devices, silently disabling AMP.

2 open issues
What changed in this PR

Updates LeLab’s FastAPI backend and React interface for LeRobot v0.7.0, adapting training, motor control, and rollout behavior to upstream changes.

Changes:

  • Replaces W&B integration with Trackio configuration and dashboard links.
  • Updates motor-bus calls, calibration writes, mixed precision, rollout arguments, and shutdown timing.
  • Adds regression tests, including validation against LeRobot’s CLI parsers.
File Description
tests/​test_utils_system.py Tests metadata-based policy dependency checks.
tests/​test_train.py Tests Trackio flags and mixed precision.
tests/​test_rollout.py Tests task quoting and setup-stop timing.
tests/​test_lerobot_cli.py Adds upstream CLI parser compatibility tests.
tests/​test_jobs.py Tests tracking links and default Spaces.
tests/​test_devices.py Tests serial-bus cleanup after disconnect failures.
tests/​test_calibrate.py Tests public motor-bus API usage.
pyproject.toml Pins LeRobot to v0.7.0.
lelab/​utils/​system.py Checks policy extras through dependency metadata; removes W&B installation support.
lelab/​utils/​devices.py Uses bus disconnect for fallback cleanup.
lelab/​train.py Generates Trackio and mixed-precision arguments.
lelab/​teleoperate.py Disables torque before writing calibration.
lelab/​server.py Removes W&B installation endpoints.
lelab/​rollout.py Quotes task strings and extends setup-stop grace.
lelab/​replay.py Disables torque before writing calibration.
lelab/​record.py Updates calibration writes and exception logging.
lelab/​jobs.py Captures tracking links and defaults Trackio Spaces.
lelab/​calibrate.py Uses public homing APIs and simplifies error handling.
frontend/​src/​pages/​Training.tsx Submits Trackio settings and displays metrics links.
frontend/​src/​lib/​jobsApi.ts Updates training and job API types.
frontend/​src/​hooks/​useInstallExtra.ts Updates documentation examples only.
frontend/​src/​components/​training/​WandbInstallDialog.tsx Deletes the W&B installation dialog.
frontend/​src/​components/​training/​types.ts Replaces W&B configuration fields with Trackio fields.
frontend/​src/​components/​training/​PolicyExtraDialog.tsx Describes unmet package requirements.
frontend/​src/​components/​training/​config/​EssentialsCard.tsx Adds Trackio controls and removes the install gate.
frontend/​src/​components/​training/​config/​AdvancedCard.tsx Adds optional Trackio Space configuration.
frontend/​src/​components/​jobs/​JobsSection.tsx Consumes tracking links from progress updates.
CLAUDE.md Documents migration practices and corrects module descriptions.

Review effort: Balanced

Comment thread lelab/train.py
# Training takes mixed precision from accelerate alone (huggingface/lerobot#4010); use_amp
# above stays for the saved config, which evaluation and inference read. HF Jobs pods are
# GPUs; bf16 needs no loss scaling.
if request.policy_use_amp and (is_cloud or device == "cuda"):

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The form only sends cpu or the auto-selected device type, so the device is never indexed.

Comment thread lelab/train.py Outdated
Comment on lines +163 to +164
if request.policy_use_amp and (is_cloud or device == "cuda"):
cmd.extend(["--accelerator.mixed_precision", "bf16"])

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to fp16: it is what use_amp trained with on CUDA in v0.6.1 (the torch.autocast default), what lerobot-eval still runs under, and it works on the T4.

LeRobot's parallel training framework (huggingface/lerobot#4010) takes mixed
precision from `--accelerator.mixed_precision` alone; `--policy.use_amp` is
only read by evaluation and inference now, so the switch no longer changed
how a run trained. Send fp16 on CUDA and on HF Jobs pods, the torch.autocast
default that v0.6.1 trained with and that evaluation still runs under, and
keep use_amp so the saved config still runs inference in AMP.
The check probed one module per policy, which no longer matches LeRobot:
the `wallx` extra dropped torchdiffeq (huggingface/lerobot#4077), so WALL-OSS
stayed "missing" even once installed. A probe also passes an environment
upgraded from an older LeRobot, where transformers 5.5 still imports though
the extras now pin 5.22.

Read what `lerobot[extra]` requires from LeRobot's own metadata, through the
extras it is built from, and report each package that is missing or out of
range. New extras need no hand-picked probe, and a test fails when LeRobot
renames or drops an extra LeLab offers.
draccus decodes a string flag as YAML, so a task like "step 1: grab the
cube" reached the policy as a dict, "yes" as True, and "null" as None since
the draccus bump in LeRobot main. A language-conditioned policy then ran on
the wrong instruction without any error. JSON-quote the task, which draccus
decodes back to the exact string.
LeRobot now connects the arm only after the policy has loaded
(huggingface/lerobot#4866), and a stop signal during setup is only noted
until the control loop starts. Killing the process 5s after Stop could land
in the middle of connecting the arm and leave it powered. Wait up to 60s
while setup runs; the 5s grace still applies once the loop has started.
The argv-shape tests all passed while every training run died on the
removed `--wandb.enable` flag. Parse the real training argv (local, HF Jobs,
and GR00T's own flags) and the real rollout argv with the installed
LeRobot, and check every policy the training form offers is a policy type
LeRobot registers, so the next rename fails here instead of on a user's run.
LeRobot's init_logging() now installs a real logging.Formatter that keeps
exc_info (huggingface/lerobot#4215), so the tracebacks folded into the
message by hand are no longer needed.
…DE.md

Also fix two module descriptions that no longer matched the code: recording
drives record_loop with its own events dict rather than patching LeRobot's
keyboard listener, and teleoperation runs its own loop.
@nicolas-rabault
nicolas-rabault merged commit 1894ab5 into main Nov 6, 2026
6 checks passed
@nicolas-rabault
nicolas-rabault deleted the chore/lerobot-0.7 branch November 6, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants