LeRobot 中的 GR00T N1.7 集成:从模型架构到 Original-vs-LeRobot 数值一致性验证
【免费下载链接】lerobot🤗 LeRobot: Making AI for Robotics more accessible with end-to-end learning项目地址: https://gitcode.com/GitHub_Trending/le/lerobot
本篇技术指南围绕docs/source/policy_groot_README.md展开,系统介绍 LeRobot 对 NVIDIA GR00T N1.7 基础模型(Cosmos-Reason2/Qwen3-VL 骨干 + flow-matching 动作头)的集成方式,重点剖析仓库中用于证明"LeRobot 重实现与 NVIDIA 原版gr00t包数值一致"的Original-vs-LeRobot parity test(模型级 parity 与前处理级 parity 双维度校验)。读完本文,你将掌握 GR00T N1.7 在 LeRobot 中的版本选型规则、N1.5 迁移注意事项、双虚拟环境 producer/consumer 对拍测试的完整运行流程与公平性控制手段,并能结合 GrootConfig、GR00TN17 模型实现 与 processor 管线 理解其底层原理。
GR00T 与 LeRobot 集成概览
GR00T(Generalist Robot Transformer)是 NVIDIA 面向通用人形机器人的基础模型家族,属于跨具身(cross-embodiment)策略:它同时接受语言指令、多路相机图像与本体感受(proprioception)状态,输出一段动作块(action chunk)以完成多样化环境中的操作任务。LeRobot 通过groot策略类型接入 GR00T N1.7,模型使用 Cosmos-Reason2/Qwen3-VL 骨干,并提供 SimplerEnv、DROID、LIBERO 等具身标签(embodiment tag)的公开检查点。
核心版本事实:LeRobot 当前版本仅支持 GR00T N1.7。GR00T N1.5 支持已被移除,最后一个支持 N1.5 的发布版本是
lerobot==0.5.1。N1.5 的检查点与配置会被明确拒绝并附带迁移指引。
版本识别与 N1.5 拒绝机制(源码实现)
在 configuration_groot.py 中,版本管理通过一组明确的常量与函数实现:
GROOT_N1_7 = "n1.7"与GROOT_N1_5 = "n1.5"分别标识两个版本;GROOT_N1_7_BASE_MODEL = "nvidia/GR00T-N1.7-3B"与GROOT_N1_7_BACKBONE_MODEL = "nvidia/Cosmos-Reason2-2B"定义默认基座模型。_GROOT_MODEL_VERSION_ALIASES将n1.7、n1_7、n1d7、n17、1.7等拼写归一化为n1.7;而_GROOT_N1_5_VERSION_ALIASES(n1.5、n1_5、n1d5、n15、1.5)刻意不参与归一化,只用于识别后抛出带迁移提示的异常。GROOT_N1_5_REMOVAL_GUIDANCE是统一的迁移提示文案:需要继续使用 N1.5 检查点时执行pip install 'lerobot==0.5.1';使用当前版本则迁移到model_version='n1.7'(基座nvidia/GR00T-N1.7-3B)。infer_groot_model_version会从路径字符串、本地config.json的model_version/model_type/architectures/backbone_cfg等多处线索推断版本,N1.7 的GrootConfig.__post_init__一旦检测到base_model_path指向 N1.5 就抛ValueError,避免把旧检查点静默当作 N1.7 使用。
值得一提的细节是:N1.5 时代的旧默认值(如max_state_dim=64、max_action_dim=32、chunk_size=50、image_size=(224,224))会被自动重映射为 N1.7 期望值(132、132、40、(256,256))并打印警告,保证旧命令与旧配置不会静默跑出错误维度。
研究资料与引用信息
原文档完整保留了 GR00T 系列的核心研究资料,整理如下:
- 技术报告:GR00T N1 technical report(涵盖 GR00T N1.x 家族,包括 N1.7):
https://arxiv.org/abs/2503.14734 - 模型卡:GR00T N1.7 模型卡(
nvidia/GR00T-N1.7-3B) - 早期版本研究页:GR00T N1.5 research page(N1.7 之前的版本)
- 官方代码仓库:
https://github.com/NVIDIA/Isaac-GR00T - 官方博客:NVIDIA Isaac GR00T 开发者博客
- Hugging Face 模型:
- GR00T N1.7:
nvidia/GR00T-N1.7-3B - GR00T N1.7 LIBERO 检查点:
nvidia/GR00T-N1.7-LIBERO
- GR00T N1.7:
引用该模型的 BibTeX 条目(原文档提供,可直接用于论文致谢):
@inproceedings{gr00tn1_2025, archivePrefix = {arxiv}, eprint = {2503.14734}, title = {{GR00T} {N1}: An Open Foundation Model for Generalist Humanoid Robots}, author = {NVIDIA and Johan Bjorck and Fernando Castañeda, Nikita Cherniadev and Xingye Da and Runyu Ding and Linxi "Jim" Fan and Yu Fang and Dieter Fox and Fengyuan Hu and Spencer Huang and Joel Jang and Zhenyu Jiang and Jan Kautz and Kaushil Kundalia and Lawrence Lao and Zhiqi Li and Zongyu Lin and Kevin Lin and Guilin Liu and Edith Llontop and Loic Magne and Ajay Mandlekar and Avnish Narayan and Soroush Nasiriany and Scott Reed and You Liang Tan and Guanzhi Wang and Zu Wang and Jing Wang and Qi Wang and Jiannan Xiang and Yuqi Xie and Yinzhen Xu and Zhenjia Xu and Seonghyeon Ye and Zhiding Yu and Ao Zhang and Hao Zhang and Yizhou Zhao and Ruijie Zheng and Yuke Zhu}, month = {March}, year = {2025}, booktitle = {ArXiv Preprint}, }模型与配置核心(为 parity 测试打底)
在深入 parity 测试之前,先快速建立对 LeRobot 侧实现结构的认知,这有助于理解测试中"字节级一致输入"与"原始输出action_pred"究竟指什么。
GrootConfig:策略包装层的关键参数
GrootConfig 是groot策略的配置类(通过@PreTrainedConfig.register_subclass("groot")注册),关键字段如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
n_obs_steps/chunk_size/n_action_steps | 1/40/40 | 观测步数、解码动作块长度与执行步数,N1.7 检查点期望 40 步 chunk |
max_state_dim/max_action_dim | 132/132 | 状态/动作最大维度,更短的向量会被零填充 |
base_model_path | nvidia/GR00T-N1.7-3B | 基座模型来源,与保存的 LeRobot 检查点pretrained_path刻意区分 |
embodiment_tag | "new_embodiment" | 训练使用的具身标签,如new_embodiment、gr1、libero_sim |
tune_llm/tune_visual/tune_projector/tune_diffusion_model/tune_vlln | False/False/True/True/True | 各部分是否微调:LLM 骨干、视觉塔、投影器、扩散模型、VL LayerNorm+自注意力投影 |
tune_top_llm_layers | 0 | 仅解冻 LLM 骨干最后若干层(与tune_llm独立) |
num_inference_timesteps | None(沿用检查点值,N1.7 默认为 4) | 推理期 flow-matching 去噪步数 |
rtc_ramp_rate | None(检查点默认 6.0) | 实时分块(RTC)重叠混合斜率 |
use_flash_attention | False | 是否请求 flash-attention-2 内核,缺省透明回退到数值等价的 SDPA |
use_relative_actions/relative_exclude_joints | False/[] | 是否启用 GR00T 式状态相对动作块;relative_exclude_joints指定保持绝对值的维度(如["gripper"]) |
optimizer_lr/optimizer_betas/optimizer_weight_decay | 1e-4/(0.9, 0.999)/1e-5 | 与 Isaac-GR00T N1.7 微调配方一致(AdamW) |
use_bf16/model_params_fp32 | True/True | BF16 autocast 计算、FP32 参数(原生 N1.7 配方) |
值得强调的设计点是normalization_mapping:GR00T 在自身的 processor 步骤内部完成状态/动作归一化(按具身使用 min/max 或 q01/q99 百分位),Qwen3-VL 骨干的图像处理器负责图像归一化,因此策略不使用LeRobot 的NormalizerProcessorStep/UnnormalizerProcessorStep,该映射对每个特征都是IDENTITY。GrootConfig.get_optimizer_preset()返回 AdamW(grad_clip_norm=1.0),get_scheduler_preset()返回cosine调度(num_warmup_steps = ceil(max_steps * warmup_ratio),warmup 约 5%)。
GR00TN17 模型结构
groot_n1_7.py 实现了自包含的 N1.7 模型(不依赖外部gr00t包,但保持与公共检查点兼容):
Qwen3Backbone:包装 Hugging Face 的Qwen3VLForConditionalGeneration(基座nvidia/Cosmos-Reason2-2B)。构造时通过select_layer截断语言模型层数,支持tune_llm/tune_visual/tune_top_llm_layers的冻结策略;forward通过注册在最后一层解码器上的 hook 捕获末层 decoder 输出(_last_decoder_layer_output),这是跨 transformers 版本保持动作头输入稳定的关键。GR00TN17ActionHead:flow-matching 动作头。state_encoder/action_decoder使用CategorySpecificMLP(按具身类别区分权重的线性层),action_encoder是MultiEmbodimentActionEncoder(类别特定投影 + 正弦时间编码);核心去噪网络是AlternateVLDiT(或DiT,cross_attention_dim=backbone_embedding_dim=2048),配合vlln(LayerNorm)与vl_self_attention处理骨干特征。- 训练时
forward按 flow-matching 范式加噪:noisy_trajectory = (1-t)*noise + t*actions、velocity = actions - noise,时间步t从 Beta 分布Beta(1.5, 1.0)采样并乘以noise_s=0.999,损失为带action_mask的 MSE。 - 推理时
get_action执行 Euler 积分去噪:从纯噪声torch.randn(B, action_horizon, action_dim)出发,步长为dt = 1/num_inference_timesteps,每步用当前去噪网络预测的 velocity 更新actions;返回的action_pred即归一化空间中的原始 flow-matching 预测——这正是 parity 测试比对的对象。
前处理/后处理管线
processor_groot.py 中的GrootN17PackInputsStep、GrootN17VLMEncodeStep、GrootN17ActionDecodeStep等步骤构成 GR00T 专属管线:从原生 N1.7 检查点的processor_config.json/statistics.json/embodiment_id.json读取预处理与动作解码选择(_GrootN17CheckpointProcessorAssets),将 checkpoint 中按语义分组的统计量(EEF 位姿、关节等)展平为 LeRobot 单一向量统计,并负责状态/动作的 min-max 或百分位归一化、clip_outliers裁剪、语言指令的 Qwen3-VL chat template 格式化、图像打包与动作块解码(含 LIBERO gripper 动作符号转换)。
Original-vs-LeRobot parity test 详解
文档正文的技术核心是tests/policies/groot/test_groot_vs_original.py所实现的parity test:验证 LeRobot 对 GR00T N1.7(Qwen3-VL 骨干 + flow-matching 动作头)的重实现与 NVIDIA 原版gr00t包在数值上一致。测试对检查点中出现的每一个 embodiment tag参数化展开,包含两个对比维度。
维度一:模型级 parity(Model parity)
给定字节级一致的前处理输入(即原版 processor 产出的input_ids、attention_mask、pixel_values、image_grid_thw、state、embodiment_id)与相同的 flow-matching 随机种子(记录在产物中),两侧实现必须产生完全相同的原始模型输出get_action(...)["action_pred"](归一化后的 flow-matching 预测)。输出形状必须精确匹配,任何 action-horizon 或 action-dim 的不一致都会导致测试失败。
对应到源码,test_groot_vs_original.py 中的test_groot_get_action_parity用_load_artifact读取.npz中in::前缀的输入张量,_unflatten还原嵌套字典,然后在torch.inference_mode()下调用lerobot_model.get_action(model_inputs),将输出与action_pred比对;测试先按min(original, lerobot)截齐两个时间/维度轴,再打印max|diff|与mean|diff|并断言torch.allclose(..., atol, rtol)。
维度二:前处理级 parity(Preprocessor parity)
给定完全相同的原始观测(各相机帧、状态向量、语言指令),LeRobot 自己的前处理管线(真实的 Qwen3-VL chat template / tokenizer / 图像打包 + 检查点驱动的状态归一化,不使用任何 mock)必须产出与原版 processor相同的 collated 模型输入(input_ids、attention_mask、pixel_values、image_grid_thw、state、embodiment_id)。
这两条测试路径互为补充:模型级 parity 隔离了"模型本身",前处理级 parity 则单独覆盖了 LeRobot 自己的 tokenization / 图像打包实现。
为什么需要两个虚拟环境
原版gr00t包将依赖锁定在transformers==4.57.3(Python 3.10);而本集成需要transformers>=5.x(以支持 Qwen3-VL)。在 5.x 下,PretrainedConfig本身就是一个带默认值的 dataclass,导致原版配置 dataclass 无法导入(报non-default argument follows default argument)。因此两个实现无法在同一个 Python 进程中同时导入。
为解决这一矛盾,测试采用producer / consumer 双虚拟环境拆分:
- Producer(生产端)——dump_original_n1_7.py,运行在原版 gr00t 虚拟环境中。对每个具身标签,它从检查点元数据通用地构建 dummy 输入(状态维度来自
statistics.json;相机/语言键来自 processor 的 modality 配置,绝不针对某个 tag 硬编码),运行原版模型,并把以下内容保存为一个.npz:- 原始观测(
raw::前缀键); - 精确的 collated 输入(
in::前缀键); - 随机种子;
- 原始
action_pred。
- 原始观测(
- Consumer(消费端)——即上述 pytest,运行在LeRobot 虚拟环境中。它自动发现每个
.npz:模型级 parity 用例用记录的种子重放字节级一致的输入并断言输出一致;前处理级 parity 用例则用原始观测跑完整的 LeRobot 前处理管线,断言 collated 张量一致。
兼容性注意:由旧版本 dump 脚本生成的产物不含
raw::字段,此时前处理级 parity 用例会跳过并提示重新生成。重跑 producer 即可刷新产物。
dump_original_n1_7.py的具体运行参数:--ckpt(必需,检查点路径)、--out-dir(必需,.npz输出目录)、--tags(可选,逗号分隔的具身标签,默认导出检查点统计中的全部标签)、--device(默认cuda)、--seed(默认 42)。它内部加载一次Gr00tPolicy(用于 processor/预处理)与一个fair model(AutoModel.from_pretrained时强制use_flash_attention=False、load_bf16=False,并转 fp32),逐 tag 调用policy.processor(...)+policy.collate_fn(...)获得 collated 输入后运行fair_model.get_action(**collated)。
公平性控制(Fairness controls)
文档明确列出了三条保证对拍公平性的控制手段,源码中均有对应实现:
- 相同的前处理输入(模型级 parity):原版 processor 的
input_ids、pixel_values、image_grid_thw、attention_mask、state、embodiment_id被原样喂给 LeRobot 模型(不做任何重新 tokenize / 重新归一化),从而模型比较只隔离模型本身;LeRobot 自己的 tokenization/图像打包由前处理级 parity 用例单独覆盖。 - 相同的精度与注意力内核:两侧都运行fp32 + SDPA。原版默认
use_flash_attention=True(flash_attention_2 + bf16);producer 强制 SDPA + fp32。(若使用默认配置,差距约 3e-2——这纯粹是内核/舍入噪声,而非实现差异。)对应在 consumer 端,test_groot_vs_original.py 的lerobot_modelfixture 中设置model.compute_dtype = "float32"、model.to(device=DEVICE, dtype=torch.float32)。 - 相同的 flow-matching 种子:两侧在采样前固定随机种子;producer 将种子记录进每个产物(
--seed,默认 42),consumer 重放记录值。对应实现为测试中的torch.manual_seed(SEED)与torch.cuda.manual_seed_all(SEED)。
如何运行
原文档给出了完整的两步运行流程(先 producer 后 consumer):
# 解析本地检查点(GR00T-N1.7-LIBERO / libero_10) CKPT=$(python - <<'PY' import os from huggingface_hub import snapshot_download print(os.path.join(snapshot_download("nvidia/GR00T-N1.7-LIBERO", allow_patterns=["libero_10/*"]), "libero_10")) PY ) # 1) 为所有具身标签生成原版侧产物(原版 gr00t 虚拟环境,CUDA) CUDA_VISIBLE_DEVICES=0 /path/to/Isaac-GR00T/.venv-original/bin/python \ tests/policies/groot/utils/dump_original_n1_7.py \ --ckpt "$CKPT" --out-dir tests/policies/groot/artifacts --device cuda --seed 42 # 2) 运行 parity 测试(LeRobot 虚拟环境)——每个具身标签一个参数化用例 CUDA_VISIBLE_DEVICES=0 GROOT_PARITY_DEVICE=cuda \ uv run pytest tests/policies/groot/test_groot_vs_original.py -v -s关键约束与事实:
.npz产物仅存在于本地(gitignored,每个约 6–10 MB),由 producer 重新生成,永远不会被提交。- 测试在 CI 或检查点/产物缺失时跳过(skip)而不会失败:文件顶部的
pytestmark在CI == "true"或GITHUB_ACTIONS == "true"时直接跳过;_discover_artifacts()找不到产物时通过skipif跳过并提示先运行 producer;_resolve_checkpoint()用local_files_only=True的snapshot_download解析检查点,失败同样跳过。 - 产物文件命名约定为
original_n1_7_<embodiment_tag>.npz,测试按前缀original_n1_7_发现全部产物并自动参数化。
环境变量开关(全部可选)
原文档给出了一张完整的环境变量表,整理如下:
| 变量 | 默认值 | 用途 |
|---|---|---|
GROOT_N1_7_PARITY_DIR | tests/policies/groot/artifacts | 每标签.npz产物的目录 |
GROOT_N1_7_LIBERO_CKPT | 自动(HF 缓存) | 覆盖检查点目录 |
GROOT_PARITY_DEVICE | 可用时cuda | cpu或cuda |
GROOT_PARITY_ATOL/GROOT_PARITY_RTOL | 1e-3 | 对比容差 |
这些变量在测试文件头部直接读取:DEVICE = os.environ.get("GROOT_PARITY_DEVICE", "cuda" if torch.cuda.is_available() else "cpu"),ATOL/RTOL同理,均带1e-3默认值。
相关测试矩阵:围绕 N1.7 的完整质量保障
parity 测试只是tests/policies/groot/下的测试家族之一,其余测试从不同侧面保证 N1.7 集成的正确性,可作为深入阅读的入口:
- test_groot_n1_7.py:覆盖配置默认值(
chunk_size=40、max_state_dim=132等)、N1.5 别名拒绝、LIBERO 动作解码转换、原始 N1.7 检查点 processor 资产加载、相对动作统计、RTC 前缀处理与动作块截断(test_groot_n1_7_predict_action_chunk_truncates_to_checkpoint_valid_horizon断言 LIBERO 检查点只输出 16 步有效动作)。 - test_groot_lerobot.py、test_groot_state_dropout.py、test_groot_train_random_crop.py、test_groot_training_optim_contract.py:分别覆盖 LeRobot 包装层、状态丢弃正则化、随机裁剪增强与优化器契约。
- test_groot_n1_7_oss_parity.py:N1.7 开放源码侧的额外一致性校验。
结论与实操要点
围绕docs/source/policy_groot_README.md,可将关键结论归纳如下:
- 版本唯一性:LeRobot 当前仅支持 GR00T N1.7;N1.5 会被拒绝并提示
pip install 'lerobot==0.5.1'或迁移到 N1.7(nvidia/GR00T-N1.7-3B),相关逻辑集中在 configuration_groot.py。 - parity 测试是"双保险":模型级 parity 用字节级一致的输入隔离验证模型权重与 forward 计算;前处理级 parity 用完全相同的原始观测验证 LeRobot 全链路前处理(真实 Qwen3-VL tokenizer/图像打包 + 检查点统计归一化,无 mock)。
- 双环境 producer/consumer 是必然选择:
transformers==4.57.3(原版 gr00t)与transformers>=5.x(LeRobot 需要 Qwen3-VL)无法同进程共存,因此必须先在原版环境中 dump 产物,再到 LeRobot 环境消费比对。 - 公平性三要素:同输入、同精度与注意力内核(fp32 + SDPA)、同 flow-matching 种子(默认 42),三者缺一不可,否则 3e-2 量级的内核/舍入噪声会掩盖真实差异。
- 可复现路径:按上文"如何运行"一节的两条命令即可复现;产物仅本地存在且测试在 CI 上安全跳过(skip 而非 fail),不会阻塞无本地 GPU 的持续集成。
若要在自己的数据上微调 GR00T N1.7,可参考 groot.mdx 中lerobot-train的完整命令(--policy.type=groot、--policy.base_model_path=nvidia/GR00T-N1.7-3B、--policy.embodiment_tag=new_embodiment、--policy.use_relative_actions=true、--policy.relative_exclude_joints='["gripper"]'等);而无论训练还是评估,parity 测试所验证的"模型与前处理均与原版数值一致"都是这套工作流可信赖的前提。
【免费下载链接】lerobot🤗 LeRobot: Making AI for Robotics more accessible with end-to-end learning项目地址: https://gitcode.com/GitHub_Trending/le/lerobot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考