N1.5 removal is now explicit and actionable:
- Legacy N1.5 checkpoint configs (tokenizer_assets_repo) parse and fail
with a single clear error pointing to lerobot==0.5.1 instead of a
cryptic draccus DecodingError
- Removed N1.5 processor registry names (groot_pack_inputs_v3,
groot_eagle_encode_v3, groot_eagle_collate_v3) are stubbed to raise the
same guidance; groot_action_unpack_unnormalize_v1 changed semantics, so
the step is re-registered as _v2 and _v1 is stubbed
- N1.5 detection also recognizes checkpoint config.json content
(model_type/architectures/eagle backbone), not just path names; every
rejection surface includes the migration guidance
- groot.mdx documents the breaking change and migration path
Runtime fixes:
- use_bf16=False no longer crashes (compute_dtype only set when used)
- GrootN17ActionDecodeStep handles the 2-D (B, D) actions delivered by
sync select_action (relative eef/non-eef decode was broken in
lerobot-eval/record flows)
- Postprocessor falls back to dataset stats when a raw checkpoint lacks
the configured embodiment tag instead of silently emitting normalized
[-1, 1] actions
- Hub-hosted finetuned N1.7 checkpoints load: the processor config is
resolved via hf_hub_download for non-local paths, with a tolerant
retry when inspection fails
- Raw-checkpoint processor branch honors caller overrides (device,
rename_map) instead of dropping them
- Relative-action raw-state cache is per-instance instead of
process-global (cross-instance contamination)
- Camera/modality-key mismatches warn, including the zero-match
fallback; checkpoint revision is no longer forwarded into backbone
loading; deprecated Qwen2VLImageProcessorFast replaced with
Qwen2VLImageProcessor
Config/UX:
- GrootConfig defaults are the N1.7 values; explicitly passed legacy
N1.5-era values (chunk_size=50, max_state_dim=64, ...) are remapped
with a warning instead of silently
- Explicit action_decode_transform='none' wins over the libero_sim
default (new 'auto' sentinel) and survives save/load round-trips
Tests/CI:
- pytest.importorskip guards so fast_tests tiers pass without
transformers (was 10 failures, now 0)
- Regression tests for every fix; from_pretrained rejection tests now
actually exercise from_pretrained
- Parity test reads the artifact seed, fails on shape mismatch instead
of silently truncating, and a new case runs LeRobot's real Qwen3-VL
preprocessing on raw observations dumped by the producer
- docs: dead huggingface-cli download replaced with hf download
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The test loaded MODEL_PATH='aractingi/bimanual-handover-groot-10k', an N1.5
checkpoint (config base_model_path=nvidia/GR00T-N1.5-3B, no model_version). On
load, model_version defaults to n1.7 while the base path infers n1.5, so the
version-consistency guard in GrootConfig.__post_init__ raised ValueError and both
test_lerobot_groot_inference and test_lerobot_groot_forward_pass failed. N1.5 is no
longer a supported model_version.
Adopt the test for N1.7:
- MODEL_PATH -> nvidia/GR00T-N1.7-3B (root-level sharded safetensors; loads via
GrootPolicy.from_pretrained as a base N1.7 model).
- Embodiment tag 'gr1' (N1.5) -> 'gr1_unified' (valid N1.7 tag from the checkpoint
embodiment_id.json), via a single EMBODIMENT_TAG constant.
- DUMMY_ACTION_HORIZON 16 -> 40 to match N1.7's native action-chunk size.
- Docstrings/labels updated to 'GR00T N1.7'.
Both tests run and pass on CUDA; full tests/policies/groot/ suite is
73 passed / 0 failed / 0 skipped.
Mirror the tests/policies/pi0_pi05/utils convention: move dump_original_n1_7.py into
a tests/policies/groot/utils/ package (with __init__.py) and update all path
references in the test docstring/skip-message and the policy README.
- Rename test_groot_n1_7_vs_original.py -> test_groot_vs_original.py
- Make the test self-contained: producer script (dump_original_n1_7.py) now lives
next to the test; default artifact dir is repo-relative
(tests/policies/groot/artifacts/), overridable via GROOT_N1_7_PARITY_DIR. The
test only reads artifacts and skips if absent -- it never creates external dirs.
- Heavy .npz artifacts (~6-9MB each) are gitignored and regenerated by the producer;
never committed.
- Drop the verbose 'MULTIPLE EMBODIMENTS' docstring block (kept a one-line note).
- Document the parity procedure in the groot policy README (docs/source/policy_groot_README.md).
- Rename test fn test_groot_n1_7_get_action_parity -> test_groot_get_action_parity.
9/9 embodiments still pass (max|diff| < 3e-6, fp32 eps).
Generalize the original-vs-LeRobot N1.7 output-parity test from a single
libero_sim case to every embodiment tag in the checkpoint (libero_sim, oxe_droid,
real_g1, the real_r1_pro_sharpa family, and the xdof family). Inputs are built
generically from checkpoint metadata; the test discovers per-tag .npz artifacts
and runs one parametrized case each, loading the LeRobot model once via a fixture.
All 9 embodiments match the original to fp32 epsilon (max|diff| < 3e-6), confirming
the integration is correct across the model's full embodiment space and not overfit
to libero_sim.
Verifies the LeRobot GR00T N1.7 integration produces equivalent raw
action_pred to NVIDIA Isaac-GR00T for the same checkpoint, inputs, seed,
precision (fp32) and attention kernel (SDPA): max|diff|=8.9e-7 on the
libero_sim embodiment (GR00T-N1.7-LIBERO/libero_10).
The two impls pin incompatible transformers majors (orig 4.57.3 vs
LeRobot 5.x) and cannot share a process, so the original outputs + exact
collated inputs are produced out-of-process and loaded from an .npz. The
test skips on CI / when the checkpoint or artifact are absent.