OpenPi、GR00T的视觉语言模型与动作模型连接方式差异分析总结

VLA模型通常可以拆成两个逻辑模块:视觉语言模型动作生成模型,前者用于生成视觉语言语义特征,后者用于生成连续动作序列。

在OpenPi中,VLM并不是先完整运行一遍,再把最终特征交给动作模型。PaliGemma和Action Expert会在Transformer的每一层共同计算注意力。换句话说,OpenPi虽然也有两个模块,但在计算图上已经被编织成了一个整体。

GR00T则保留了明显的模块边界:Qwen3-VL先生成视觉语言Token,随后DiT把这些Token当成条件,通过Cross-Attention预测动作。

两者最核心的差异可以概括为:

对比项 OpenPi π0/π0.5 GR00T N1.7
VLM SigLIP + PaliGemma Cosmos-Reason2-2B,即Qwen3-VL结构
动作模型 Gemma Action Expert 独立的Diffusion Transformer
连接位置 每一层Transformer内部 VLM最终特征与DiT之间
连接机制 联合注意力、不同专家参数 Cross-Attention
VLM信息形态 逐层更新的Prefix K/V 固定的Backbone Features
状态输入 π0放在Action Expert;π0.5放入离散Prefix 单独的State Encoder
默认微调方式 支持全量或LoRA 默认冻结VLM,训练动作头
模块替换难度 较高 相对较低

OpenPi让VLM和Action Expert逐层交互

OpenPi中π0的主要实现位于,

复制代码
src/openpi/models/pi0.py
src/openpi/models/gemma.py

模型初始化时并不是创建一个PaliGemma,再在其后增加普通MLP动作头,而是同时创建两个Gemma配置:

复制代码
paligemma_config = get_config("gemma_2b")
action_expert_config = get_config("gemma_300m")

llm = GemmaModule(
    configs=[
        paligemma_config,
        action_expert_config,
    ]
)

第一个专家负责图像和语言,第二个专家负责状态、噪声动作以及扩散时间。两边使用不同的模型参数和隐藏层宽度。默认配置中,PaliGemma的宽度为2048,Action Expert的宽度为1024,但两者具有相同的层数、注意力头数量和Head Dimension,

复制代码
PaliGemma:18层,width=2048
Action Expert:18层,width=1024

共同配置:num_heads=8,head_dim=256,num_kv_heads=1

隐藏层宽度虽然不同,但两边都可以投影到相同的注意力空间。因此,OpenPi不需要先把VLM最终特征压缩成固定长度向量,也没有一个独立的VLM到动作模型投影层。输入首先被拆成Prefix和Suffix。Prefix是视觉语言部分,

复制代码
image_tokens = siglip(images)
language_tokens = gemma_embed(prompt)

prefix_tokens = concat(
    image_tokens,
    language_tokens,
)

Suffix是动作部分。以π0为例:

复制代码
state_token = state_proj(robot_state)
action_token = action_in_proj(noisy_action)
time_token = time_embedding(t)

suffix_tokens = concat(
    state_token,
    mix(action_token, time_token),
)

关键代码位于Gemma Attention中。两个专家先分别使用自己的参数计算Q、K、V,

复制代码
vlm_qkv = vlm_attention_proj(prefix_tokens)
action_qkv = action_attention_proj(suffix_tokens)

然后沿Token序列维度拼接,

复制代码
q = concat(vlm_q, action_q)
k = concat(vlm_k, action_k)
v = concat(vlm_v, action_v)
attention_output = attention(q, k, v, mask)

注意力计算完成后,再把结果按照Prefix和Suffix的长度切开,分别送入两个专家自己的输出投影和MLP,

复制代码
vlm_output = vlm_out_proj(
    attention_output[:, :prefix_len]
)

action_output = action_out_proj(
    attention_output[:, prefix_len:]
)

需要注意的是,按Prefix和Suffix切分得到的vlm_output与action_output并不是模型的最终结果,而是当前Transformer层中两条分支各自的注意力更新量。 两路结果会先分别经过各自的输出投影,再与进入当前层之前的隐藏状态做残差连接。随后,VLM Token和Action Token分别进入各自参数独立的MLP,得到下一层的输入。经过最后一层后,最终的Prefix Output不直接参与动作预测。模型只截取Suffix Output中对应Action Horizon的部分,并通过action_out_proj预测Flow Matching的速度场。Prefix分支作用在于训练时,Action Query在每一层读取VLM的Key/Value;推理时,这些逐层生成的Prefix Key/Value会被保存在KV Cache中,供每个去噪步骤中的Action Expert重复读取。

训练时,Prefix和Suffix会放在一次完整的前向计算中,

