← 返回 VLA 技术站

OpenVLA

Open-Source Vision-Language-Action Model · 7.5B 参数 · 斯坦福 + 伯克利

核心思路

设计哲学:动作即语言

OpenVLA 的核心洞察是将连续的机器人动作离散化为 LLM 的 token,让 VLM 直接像「说下一个词」一样输出动作。这样就能完整复用标准 LLM 的 next-token prediction 训练范式——无需额外的扩散头或回归头,任何 LLM 训练/推理基础设施都能直接用。

站在巨人肩上

不重新发明轮子,而是复用互联网规模预训练的 VLM(视觉-语言模型)作为「大脑」。VLM 已经从海量图文数据中学到了丰富的视觉理解和语言推理能力,这些知识可直接迁移到机器人操控任务。在 VLM 之上嫁接动作输出能力,是 OpenVLA 的基本策略。

要解决的问题

此前 VLA 模型(如 RT-2/RT-2-X)由 Google 闭源,公众无法获取权重、无法微调、无法二次开发。OpenVLA 的目标是打造完全开源、可直接微调、在消费级 GPU 上可运行的通用机器人操控策略模型。

核心成果:7.5B 参数的 OpenVLA 在 29 个任务上,绝对成功率比 55B 参数的闭源 RT-2-X 高 16.5%(参数少 7 倍);比 Diffusion Policy 高 20.4%

技术方案特点

模型架构

构建在 Prismatic VLM 框架之上,由三大组件融合而成:

┌──────────────────────────────────────────────────┐ │ OpenVLA (7.5B) │ │ │ │ ┌──────────────┐ ┌───────────────┐ │ │ │ DINOv2 ViT-L │ │ SigLIP-SO400M │ ← 双编码器 │ │ │ (reg4, 224px)│ │ (So400M, 224) │ 融合 │ │ └──────┬───────┘ └───────┬───────┘ │ │ │ 256 tokens │ 256 tokens │ │ └────────┬───────────┘ │ │ 序列拼接 → 512 图像 token │ │ │ │ │ ┌────────▼────────┐ │ │ │ MLP Projector │ ← 3层GELU投影 │ │ └────────┬────────┘ │ │ ┌────────▼──────────────┐ │ │ │ Llama-2-7B (base LLM) │ │ │ │ next-token prediction │ │ │ └───────────────────────┘ │ └──────────────────────────────────────────────────┘
组件配置说明
视觉编码器DINOv2 ViT-L + SigLIP-SO400M224×224px,patch=14,各出 256 token,序列拼接成 512 token
LLM 基座Llama-2-7B(base 版)非 chat 版,纯 base model
投影层3 层 MLP + GELULinear(1024→4096) → GELU → Linear(4096→4096) → GELU → Linear(4096→4096)
为什么选双编码器?SigLIP 提供强语义/语言对齐特征,DINOv2 提供强空间/几何细节特征,两者互补。实验证明融合双编码器显著优于单一编码器。

输入输出格式

输入:

# 语言指令 prompt 格式
prompt = "In: What action should the robot take to {INSTRUCTION}?\nOut:"
# 例: "In: What action should the robot take to pick up the red block?\nOut:"

输出:7 维连续动作向量(末端执行器增量)

action = [dx, dy, dz, droll, dpitch, dyaw, gripper]  # 7-DoF

动作表达方式:256-bin 离散化 Token

这是 OpenVLA 的核心设计——不输出连续值,而是将动作离散化为 token

  1. 每个动作维度均匀分成 256 个 binbins = np.linspace(-1, 1, 256)
  2. 动作值归一化到 [-1, 1],digitize 映射到 bin index
  3. 256 个 bin 映射到 LLM 词表的最后 256 个 token
  4. 7-DoF 动作 = 7 个 token,推理时 generate(max_new_tokens=7)
# 核心逻辑(prismatic/vla/action_tokenizer.py)
self.action_token_begin_idx = tokenizer.vocab_size - (n_bins + 1)

