1. 为什么又造了一个新名词

1.1 标题里那个"World"到底新在哪

笔者第一次看到 World-Language-Action 这个标题的反应是——又一个三件套合成词。这两年从 VLA 到 WAM 再到 RDT、UniSim、Genie,机器人基础模型几乎每个月都在生造新概念。但读完论文和代码,再回头看作者把它叫 WLA 的理由,会发现这不是一次概念堆叠,而是一次相当务实的工程拼接:把 VLA 已经做好的语义推理,和 WAM 在做但还没接好的物理建模,绑到同一个 AR Transformer 上去预测。这套架构最值得记住的判断是——未来状态不是单一表示能扛下来的,至少要拆成"接下来要干嘛"和"接下来世界会怎么变"两份,前者交给 LLM,后者交给扩散,再共同条件化动作生成。代码:SJTU-DENG-Lab/WLA | 权重:HuggingFace Collection

1.2 现有路线的两道缺口

进一步看,机器人基础模型这两年的两条路线其实早就把缺口暴露出来了。第一条是 VLA(Vision-Language-Action),代表是 Google 的 RT-2、Stanford 的 OpenVLA、Physical Intelligence 的 π0/π0.5。它们的共同套路是借用一个预训练好的 VLM 来承接视觉理解和语言指令,再在 VLM 输出端接一个 action head,直接把动作 token 化或者用 flow matching 生成。第二条是 WAM(World Action Model),代表是 1X 的 World Model、DeepMind 的 Genie 系列、UniSim、以及 Motus 这类 video-to-action 工作。它们的共同套路是先训一个未来视频预测器,再用预测的视觉来约束动作策略。这两条路在 benchmark 上各擅胜场,但放到 RMBench 这种长程双臂任务里就同时露怯——前者缺物理监督,后者缺语言进度管理。WLA 的核心问题就是:能不能让一个模型同时拥有这两件本事。

在这里插入图片描述

如果把图 1 里的三种结构压成一行话来概括,差别全部集中在中间那层"未来表示"。VLA 没有,AR Transformer 直接到 action;WAM 有,但只有一份像素级或 video latent 级的视觉未来;WLA 有两份——一份是文本子任务序列(语义未来),描述"接下来这段动作应该完成哪些子任务",另一份是 meta-query 输出的 latent action(物理未来),描述"完成这段动作所需的状态转移"。两份未来不是冗余,因为它们各自处在不同的抽象层和时间尺度上:文本未来跨越多个动作 chunk,承担长程进度管理;latent action 紧贴当前 chunk,承担物理动态学习。这一拆分是整篇论文在架构层面最关键的一步。

2. WLA 的整体框架:两路未来共同条件化动作

2.1 输入输出接口与四步预测链

WLA 的输入输出接口没有偏离 VLA 的标准设定。给定时间步 t t t,模型接收当前观察 o t o_t ot、历史观察 o < t o_{<t} o<t、机器人本体状态 s t s_t st、用户指令 ℓ \ell ,要在执行下一个 action chunk 之前先把两路未来生成出来。形式上可以写成下面这一组式子,分别对应文本意图、物理动态、世界预测、动作生成四步:

c t : t + H = f AR ( o t ,   o < t ,   ℓ ,   M t ) , M t + 1 = update ( M t ,   c t : t + H ) c_{t:t+H} = f_{\text{AR}}\bigl(o_t,\, o_{<t},\, \ell,\, M_t\bigr), \qquad M_{t+1} = \text{update}\bigl(M_t,\, c_{t:t+H}\bigr) ct:t+H=fAR(ot,o<t,,Mt),Mt+1=update(Mt,ct:t+H)

z t = f AR ( m   ∣   o t ,   o < t ,   ℓ ,   c t : t + H ) z_t = f_{\text{AR}}\bigl(\mathbf{m} \,\bigm|\, o_t,\, o_{<t},\, \ell,\, c_{t:t+H}\bigr) zt=fAR(m ot,o<t,,ct:t+H)