复制代码
(prefix_out, suffix_out) = model(
    [prefix_tokens, suffix_tokens],
    mask=asymmetric_attention_mask,
)

pred_velocity = action_out_proj(
    suffix_out[:, -action_horizon:]
)

Flow Matching只监督动作部分,

复制代码
x_t = t * noise + (1 - t) * action
target_velocity = noise - action

loss = mse(
    pred_velocity,
    target_velocity,
)

代码中没有为VLM单独增加文本生成损失。VLM是否更新取决于训练配置,既可以全量训练,也可以通过LoRA只更新部分注意力层和FFN。即使损失只计算在动作输出上,只要VLM参数没有被冻结,动作损失仍然可以通过联合注意力传回PaliGemma。

推理时,OpenPi会先运行一次图像和语言Prefix,并保存其KV Cache,

复制代码
prefix_output, kv_cache = vlm(prefix_tokens)

之后每一步去噪只重新计算Action Expert,

复制代码
for t in denoise_steps:
    suffix_tokens = embed_action(x_t, state, t)

    velocity = action_expert(
        suffix_tokens,
        past_key_values=kv_cache,
    )

    x_t = x_t + dt * velocity

说明OpenPi的VLM和动作专家虽然连接很深,但推理时不需要在每个Flow Matching Step中重复运行视觉编码器和完整PaliGemma。π0.5在连接方式上又做了两个调整,

第一,π0中机器人状态是Action Expert的连续State Token;π0.5会把状态离散化,并放入语言侧的Prefix。此时动作专家读取到的Prefix已经同时包含图像、指令和机器人状态。

第二,π0.5不再把时间编码直接与动作特征拼接,而是使用时间编码调制Action Expert中的AdaRMSNorm,

复制代码
π0:
Action Embedding + Time Embedding → MLP

π0.5:
Action Embedding → Action Expert
Time Embedding   → AdaRMSNorm

具体来看,在π0.5中,动作嵌入和时间嵌入不会直接拼接或相加。动作嵌入作为Action Expert的Token输入,时间嵌入则作为条件,调制Action Expert每个Transformer Block中的归一化和残差连接。

GR00T将VLM特征作为DiT的条件输入

源码实现如下,

复制代码
gr00t/model/modules/qwen3_backbone.py
gr00t/model/gr00t_n1d7/gr00t_n1d7.py
gr00t/model/modules/dit.py

GR00T的连接方式更加接近传统的Encoder---Decoder。首先,图像和语言指令进入Cosmos-Reason2-2B。该模型采用Qwen3-VL架构:

复制代码
outputs = qwen3_vl(
    input_ids=input_ids,
    pixel_values=pixel_values,
    image_grid_thw=image_grid_thw,
    output_hidden_states=True,
)

vl_features = outputs.hidden_states[-1]

返回结果仍然是一组Token,既包含文本Token,也包含图像Token。代码还通过image_token_id生成image_mask,用于区分两类信息,

复制代码
image_mask = input_ids == image_token_id

这些特征会先经过LayerNorm,以及可选的视觉语言Self-Attention,

复制代码
vl_features = vlln(vl_features)
vl_features = vl_self_attention(vl_features)

另一侧,机器人状态和噪声动作不进入VLM,而是由动作头独立编码,

复制代码
state_features = state_encoder(
    state,
    embodiment_id,
)

action_features = action_encoder(
    noisy_action,
    timestep,
    embodiment_id,
)

sa_features = concat(
    state_features,
    action_features,
)

sa_features是DiT的查询序列,vl_features是Cross-Attention的条件序列,

复制代码
model_output = dit(
    hidden_states=sa_features,
    encoder_hidden_states=vl_features,
    timestep=timestep,
)

两模块不要求隐藏层宽度一致。Cross-Attention内部会分别对DiT Query和VLM Key/Value做线性投影,因此更换VLM时,只要重新适配cross_attention_dim,不需要像OpenPi那样保证两个专家具有相同的层数、Head数量和Head Dimension。

GR00T N1.7默认使用AlternateVLDiT,其Transformer Block交替执行两种操作,

复制代码
Cross-Attention:动作Token读取VLM特征
Self-Attention: 状态和动作Token彼此交互

在Cross-Attention层中,又会根据image_mask交替读取文本和图像,

复制代码
第一个Cross-Attention Block:主要读取非图像Token
下一个Cross-Attention Block:主要读取图像Token
之后继续交替

对应的代码逻辑可以简化为,

复制代码
if current_block_attends_text:
    condition_mask = non_image_mask
else:
    condition_mask = image_mask

action_features = cross_attention(
    query=action_features,
    key=vl_features,
    value=vl_features,
    mask=condition_mask,
)

避免了动作Token在每一层都无差别地读取全部视觉语言序列,让语言约束和图像细节以不同节奏进入动作生成过程。

