LeRobot documentation

X-VLA:首个面向任意机器人、任意任务的软提示机器人基础模型

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

X-VLA:首个面向任意机器人、任意任务的软提示机器人基础模型

概述

多年来,机器人领域一直致力于构建能够遵循自然人类指令、并在多种环境和多种机器人本体上灵巧操作的智能体。大语言模型(LLM)和视觉语言模型(VLM)近期的突破指明了一条前进之路:将这些基础模型架构扩展到具身控制领域,使其以动作为基础。这推动了视觉-语言-动作(VLA)模型的兴起,人们期望一个通用的模型能够将广泛的语义理解能力与稳健的操作技能结合起来。

但训练此类模型颇具挑战。机器人数据分散在不同的平台、传感器、本体形态和数据采集协议中。异构性无处不在:不同的机械臂构型、不同的动作空间、不同的相机配置、不同的视觉域以及不同的任务分布。这些不一致性造成了严重的分布偏移,使得预训练过程不稳定,且模型适配不可靠。

受元学习和提示学习的启发,我们提出这样一个问题:“如果 VLA 模型能够像 LLM 通过提示学习任务一样,通过提示来学习每个机器人和数据集的结构,会怎样?”

X-VLA 是一个基于软提示和流匹配的 VLA 框架,它将每种硬件配置视为一个“任务”,并使用一组可学习的嵌入对其进行编码。这些 Soft Prompts 捕获了具身智能体和特定领域的差异,从多模态融合的最初阶段开始引导 Transformer。借助这一机制,X-VLA 能够在单一统一架构中协调多样的机器人形态、数据类型和传感器配置。

XVLA Architecture

X-VLA 完全基于 Transformer 编码器构建,能够随着模型规模和数据集多样性的增加而自然扩展。在 6 个仿真基准测试和 3 台真实机器人上,Soft Prompts 在处理硬件和领域差异方面始终优于现有方法。X-VLA-0.9B 在涵盖七种机器人平台的 29 万个回合(episodes)上进行训练,在阶段 I 中学习了与具身无关的通用策略,并在阶段 II 中通过仅学习一组新的提示(prompts)即可高效适应新机器人,同时保持骨干网络冻结。

XVLA Architecture 2

在仅微调 1% 的参数(9M)的情况下,X-VLA-0.9B 在 LIBERO 和 Simpler-WidowX 上实现了接近 π₀ 的性能,尽管其使用的可训练参数数量减少了 300 倍。此外,它仅凭极少的演示就展现了强大的真实世界灵巧性,包括在不到两分钟内完成折叠布料。

XVLA fold visualization

X-VLA 表明,通用机器人智能并不依赖于日益复杂的架构,而关键在于吸收异构性的正确方式。Soft Prompts 提供了一种简单且可扩展的机制,用于统一多样化的机器人数据,为构建可适应、跨具身的机器人基础模型铺平了道路。

安装

安装 LeRobot 后,安装 X-VLA 的依赖项:

pip install -e ".[xvla]"

如果您是从 PyPI 安装的 LeRobot:

pip install 'lerobot[xvla]'

快速入门

基本用法

要在您的 LeRobot 配置中使用 X-VLA,请将策略类型指定为:

policy.type=xvla

评估预训练检查点

使用 LIBERO 进行示例评估:

lerobot-eval \
  --policy.path="lerobot/xvla-libero" \
  --env.type=libero \
  --env.task=libero_spatial,libero_goal,libero_10 \
  --env.control_mode=absolute \
  --eval.batch_size=1 \
  --eval.n_episodes=1 \
  --env.episode_length=800 \
  --seed=142

可用检查点

🎯 基础模型

lerobot/xvla-base

X-VLA 的 0.9B 参数实例,采用精心设计的处理与学习方案进行训练。训练流程包含两个阶段:

  • 阶段 I:预训练 - 基于来自 Droid、Robomind 和 Agibot 的 290K 个 episode 进行预训练,涵盖五种机械臂类型(从单臂到双臂配置)下的七个平台。通过利用软提示(soft prompts)来吸收具身特定的差异,该模型学习到一个与具身无关的通用策略。

  • 第二阶段:领域适应 - 针对目标领域调整为可部署的策略。引入一组新的软提示(soft prompts)并进行优化,以编码新领域的硬件配置,同时保持预训练骨干网络冻结。

模拟检查点

lerobot/xvla-libero

在 LIBERO 基准测试中达到 93% 的成功率。针对模拟任务从基础模型微调而来。

lerobot/xvla-widowx

在 BridgeData 上进行了微调,用于在紧凑型 WidowX 平台上进行拾取和放置实验。展示了强大的操作能力。

🤖 真实场景检查点

lerobot/xvla-folding