y ^ t + H = f world ( z t ,   ENC ( o t ) ) , a t : t + H = f action ( z t ,   s t ) \hat{y}_{t+H} = f_{\text{world}}\bigl(z_t,\, \text{ENC}(o_t)\bigr), \qquad a_{t:t+H} = f_{\text{action}}\bigl(z_t,\, s_t\bigr) y^t+H=fworld(zt,ENC(ot)),at:t+H=faction(zt,st)

在这里插入图片描述

这里 c t : t + H c_{t:t+H} ct:t+H 是覆盖未来 H H H 步动作窗口的子任务序列,由 AR Transformer 从 memory M t M_t Mt 和当前观察滚动预测出来; m = { m 1 , … , m N } \mathbf{m} = \{m_1,\dots,m_N\} m={m1,,mN} 是固定数量的 meta-query,通过 causal attention 在 AR 上下文中汇聚信息,输出紧凑的物理动态 latent z t z_t zt f world f_{\text{world}} fworld z t z_t zt 去预测未来帧 o t + H o_{t+H} ot+H 的 VAE feature y ^ t + H \hat{y}_{t+H} y^t+H,提供物理监督; f action f_{\text{action}} faction 接收 z t z_t zt 和本体状态 s t s_t st,吐出未来 H H H 步的 action chunk。环境推进 H H H 步后,memory 把 c t : t + H c_{t:t+H} ct:t+H 中已经覆盖的子任务追加进去,进入下一窗口。这是一个标准的 receding-horizon 控制循环,但中间多了语义和物理两层未来预测。

在这里插入图片描述

2.2 训练 / 推理的关键不对称

这套架构在工程实现上有一个非常关键的不对称——两个 expert 在训练期和推理期的角色完全不同。World Expert 在训练期承担未来视觉特征的监督,是塑造 latent action z t z_t zt 的主要驱动力;但到了推理期,它可以整个被关掉,因为 z t z_t zt 此时已经被训练好,Action Expert 直接拿它生成动作就行,不需要再把未来帧画出来。Action Expert 则全程在线。这个不对称是 WLA 推理延迟能压到 40 ms 的关键,也是它和 Motus 这类视频生成 WAM 拉开五个数量级延迟差距的根本原因。换句话说,WLA 在训练时享用了 world model 的物理先验,在推理时却避开了 world model 的延迟代价,这几乎是 WAM 路线想做但一直没做干净的事。

在这里插入图片描述

3. 文本意图链:让 VLM 承担长程进度管理

3.1 滚动预测的子任务窗口

文本意图这条路径的核心思路,是把"模型每一步在做什么"从隐性常识变成显性变量。具体做法是把原始指令 ℓ \ell 分解成一段子任务序列 c = ( c 1 , … , c K ) c=(c_1,\dots,c_K) c=(c1,,cK),每个 c k c_k ck 对应一段时间区间 [ τ k , τ k + 1 ) [\tau_k,\tau_{k+1}) [τk,τk+1),然后让 AR Transformer 在每一步 t t t 都重新预测覆盖未来动作窗口 [ t , t + H ) [t,t+H) [t,t+H) 的连续子任务窗口 c t : t + H c_{t:t+H} ct:t+H。这里要厘清一个常见误解:WLA 的子任务不是一条预先生成好的静态计划,而是每一步都重新预测的滚动窗口——这意味着模型在长程任务中可以根据历史 memory M t M_t Mt 动态调整后续要执行的子目标,而不是死板地照着开局计划走完整个 episode。

3.2 0.005 的损失权重为何决定长程胜率

这条路径的工程价值在 RMBench 这种长程双臂任务上立刻显现。RMBench 的特点是任务需要反复试错、需要在多个子目标之间切换、需要根据当前进度判断下一步应该执行哪个子任务。后面实验部分会看到,去掉这条文本路径之后 RMBench 的成功率从 56.5% 跌到 17.3%——一个权重只有 0.005 的语言损失,撑起了整整 39 个百分点的差距。这说明子任务文本在 WLA 里不是一个装饰性的辅助监督,而是真正的中间推理变量。AR Transformer 通过被迫预测下一段子任务,被迫维护一个隐式的进度状态,这个进度状态再通过隐藏层激活流向 Action Expert,约束动作生成。

