Commit 235d4c6
authored
feat(training): add NVIDIA ARM64 support for LeRobot 0.6.1 (#1407)
# Pull Request
## Description
<!-- Brief description of changes. Link related issues using Closes #123
-->
Adds NVIDIA ARM64 (Jetson Thor / CUDA 13) support so LeRobot
imitation-learning work can run on local ARM64 hardware as well as the
existing x86_64 AzureML and OSMO targets, and bumps LeRobot to
**0.6.1**. The dataset-consuming code paths were updated for LeRobot's
newer shared-file layout, and several related correctness fixes travel
with the change.
> The decoder choice drives much of this PR. LeRobot's `dataset` extra
requires TorchCodec, which publishes no SBSA CUDA 13 wheel, and
`get_safe_default_video_backend()` selects TorchCodec whenever it is
importable. Keeping TorchCodec on x86_64 only would have decoded
training and evaluation frames through different backends per
architecture, so the branch standardizes on **PyAV** everywhere.
### Dependencies
- Moved `training/il/lerobot` from `lerobot[dataset]==0.6.0` to
`lerobot[av-dep]==0.6.1` and removed `torchcodec` as both a direct
dependency and a resolution override.
- Declared `pandas` and `jsonlines` directly, since *lerobot.datasets*
imports them eagerly and they shipped in the extra that is no longer
selected. Runtime installs use `uv pip install --no-deps`, so both must
be in the lock.
- Removed the `wandb` pin. All three LeRobot entry points
(*azureml-train-entry.sh*, *lerobot-train-osmo-entry.sh*, and
*train.py*) pass `--wandb.enable=false`, and `wandb` only appears in
LeRobot's unselected `training` extra.
- Widened `[tool.uv].environments` to cover `x86_64` and `aarch64`, and
added the `jetson-ai-lab-cu130` index as an `explicit` source for ARM64
`torch` and `torchvision` only.
- Existing CVE-motivated pins (`gitpython`, `urllib3`, `cryptography`)
are unchanged.
### Dev container
- Rebuilt *.devcontainer/Dockerfile* as a two-stage image. The CUDA
stage is digest-pinned, installs exact-version CUDA and CUPTI packages,
and adds cuDSS plus NVPL BLAS/LAPACK on arm64 only. The final base moved
to `devcontainers/base:ubuntu-24.04`.
- Added `hostRequirements.gpu: "optional"` so GPU-less hosts still
build, plus the `--group-add` entries CUDA needs. `/dev/nvmap` is owned
by `video` and `/dev/dri/renderD*` by `render`; without both,
`cudaGetDeviceCount()` fails with error 801 while `nvidia-smi` still
looks healthy.
- Reworked the `osmo-cli` install from an x86_64-only skip into an
architecture dispatch that installs the checksum-verified OSMO 6.3.0
client on `arm64` as well.
### Data viewer
- **Blob sync** now requests blob metadata and skips ADLS Gen2 directory
blobs (`hdi_isfolder`) along with HuggingFace `.cache` entries. Writing
a directory blob as a file previously blocked creation of the directory
beneath it.
- **Cached episode clips** are validated with a bounded *ffmpeg* probe
before being served; invalid clips are deleted and regenerated.
- **TrajectoryEditor** was split into a wrapper and an inner frame
component keyed by episode and frame, replacing a synchronization effect
that discarded in-progress edits whenever the adjustments map changed
for an unrelated frame. Clearing all adjustments now also resets the
editor inputs, which the previous version left showing stale deltas.
### Evaluation and training scripts
- *run-local-lerobot-eval.py* reads the `meta/episodes/**.parquet`
metadata layout, resolves data and video files through the `data_path`
and `video_path` templates, filters rows by `episode_index`, and decodes
only each episode's timestamp window. The legacy chunk-scan and
`episodes.jsonl` paths remain as fallbacks, and metadata lookups are
guarded so datasets lacking the newer columns fall back rather than
raising.
- *download_dataset.py* skips ADLS directory-marker blobs instead of
trying to download them as files.
### Infrastructure
- *03-deploy-osmo.sh* labels the pre-created `osmo-default-admin`
secret, plus `db-secret` and `redis-secret` when they are Key
Vault-backed, with `secrets-store.csi.k8s.io/managed=true`. The CSI
driver otherwise refuses to adopt secrets it does not own. The change is
metadata-only and reads no secret material.
None
## Type of Change
<!-- Mark relevant options with [x] -->
- [x] 🐛 Bug fix (non-breaking change fixing an issue)
- [x] ✨ New feature (non-breaking change adding functionality)
- [ ] 💥 Breaking change (fix or feature causing existing functionality
to change)
- [x] 📚 Documentation update
- [ ] 🏗️ Infrastructure change (Terraform/IaC)
- [ ] ♻️ Refactoring (no functional changes)
<!-- Note: x86_64 video decoding moves from TorchCodec to PyAV. No API
changes, but reviewers should confirm this is acceptable for existing
AzureML and OSMO training runs. -->
## Component(s) Affected
<!-- Mark all that apply -->
- [ ] `infrastructure/terraform/prerequisites/` - Azure subscription
setup
- [ ] `infrastructure/terraform/` - Terraform infrastructure
- [x] `infrastructure/setup/` - OSMO control plane / Helm
- [ ] `workflows/` - Training and evaluation workflows
- [x] `training/` - Training pipelines and scripts
- [x] `docs/` - Documentation
<!-- Also affected, not listed above: .devcontainer/,
data-management/viewer/ (backend and frontend), evaluation/sil/ -->
## Testing Performed
<!-- Describe testing. Check applicable items -->
- [ ] Terraform `plan` reviewed (no unexpected changes)
- [ ] Terraform `apply` tested in dev environment
- [ ] Training scripts tested locally with Isaac Sim
- [ ] OSMO workflow submitted successfully
- [ ] Smoke tests passed (`smoke_test_azure.py`)
None of the listed items apply: this PR changes no Terraform, submits no
OSMO workflow, and touches no Isaac Sim path. Validation performed
instead:
| Check | Result |
| --- | --- |
| `npm run lint:md` (tracked files) | 0 issues |
| `npm run spell-check` | 0 issues across 791 files |
| `npm run format:tables` | clean |
| `npm run lint:sh` | 95 files, 0 errors, 0 warnings |
| `npm run lint:py` | passed |
| `npm run lint:uvlock` (changed-files-only, as PR validation runs it) |
passed |
| Frontend `npm run validate` | 1669/1669 tests, 0 errors |
| Backend `pytest` (changed modules) | 107 passed, 15 skipped |
Hardware validation on an NVIDIA Thor (aarch64) host, inside the rebuilt
dev container as the non-root `vscode` user:
- `torch.cuda.is_available()` returned `True`, device reported as
`NVIDIA Thor`, CUDA runtime 13.0, and a 2048x2048 matmul produced finite
values.
- `get_safe_default_video_backend()` resolved to `pyav` with
`torchcodec` absent, confirming the decoder is consistent across
architectures.
- The `osmo` 6.3.0 arm64 client installed and reported its version.
Environment: local NVIDIA Thor workstation only. No Azure resources were
deployed and no cost was incurred.
Known limitations: the x86_64 path was not executed on hardware, so the
TorchCodec-to-PyAV decoder change is unverified for AzureML and OSMO
training runs. LeRobot training itself was not run end-to-end on ARM64;
validation covered CUDA availability, dependency resolution, and backend
selection.
## Documentation Impact
<!-- Select one -->
- [ ] No documentation changes needed
- [x] Documentation updated in this PR
- [ ] Documentation issue filed
*docs/contributing/prerequisites.md* gains a Dev Container GPU Runtime
section covering host runtime configuration for CSV-mode ARM64 hosts and
the device-group access requirements, including how to confirm the host
`render` GID and the misleading error-801 symptom.
*docs/getting-started/quickstart.md* cross-links to it.
## Bug Fix Checklist
*Complete this section for bug fix PRs. Skip for other contribution
types.*
- [x] Linked to issue being fixed — Closes #1446
- [x] Regression test included, OR
- [ ] Justification for no regression test:
Regression coverage added for each fix: two TrajectoryEditor tests
(pending edits surviving an unrelated store update, and inputs clearing
on Clear All), blob-sync tests asserting directory and `.cache` blobs
are not downloaded, and a handler test proving an invalid cached clip is
regenerated. The TrajectoryEditor tests were confirmed to fail against
the pre-fix implementations.
## Checklist
- [x] My code follows the [project conventions](copilot-instructions.md)
- [x] Commit messages follow [conventional commit
format](instructions/commit-message.instructions.md)
- [x] I have performed a self-review
- [x] Documentation impact assessed above
- [x] No new linting warnings introduced
## Notes
The 39 frontend lint warnings are pre-existing
`react-hooks/set-state-in-effect` findings; this PR removes one such
effect and adds none.
`npm run lint:uvlock` passes for all 13 locked Python projects after the
review update.
Follow-up candidates, all evidenced in the diff:
- The `datasets==5.0.0` override comment in
*training/il/lerobot/pyproject.toml* cites a cap from LeRobot's
`dataset` extra, which is no longer selected; confirm whether the
override is still required.
- The `render` GID `993` in *.devcontainer/devcontainer.json* is
host-specific. It is documented in both the file comment and the
prerequisites guide, but it is not resolved dynamically.
## Review amendment — September 1, 2026
Closes #1446
Reviewer feedback is addressed in `a43555e0`:
- Digest-pinned the final dev-container runtime image and removed the
unrestricted base-image build argument so container discovery scans the
shipped image.
- Enabled all NVIDIA driver capabilities, including Vulkan.
- Contained metadata-template and legacy video paths within the dataset
root, rejecting absolute paths and traversal.
- Added real LeRobot shared-file integration coverage for metadata
loading, Parquet episode filtering, path templates, timestamp-window
video decoding, empty episodes, and legacy fallbacks.
- Added direct ffmpeg probe coverage for valid clips, failures,
timeouts, and environments without ffmpeg.
- Added PyAV and PyArrow to the evaluation CI test group so integration
coverage executes rather than skips.
- Isolated Dataviewer API tests from developer Azure storage
configuration to prevent credential retries.
Validation after the review fixes: evaluation 300 passed with 96.25%
coverage; Dataviewer backend 1,136 passed; Dataviewer frontend 1,669
passed; LeRobot download tests 67 passed; Python lint, uv lock
consistency, and focused container-image discovery tests passed.
Reviewer-provided AzureML and OSMO end-to-end runs also passed.1 parent 08c2972 commit 235d4c6
23 files changed
Lines changed: 1453 additions & 501 deletions
File tree
- .devcontainer
- data-management/viewer
- backend
- src/api
- services/dataset_service
- storage
- tests
- api
- storage
- frontend/src/components/frame-editor
- __tests__
- docs
- contributing
- getting-started
- evaluation
- sil/scripts
- tests
- infrastructure/setup
- training
- il
- lerobot
- scripts/lerobot
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
| |||
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| 37 | + | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
| |||
52 | 54 | | |
53 | 55 | | |
54 | 56 | | |
| 57 | + | |
55 | 58 | | |
56 | 59 | | |
57 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
3 | 23 | | |
4 | 24 | | |
5 | 25 | | |
| |||
8 | 28 | | |
9 | 29 | | |
10 | 30 | | |
11 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
10 | 9 | | |
11 | 10 | | |
12 | 11 | | |
| |||
92 | 91 | | |
93 | 92 | | |
94 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
95 | 109 | | |
96 | 110 | | |
97 | 111 | | |
98 | | - | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
99 | 115 | | |
100 | 116 | | |
101 | 117 | | |
| |||
106 | 122 | | |
107 | 123 | | |
108 | 124 | | |
109 | | - | |
| 125 | + | |
110 | 126 | | |
111 | 127 | | |
112 | 128 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
| 78 | + | |
78 | 79 | | |
79 | 80 | | |
80 | 81 | | |
| |||
344 | 345 | | |
345 | 346 | | |
346 | 347 | | |
| 348 | + | |
347 | 349 | | |
348 | 350 | | |
349 | 351 | | |
| |||
Lines changed: 31 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
475 | 475 | | |
476 | 476 | | |
477 | 477 | | |
478 | | - | |
| 478 | + | |
479 | 479 | | |
| 480 | + | |
480 | 481 | | |
481 | 482 | | |
482 | 483 | | |
| |||
495 | 496 | | |
496 | 497 | | |
497 | 498 | | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
498 | 528 | | |
499 | 529 | | |
500 | 530 | | |
| |||
Lines changed: 17 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
606 | 606 | | |
607 | 607 | | |
608 | 608 | | |
609 | | - | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
610 | 616 | | |
611 | 617 | | |
612 | 618 | | |
613 | 619 | | |
614 | 620 | | |
615 | 621 | | |
616 | 622 | | |
617 | | - | |
618 | 623 | | |
619 | 624 | | |
620 | 625 | | |
| |||
642 | 647 | | |
643 | 648 | | |
644 | 649 | | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
645 | 656 | | |
646 | 657 | | |
647 | 658 | | |
| |||
665 | 676 | | |
666 | 677 | | |
667 | 678 | | |
668 | | - | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
669 | 683 | | |
670 | 684 | | |
671 | 685 | | |
| |||
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | 6 | | |
8 | 7 | | |
9 | 8 | | |
| |||
29 | 28 | | |
30 | 29 | | |
31 | 30 | | |
32 | | - | |
| 31 | + | |
33 | 32 | | |
34 | 33 | | |
35 | | - | |
| 34 | + | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
| 12 | + | |
| 13 | + | |
14 | 14 | | |
| 15 | + | |
| 16 | + | |
15 | 17 | | |
16 | | - | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
17 | 22 | | |
18 | 23 | | |
19 | 24 | | |
20 | | - | |
| 25 | + | |
21 | 26 | | |
22 | 27 | | |
23 | 28 | | |
24 | | - | |
| 29 | + | |
25 | 30 | | |
26 | 31 | | |
27 | 32 | | |
28 | 33 | | |
29 | | - | |
30 | | - | |
31 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
32 | 37 | | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | 38 | | |
40 | 39 | | |
41 | 40 | | |
42 | 41 | | |
43 | | - | |
| 42 | + | |
44 | 43 | | |
45 | 44 | | |
46 | 45 | | |
47 | 46 | | |
48 | | - | |
49 | | - | |
| 47 | + | |
50 | 48 | | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | 49 | | |
56 | 50 | | |
57 | 51 | | |
| |||
Lines changed: 21 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
35 | 41 | | |
36 | 42 | | |
37 | 43 | | |
| |||
544 | 550 | | |
545 | 551 | | |
546 | 552 | | |
547 | | - | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
548 | 561 | | |
549 | 562 | | |
550 | 563 | | |
| |||
559 | 572 | | |
560 | 573 | | |
561 | 574 | | |
| 575 | + | |
562 | 576 | | |
563 | 577 | | |
564 | 578 | | |
| |||
584 | 598 | | |
585 | 599 | | |
586 | 600 | | |
587 | | - | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
588 | 607 | | |
589 | 608 | | |
590 | 609 | | |
| |||
0 commit comments