# 编码:连续动作 → token ID
discretized_action = np.digitize(action, self.bins)
token_id = tokenizer.vocab_size - discretized_action

# 解码:token ID → 连续动作
discretized_actions = tokenizer.vocab_size - action_token_ids
continuous_action = bin_centers[discretized_actions - 1]

推理时反归一化:模型输出的归一化动作通过数据集的 q01/q99 分位数还原为真实物理量:

actions = 0.5 * (normalized_actions + 1) * (action_high - action_low) + action_low
# action_high = q99, action_low = q01

训练数据

指标数值
轨迹总数970K 条真实机器人演示
数据集组件~26 个 Open X-Embodiment 子数据集
主要数据集BridgeData V2、Google RT-1 (fractal)、DROID、KUKA、BC-Z 等
数据格式RLDS(Reinforcement Learning Datasets)
混合策略加权采样(前 70% 含 DROID 大权重,后 30% 不含 DROID)

代码框架

仓库结构

openvla/
├── prismatic/                     # 核心包
│   ├── models/
│   │   ├── vlms/prismatic.py      # PrismaticVLM 基类(VLM 主体)
│   │   ├── vlas/openvla.py        # ★ OpenVLA 类(predict_action)
│   │   └── backbones/
│   │       ├── vision/            # 视觉编码器(DINOv2, SigLIP)
│   │       └── llm/               # LLM 后端(Llama-2)
│   ├── vla/
│   │   ├── action_tokenizer.py    # ★ 动作离散化/反离散化核心
│   │   └── datasets/rlds/oxe/     # ★ OXE 数据加载管线
│   │       ├── configs.py         # 各数据集观测/动作空间配置
│   │       └── mixtures.py        # 数据混合权重定义
│   ├── extern/hf/                 # ★ HuggingFace 兼容层
│   │   ├── configuration_prismatic.py
│   │   ├── modeling_prismatic.py  # HF格式模型定义
│   │   └── processing_prismatic.py
│   └── conf/vla.py                # VLA 训练超参配置
├── vla-scripts/                   # ★ 训练/微调/部署脚本
│   ├── train.py                   # 全量训练(FSDP)
│   ├── finetune.py                # LoRA 微调
│   └── deploy.py                  # REST API 部署
└── experiments/robot/             # 机器人环境评测代码

核心模块

模块作用
OpenVLAPrismaticVLM 子类,封装 predict_action():构建 prompt → 预处理图像 → generate() → 解码 token → 反归一化
ActionTokenizer连续动作 ↔ 256 离散 token 双向转换,映射到词表末尾
OpenVLAForActionPredictionHF 格式完整模型,支持 AutoModelForVision2Seq 自动加载
RLDSDataset高性能 RLDS 数据管道,支持 shuffle buffer、图像增强、轨迹变换
PrismaticProjectorMLP 投影层,将视觉特征映射到 LLM 隐藏维度

微调流程

LoRA 微调(推荐,单卡可跑)

torchrun --standalone --nnodes 1 --nproc-per-node 1 vla-scripts/finetune.py \
  --vla_path "openvla/openvla-7b" \
  --data_root_dir <数据集根目录> \
  --dataset_name bridge_orig \
  --run_root_dir <日志/checkpoint目录> \
  --adapter_tmp_dir <LoRA权重临时目录> \
  --lora_rank 32 \
  --batch_size 16 \
  --grad_accumulation_steps 1 \
  --learning_rate 5e-4 \
  --image_aug True

关键参数:

全量微调(需 8×A100)

torchrun --standalone --nnodes 1 --nproc-per-node 8 vla-scripts/train.py \
  --pretrained_checkpoint <checkpoint路径> \
  --vla.type prism-dinosiglip-224px+mx-bridge \
  --data_root_dir <数据集目录> \
  --run_root_dir <日志目录> \
  --is_resume False

全量微调使用 PyTorch FSDP(Fully Sharded Data Parallel)分片训练,完成后需用 convert_openvla_weights_to_hf.py 转换为 HF 格式。