在高质量 Soft-FOLD 布料折叠数据集上训练的灵巧操作微调模型。在连续 2 小时的布料折叠任务中实现了 100% 的成功率。

lerobot/xvla-agibot-world

针对 AgileX 机器人的灵巧操作任务进行了优化。

lerobot/xvla-google-robot

已适配 Google Robot 平台。

训练 X-VLA

推荐的训练配置

在为新的本体或任务微调 X-VLA 时,我们建议不要冻结 VLM,并将 policy.dtype=bfloat16 设置为 bfloat16,以避免出现 OOM 错误。

lerobot-train \
  --dataset.repo_id=YOUR_DATASET \
  --output_dir=./outputs/xvla_training \
  --job_name=xvla_training \
  --policy.path="lerobot/xvla-base" \
  --policy.repo_id="HF_USER/xvla-your-robot" \
  --policy.dtype=bfloat16 \
  --policy.action_mode=auto \
  --steps=20000 \
  --policy.device=cuda \
  --policy.freeze_vision_encoder=false \
  --policy.freeze_language_encoder=false \
  --policy.train_policy_transformer=true \
  --policy.train_soft_prompts=true

训练参数详解

参数默认描述
freeze_vision_encoderfalse不要冻结 VLM 视觉编码器的权重
freeze_language_encoderfalse不要冻结 VLM 语言编码器的权重
train_policy_transformertrue允许策略转换器层进行训练
train_soft_promptstrue允许训练软提示

💡 最佳实践:对于针对新实例的 Phase II 适配,不要冻结 VLM 编码器,同时训练策略 Transformer 和软提示。

示例:在双手机器人上进行训练

lerobot-train \
  --dataset.repo_id=<USER>/bimanual-so100-handover-cube \
  --output_dir=./outputs/xvla_bimanual \
  --job_name=xvla_so101_training \
  --policy.path="lerobot/xvla-base" \
  --policy.dtype=bfloat16 \
  --policy.repo_id="YOUR_USERNAME/xvla-biso101" \
  --steps=3000 \
  --policy.device=cuda \
  --policy.action_mode=so101_bimanual \
  --policy.freeze_vision_encoder=false \
  --policy.freeze_language_encoder=false \
  --policy.train_policy_transformer=true \
  --policy.train_soft_prompts=true

💡 最佳性能: 如果您拥有充足的计算资源并希望实现最佳的 X-VLA 微调性能,请遵循官方的微调策略:

🔥 使用自定义学习率方案对所有组件进行全量微调

为确保优化过程稳定,视觉语言模型(VLM)必须以基础学习率的 1/10 进行训练,而其他所有组件则使用完整的学习率。 该学习率比例对于实现强劲且稳定的微调性能至关重要。默认情况下已为您完成此设置。 ❕注意

要完全匹配官方报告的性能,可能还需要为 soft-prompts 添加额外的预热学习率调度,这可以带来微小的性能提升。 我们建议将此实现到您自定义的训练流程中,以获得最佳效果。

核心概念

1. 操作模式

X-VLA 使用 Action Registry 系统来处理不同的动作空间和具身形态。action_mode 参数定义了动作的处理方式、所使用的损失函数以及预测结果的后期处理方法。

可用的操作模式

操作模式动作维度描述用例
ee6d20带有 xyz、6D 旋转和夹爪的末端执行器具有空间控制的双臂配置
joint14带夹爪的关节空间直接关节控制机器人
agibot_ee6d20采用 MSE 损失的 AGI-bot 变体AGI-bot 平台
so101_bimanual20(模型),12(实际)SO101 双臂机器人双手操作任务
auto20(模型),auto(真实)自动从数据集中检测动作维度适用于新机器人的推荐

为什么操作模式很重要

当您拥有一个使用 action_dim=20 训练的预训练检查点(例如 lerobot/xvla-base),并希望在一个具有不同动作维度(例如,双臂为 14)的数据集上进行训练时,您不能简单地裁剪动作维度。动作模式负责协调:

  1. 损失计算:针对不同动作分量使用不同的损失函数(关节使用 MSE,夹爪使用 BCE 等)
  2. 预处理:将夹爪通道置零,填充维度
  3. 后处理:对夹爪 logits 应用 sigmoid,去除填充

示例:BimanualSO101 动作空间

so101_bimanual 动作模式处理模型输出(20D)与真实机器人控制(12D)之间的不匹配:

# Model outputs 20 dimensions for compatibility
dim_action = 20

# Real robot only needs 12 dimensions
# [left_arm (6), right_arm (6)] = [joints (5) + gripper (1)] × 2
REAL_DIM = 12

# Preprocessing: Pad 12D actions to 20D for training
# Postprocessing: Trim 20D predictions to 12D for deployment