在这里插入图片描述

3.3 tokenizer 怎么把子任务和 meta-query 圈出来

代码里这条路径有意思的地方在 tokenizer 设置——WLA 在 Qwen3-VL 的词表里额外加了一组特殊 token:<begin_of_img><end_of_img> 以及 N 个 <img_i> 占位符,专门用来圈出 meta-query 的位置。子任务文本则走标准的 LM head 损失,复用 VLM backbone 自带的下一 token 预测目标,不需要额外加 head。这种共用 backbone 的多任务设计在参数效率上比双塔结构高出一截,也避免了两条监督路径之间因为分头训练带来的特征空间漂移。下面这段是 MLLMInContext.tokenize 里组装 prompt 后缀的核心逻辑:

# models/model.py
if "action" in training_mode:
    suffix = (
        "\n<begin_of_img>"
        + "".join([f"<img{i}>" for i in range(tokenizer.num_metaqueries)])
        + "<end_of_img><|im_end|>"
    )
elif "image" in training_mode:
    suffix = (
        "\n<begin_of_img>"
        + "".join([f"<img{i}>" for i in range(tokenizer.num_metaqueries)])
        + "<end_of_img><|im_end|>"
    )

这个 suffix 拼到指令尾部之后,模型在 forward 时会把 <begin_of_img><end_of_img> 之间这一段 hidden state 单独取出来,作为 meta-query 输出送进下一阶段。子任务文本则跟在指令前面,由 AR Transformer 用标准的下一 token 预测损失监督。这里要厘清的是 N 个 <img_i> 不是真正的图像 token,它们在 VLM 输入端只是占位符,作用是给 AR Transformer 留出 N 个位置让 attention 在因果掩码内自然汇聚整段上下文——这本质上是 BLIP-2 里 Q-Former 思路在 AR 范式下的简化版本,省掉了 Q-Former 那一层独立 cross-attention encoder。

在这里插入图片描述

4. 物理动态链:meta-query 当 latent action

4.1 为什么不让 AR 直接吐物理 latent

物理动态这条路径要解决的问题,是文本意图描述了"做什么",但没描述"世界会怎么变"。直接让 AR Transformer 输出连续的物理 latent 不太容易——AR 的输出本质是离散 token 上的分布,难以承载稠密的视觉动态。WLA 的做法是引入一组 meta-query:在 AR 上下文末尾追加 N 个特殊 token(也就是上一节那串 <img_i>),让它们通过 causal attention 汇聚整段上下文(观察、指令、子任务),把 hidden state 输出当作物理动态 latent z t z_t zt。这套用法和 BLIP-2 里 Q-Former 用 learnable query 抽视觉特征是同一个思路,只是在这里 query 输出的不是视觉表征,而是状态转移所需的最小描述。

4.2 encode_condition 的切片与 layerwise 拼接

这一段的关键工程实现集中在 MLLMInContext.encode_condition。它要做三件事:用 token 位置切出 meta-query hidden state,把当前观察 embedding、动作条件、meta-query 三者拼成 prefix,然后送进 connector 做维度对齐。这三步是 WLA 把 VLM 的语义空间和扩散模型的条件空间真正粘合在一起的位置,也是整个仓库里读起来最绕的一段——因为它要同时处理 VLM 多层 hidden state、可选的 history observation、可选的 raw action condition、以及 layerwise condition 的最后 K 层切片。下面这段是其中的切片逻辑:

# models/model.py
boi_pos = torch.where(input_ids == self.boi_token_id)[1]
eoi_pos = torch.where(input_ids == self.eoi_token_id)[1]

prompt_embeds_mask = (indices > boi_pos[:, None]) & (indices < eoi_pos[:, None])
embeddings_mask    = (indices > vision_start[:, None]) & (indices < vision_end[:, None])

embeddings = embeddings[embeddings_mask].view(batch_size, -1, embeddings.size(-1))

prompt_embeds_all_layer = []
for layer in prompt_embeds:
    layer_query = layer[prompt_embeds_mask].view(batch_size, -1, layer.size(-1))
    prompt_embeds_all_layer.append(layer_query)