推理部署

方式一:直接加载推理(最简)

from transformers import AutoModelForVision2Seq, AutoProcessor
import torch

processor = AutoProcessor.from_pretrained("openvla/openvla-7b", trust_remote_code=True)
vla = AutoModelForVision2Seq.from_pretrained(
    "openvla/openvla-7b",
    torch_dtype=torch.bfloat16,
    low_cpu_mem_usage=True,
    trust_remote_code=True
).to("cuda:0")

action = vla.predict_action(**inputs, unnorm_key="bridge_orig", do_sample=False)

方式二:REST API 部署(适合机器人本体算力不足时远程推理)

# 服务端
python vla-scripts/deploy.py --openvla_path openvla/openvla-7b --port 8000

# 客户端(仅需 numpy + requests)
import requests, json_numpy, numpy as np
json_numpy.patch()
action = requests.post("http://SERVER:8000/act", json={
    "image": np.zeros((256, 256, 3), dtype=np.uint8),
    "instruction": "pick up the red block",
    "unnorm_key": "bridge_orig"
}).json()

快速上手

安装

# 最小依赖(仅推理)
pip install timm==0.9.10 tokenizers==0.19.1 torch>=2.2.0 torchvision>=0.16.0 transformers==4.40.1
⚠ 版本锁死:必须严格使用 transformers==4.40.1timm==0.9.10tokenizers==0.19.1,更高版本有 breaking change。

加载模型 + 推理(最短路径)

from transformers import AutoModelForVision2Seq, AutoProcessor
from PIL import Image
import torch, numpy as np

# 1. 加载 Processor 和模型
processor = AutoProcessor.from_pretrained("openvla/openvla-7b", trust_remote_code=True)
vla = AutoModelForVision2Seq.from_pretrained(
    "openvla/openvla-7b",
    torch_dtype=torch.bfloat16,
    low_cpu_mem_usage=True,
    trust_remote_code=True
).to("cuda:0")

# 2. 准备输入
image = Image.fromarray(np.zeros((256, 256, 3), dtype=np.uint8))  # 替换为相机图像
prompt = "In: What action should the robot take to pick up the red block?\nOut:"

# 3. 推理 → 7维动作向量
inputs = processor(prompt, image).to("cuda:0", dtype=torch.bfloat16)
action = vla.predict_action(**inputs, unnorm_key="bridge_orig", do_sample=False)
print(f"预测动作 (7-DoF): {action}")  # [dx,dy,dz,droll,dpitch,dyaw,gripper]

# 4. 发送给机器人执行
# robot.act(action)
unnorm_key 说明:指定用哪个数据集的归一化统计量做反归一化。微调后的模型使用微调数据集名;若模型只训练于单一数据集则可省略。

硬件需求

场景GPU 需求备注
推理(bf16)≥15GB 显存单卡 RTX 3090/4090 (24GB) 或 A10
推理(4-bit 量化)~8GB 显存论文证明量化推理不损失成功率
LoRA 微调≥27GB(batch=12 需 48GB)A100 40/80GB 最佳
全量微调8×A100 (80GB)FSDP 分片
从头预训练64×A100 (80GB)global_batch_size=2048

关键数字

指标数值
模型参数量7.5B
训练数据970K 条真机演示轨迹
基座 LLMLlama-2-7B(base)
视觉编码器DINOv2 ViT-L + SigLIP-SO400M,224×224px
图像 token 数512(双编码器各 256,序列拼接)
动作表达256-bin 离散化 token(每维度 1 个 token)
动作维度7-DoF(xyz + 旋转 + 夹爪)
词表大小32064(Llama-2 的 32000 + 64 padding)
vs RT-2-X (55B)绝对成功率高 16.5%,参数少 7×
许可MIT(模型继承 Llama Community License)
💡 工程建议:① 控制频率建议 5-10Hz(未用 action chunking);② 微调典型需要 ~100 条目标域演示数据;③ 避免采集停顿/微小动作(模型会在这些时刻「卡住」)。