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>
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).