prefix = [embeddings, action_cond_features] if action_cond_features is not None else [embeddings]
prompt_embeds_all_layer = [
    self.connector(torch.cat(prefix + [layer_query], dim=1))
    for layer_query in prompt_embeds_all_layer
]

这段代码做的事情可以这样理解:先用 <|vision_start|> / <|vision_end|> 找出当前观察对应的 token 区间,再用 <begin_of_img> / <end_of_img> 找出 meta-query 区间,把每一层 Transformer 的 hidden state 在这两段上分别切片。然后把当前观察 embedding、(可选的)历史动作条件、本层 meta-query 三者拼成一个序列,整体过 connector。这里有两个工程细节值得注意。第一,每一层都做切片,最终保留的是最后 K 层(K 等于 World Expert 的 transformer block 数),这样 World Expert 的每一层 cross-attention 都拿到独立的 latent,称为"layerwise condition",比单一 latent 更细致地约束扩散过程。第二,connector 不轻——是一个 12 层的 Qwen2 encoder 加 RMSNorm,专门负责把 VLM 语义空间桥接到扩散模型条件空间,参数量在百兆级别。

在这里插入图片描述

5. World Expert:训练时的物理监督,推理时可关

5.1 监督目标是 VAE 特征不是像素

World Expert 是 WLA 中负责把物理动态 latent 落到具体监督上的那一环。它接收 latent action z t z_t zt 和当前观察的 VAE 编码,去预测未来帧 o t + H o_{t+H} ot+H 的 VAE feature。代码里它实例化的是 Sana 600M——一个面向 512px 图像的扩散 Transformer,比通常视频扩散模型小一个数量级。这个尺寸选择和监督目标的选择是配套的:WLA 不要 World Expert 真的把未来 RGB 渲染清楚,只要它能在 VAE feature 空间里做对状态转移。下面这一段是 WLA 的 forward 主循环里 image loss 的算法:

# models/wla.py
latents = self.vae.encode(target_images).latent
latents = torch.cat([latents, latent_depth], dim=1)
latents = (latents - self.vae.config.shift_factor) * self.vae.config.scaling_factor

noise   = torch.randn_like(latents)
sigmas  = self.get_sigmas(timesteps, latents.device, n_dim=latents.ndim, dtype=latents.dtype)
noisy_latents = (1.0 - sigmas) * latents + sigmas * noise

prompt_embeds, attention_mask = self.model.encode_condition(
    input_ids=input_ids, attention_mask=attention_mask,
    mllm_output=mllm_output, action_cond_features=action_cond_features,
)
model_pred = self.model(
    hidden_states=noisy_latents, timestep=timesteps,
    encoder_hidden_states=prompt_embeds, encoder_attention_mask=attention_mask,
)
target = noise - latents          # rectified flow velocity
image_loss = (weighting * (model_pred - target).pow(2)).mean()

整段是一个标准的 rectified flow / flow matching 训练步——把 VAE latent 和噪声按 sigma 线性插值得到 noisy latent,让 World Expert 预测速度场 noise - latents。但这里有三个工程选择值得反复琢磨。第一,监督目标用 VAE feature 而不是 DINO 或 JEPA。这是一个有讲究的取舍:DINO/JEPA 偏语义,但语义已经由文本子任务承担了;VAE 偏低层视觉细节,正好补上 latent action 需要的物理动态信息。这种"语义归语义、物理归物理"的分工在 multi-stream supervision 里并不常见,多数 VLA-WAM 工作要么两份监督混在一起,要么干脆只要其中一份。第二,只预测单帧 o t + H o_{t+H} ot+H 而不是整段未来视频。论文附录消融表明多帧监督会拖慢收敛、且不提升性能——多帧之间的相关性会让 latent action 被迫吸收太多冗余,反而模糊了"状态转移"这个核心信号。第三,World Expert 在推理期可以关闭。这是 WLA 推理延迟优势的来源,下一节会展开。

在这里插入图片描述

…详情请参照古月居

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