有关详细信息,请参阅 action_hub.py 的实现。

自动操作模式(推荐)

auto 操作模式是使用 X-VLA 控制任意机器人的最简单方式。它会自动检测数据集的操作维度,并处理填充/裁剪:

lerobot-train \
  --policy.path="lerobot/xvla-base" \
  --policy.action_mode=auto \
  --policy.max_action_dim=20 \
  ...

工作原理:

  • 从您的数据集中读取 action_feature.shape[-1](例如,Franka 为 7)
  • 模型输出 max_action_dim(默认值为 20)以兼容预训练模型
  • 损失仅在真实维度上计算:MSE(pred[:,:,:real_dim], target[:,:,:real_dim])
  • Postprocess 将输出裁剪回 real_dim 以用于机器人控制

这消除了为大多数机器人创建自定义操作模式的需要。

2. 域 ID

Domain ID 是用于不同机器人配置和相机设置的、可学习的标识符。它们使 X-VLA 能够区分:

  • 不同的机器人(机器人 1 与机器人 2)
  • 不同的相机配置(cam1 与 cam2)
  • 不同的组合(Robot1-cam1-cam2 与 Robot1-cam1 与 Robot2-cam1)

设置域 ID

训练期间:默认情况下,通用训练的 domain_id 设置为 0。

评估期间:指定与检查点的训练配置相匹配的 domain_id。

# Example: LIBERO checkpoint uses domain_id=3
domain_id = 3

XVLAAddDomainIdProcessorStep 会在预处理流水线中自动将 domain_id 添加到观测数据中。

lerobot/xvla-base 模型已在以下领域 ID 上进行训练。建议选择与您的机器人/配置最相似的一个:

微调数据集

数据集名称Domain ID
桥接0
RT11
Calvin2
libero3
widowx-air4
AIR-AGILEX-HQ5
robotwin2_abs_ee6
robotwin2_clean6
robocasa-human7
VLABench8
AGIBOT-challenge9
AIR-AGILEX10
AIRBOT18

3. 处理器步骤

X-VLA 需要特定的预处理和后处理步骤才能正常运行。

必需的预处理步骤

  1. XVLAImageToFloatProcessorStep:将图像从 [0, 255] 范围转换为 [0, 1] 范围
  2. XVLAImageNetNormalizeProcessorStep:应用 ImageNet 归一化(VLM 骨干网络所必需)
  3. XVLAAddDomainIdProcessorStep:向观测数据中添加 domain_id

自定义处理器示例

对于 LIBERO 环境,一个自定义处理器会将标准观测值转换为 X-VLA 训练时所使用的输入:

from lerobot.policies.xvla.processor_xvla import LiberoProcessorStep

processor = LiberoProcessorStep()
# Builds the 9D state from the canonical 8D state, with the end-effector rotation in 6D
# Rotates the wrist camera back, since the LIBERO integration rotates every camera by 180°

4. 配置参数

X-VLA 的关键配置参数:

# Observation and action
n_obs_steps: int = 1          # Number of observation timesteps
chunk_size: int = 32           # Action sequence length
n_action_steps: int = 32       # Number of action steps to execute

# Model architecture
hidden_size: int = 1024        # Transformer hidden dimension
depth: int = 24                # Number of transformer layers
num_heads: int = 16            # Number of attention heads
num_domains: int = 30          # Maximum number of domain IDs
len_soft_prompts: int = 32     # Length of soft prompt embeddings

# Action space
action_mode: str = "ee6d"      # Action space type (use "auto" for auto-detection)
use_proprio: bool = True       # Use proprioceptive state
max_state_dim: int = 32        # Maximum state dimension
max_action_dim: int = 20       # Max action dim for padding (used by "auto" mode)

# Vision
num_image_views: int | None    # Number of camera views
resize_imgs_with_padding: tuple[int, int] | None  # Target image size with padding

# Training
num_denoising_steps: int = 10  # Flow matching denoising steps

创建自定义操作模式

如果您的机器人具有独特的动作空间,您可以创建一个自定义的动作模式:

步骤 1:定义您的动作空间

from lerobot.policies.xvla.action_hub import BaseActionSpace, register_action
import torch
import torch.nn as nn