DiT最终输出会经过具身相关的Action Decoder,

复制代码
prediction = action_decoder(
    model_output,
    embodiment_id,
)

embodiment_id会同时进入State Encoder、Action Encoder和Action Decoder,把不同机器人之间的差异放在动作模型侧处理,而不是要求VLM理解每种机器人的具体关节定义。训练阶段同样使用Flow Matching,

复制代码
noisy_action = (1 - t) * noise + t * action
target_velocity = action - noise

prediction = action_head(
    vl_features,
    state,
    noisy_action,
    t,
)

loss = mse(prediction, target_velocity)

GR00T默认配置为,

复制代码
tune_llm = False
tune_visual = False

tune_projector = True
tune_diffusion_model = True
tune_vlln = True

默认冻结Qwen3-VL的语言和视觉部分,只训练状态编码器、动作编码器、DiT、输出解码器以及VLM特征适配层。需要时也可以解冻顶部若干LLM Layer。推理时,Qwen3-VL只运行一次,

复制代码
vl_features = backbone(images, instruction)
state_features = state_encoder(state)

随后多个去噪步骤反复调用DiT,

复制代码
actions = random_noise()

for t in range(num_inference_timesteps):
    action_features = action_encoder(actions, t)

    velocity = dit(
        hidden_states=concat(
            state_features,
            action_features,
        ),
        encoder_hidden_states=vl_features,
    )

    actions = actions + dt * velocity

两种连接方式反映了不同的设计取向

OpenPi的关键并不是PaliGemma后面接了一个动作头,而是让VLM Expert和Action Expert在每一层共同参与注意力计算。动作专家读取的不是VLM最后一层压缩后的结果,而是逐层演化的视觉语言表示。可以将其概括为如下,

复制代码
OpenPi:
VLM Layer 1  ←联合注意力→  Action Expert Layer 1
VLM Layer 2  ←联合注意力→  Action Expert Layer 2
VLM Layer 3  ←联合注意力→  Action Expert Layer 3
...

GR00T则先完成VLM编码,再由动作模型读取其最终Token,

复制代码
GR00T:
图像、语言 -> Qwen3-VL Backbone -> 固定的VL Token序列 <- Cross-Attention -> 
 -> DiT Action Head -> 动作序列

OpenPi的优势是语义理解与动作生成结合得更紧,动作专家在浅层就可以读取视觉和语言信息,并在后续每一层继续加工,适合联合预训练大规模VLA。代价是结构约束较多。两个专家需要保持相同层数,并且注意力头配置必须兼容。替换VLM、改变层数或接入完全不同的动作网络时,需要修改联合Transformer的内部实现。

GR00T的优势是模块边界清晰,VLM只需要输出Token序列,DiT通过Cross-Attention读取条件。更换视觉语言骨干、冻结VLM、独立导出动作头以及进行多具身适配都更加直接。代价是VLM和动作模型主要在Backbone出处连接。与OpenPi的逐层交互相比,动作模型无法参与VLM内部表征形成过程,只能对已经生成的视觉语言特征进行二次读取。

对于希望保持预训练VLM稳定、方便替换模型或适配多种机器人的项目,GR00T的Backbone-DiT结构更容易扩展;对于希望通过大规模联合训练,让语义特征从底层开始服务于动作生成的模型,OpenPi的双专家联合注意力结构更加紧密。

相关推荐
闵孚龙1 小时前
Autograd 自动求导:PyTorch 训练模型的发动机
人工智能·pytorch·python
云和数据.ChenGuang1 小时前
大模型厂商常用的数据库有哪些?
数据库·人工智能·pytorch·深度学习·numpy
旅僧1 小时前
Bert理论讲解
人工智能·深度学习·bert
邵宇然1 小时前
编译期阻断 Bug:Rust 类型系统如何将运行时错误消灭在编译阶段
人工智能
ACP广源盛139246256731 小时前
GSV6155@ACP#DP 1.4a 重定时器芯片,物理 AI 信号长距传输的稳定保障
大数据·人工智能·分布式·嵌入式硬件·spark
明志数科1 小时前
数据标注自动化 vs 人工——4D时序标注场景谁靠谱?
人工智能
深圳市晶科鑫实业有限公司1 小时前
AI服务器为何对低抖动差分晶振如此挑剔?
服务器·人工智能·单片机·物联网·车载系统·云计算·信息与通信
FL16238631291 小时前
基于CNN深度学习算实现手写字母识别系统python源码+训练好的模型+说明文档
python·深度学习·cnn
geneculture1 小时前
中文信息处理的词边界重构:基于融智学的汉英结构计算模型
人工智能·语言学·融智学应用场景·中文信息处理·融智时代(杂志)·言和语·言本位