@register_action("my_custom_robot")
class MyCustomActionSpace(BaseActionSpace):
    """Custom action space for my robot."""

    dim_action = 15  # Your robot's action dimension
    gripper_idx = (7, 14)  # Gripper channel indices

    def __init__(self):
        super().__init__()
        self.mse = nn.MSELoss()
        self.bce = nn.BCEWithLogitsLoss()

    def compute_loss(self, pred, target):
        """Define your loss computation."""
        # Example: MSE for joints, BCE for grippers
        joints_loss = self.mse(pred[:, :, :7], target[:, :, :7])
        gripper_loss = self.bce(pred[:, :, self.gripper_idx],
                                target[:, :, self.gripper_idx])

        return {
            "joints_loss": joints_loss,
            "gripper_loss": gripper_loss,
        }

    def preprocess(self, proprio, action, mode="train"):
        """Preprocess actions before training."""
        # Example: Zero out grippers in proprioception
        proprio_m = proprio.clone()
        action_m = action.clone() if action is not None else None
        proprio_m[..., self.gripper_idx] = 0.0
        if action_m is not None:
            action_m[..., self.gripper_idx] = 0.0
        return proprio_m, action_m

    def postprocess(self, action):
        """Post-process predictions for deployment."""
        # Example: Apply sigmoid to gripper logits
        action[..., self.gripper_idx] = torch.sigmoid(action[..., self.gripper_idx])
        return action

步骤 2:使用您的自定义操作模式

lerobot-train \
  --policy.action_mode=my_custom_robot \
  --dataset.repo_id=YOUR_DATASET \
  --policy.path="lerobot/xvla-base" \
  ...

高级主题

多摄像头支持

X-VLA 通过 num_image_views 参数支持多个相机视角:

# Configure for 3 camera views
policy.num_image_views=3

# Add empty cameras if you have fewer physical cameras
policy.empty_cameras=1  # Adds 1 zero-padded camera view

自定义预处理流水线

为您的环境创建自定义预处理流水线:

from lerobot.processor import PolicyProcessorPipeline
from lerobot.policies.xvla import (
    XVLAImageToFloatProcessorStep,
    XVLAImageNetNormalizeProcessorStep,
    XVLAAddDomainIdProcessorStep,
)

# Build custom pipeline
preprocessor = PolicyProcessorPipeline(
    steps=[
        YourCustomProcessorStep(),  # Your custom processing
        XVLAImageToFloatProcessorStep(),  # Required: convert to float
        XVLAImageNetNormalizeProcessorStep(),  # Required: ImageNet norm
        XVLAAddDomainIdProcessorStep(domain_id=5),  # Your domain ID
    ]
)

处理不同的动作维度

当您的数据集的动作维度少于预训练模型时:

选项 1(推荐):使用 auto 操作模式

# Automatically detects your dataset's action dimension
# Works with any robot without custom code
policy.action_mode=auto
policy.max_action_dim=20  # Match pretrained model

选项 2:使用内置填充的预定义操作模式

# Model expects 20D, dataset has 12D
# Action mode handles padding internally
action_mode = "so101_bimanual"  # Pads 12 → 20

选项 2:创建一个自定义操作模式,显式地映射维度

@register_action("my_mapped_action")
class MappedActionSpace(BaseActionSpace):
    dim_action = 20
    REAL_DIM = 12

    def _pad_to_model_dim(self, x):
        # Custom padding logic
        ...

故障排除

常见问题

问题:“动作维度不匹配”

  • 解决方案:检查您的 action_mode 是否与机器人的动作空间匹配。如有需要,请创建自定义的动作模式。

问题:“图像值超出 [0, 1] 范围”

  • 解决方案:确保在归一化之前使用 XVLAImageToFloatProcessorStep 对图像进行预处理。

问题:“未找到域 ID”

  • 解决方案:确保 XVLAAddDomainIdProcessorStep 位于您的预处理流水线中,并且 domain_id 正确。

问题:“在新具身环境中的成功率较低”

  • Solution:
    1. 验证您的 action_mode 是否正确
    2. 检查软提示是否正在被训练(train_soft_prompts=True)
    3. 确保进行正确的预处理(ImageNet 归一化、domain_id)
    4. 考虑增加训练步数

问题:“训练期间内存不足”

  • Solution:
    1. 将 chunk_size 减小(例如,从 32 减至 16)
    2. 启用梯度检查点
    3. 减小批量大小
    4. 冻结更多组件

引用

如果您在研究中使用 X-VLA,请引用:

@article{zheng2025x,
  title   = {X-VLA: Soft-Prompted Transformer as Scalable Cross-Embodiment Vision-Language-Action Model},
  author  = {Zheng, Jinliang and Li, Jianxiong and Wang, Zhihao and Liu, Dongxiu and Kang, Xirui
             and Feng, Yuchun and Zheng, Yinan and Zou, Jiayin and Chen, Yilun and Zeng, Jia and others},
  journal = {arXiv preprint arXiv:2510.10274},
  year    = {2025}
}

其他资源

贡献

我们欢迎贡献!如果您已为您的机器人实现了新的动作模式或处理器,请考虑提交 PR 以帮助社区。

Update on GitHub