• 正文
  • 相关推荐
申请入驻 产业图谱

WorldVLN:自回归世界动作模型在空中视觉语言导航中的实践

19小时前
176
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

转载自公众号:敢敢AUTOHUB

0. 简介

WorldVLN 研究的是空中视觉语言导航,也就是让无人机听懂自然语言指令,并在三维环境中连续飞行。它最重要的观点是:无人机导航不能只做“看图出动作”,而要先预测动作会让世界怎样变化,再根据预测结果生成动作。如果把传统 VLA 看成“看到当前画面就立刻反应”,那么 WorldVLN 更像“先在脑中预演下一小段飞行,再执行,并用真实新画面校正下一次预演”。下面会按从主到次的顺序解释 WorldVLN。先说明空中 VLN 为什么难,再讲 WorldVLN 的整体架构,然后进入本地代码中的服务接口、缓存机制、动作解码器和 GRPO 训练流程。读完后,你应该能理解三件事:第一,WorldVLN 为什么不是普通 VLA;第二,它如何完成“预测-动作-观测-更新”的闭环;第三,代码里哪些模块对应论文中的关键概念

Github项目地址:https://github.com/EmbodiedCity/WorldVLN.code
论文地址:https://arxiv.org/html/2605.15964v1

1. 为什么空中VLN需要世界动作模型

1.1 任务难点:无人机看到的是不断变化的世界

视觉语言导航听起来像是“看懂图像,再照着文字走”,但无人机场景比静态图文理解难得多。无人机只能看到第一视角的局部画面,向前飞、侧移、转弯、下降都会让下一帧画面发生明显变化。比如指令是“靠近白色建筑物左侧”,模型不仅要识别白色建筑物,还要判断向哪个方向移动后,建筑物会出现在更合适的位置。真正困难的不是识别目标,而是预测自己的动作会怎样改变后续观测

1.2 直接 VLA 的短板

传统 VLA 模型通常把策略写成条件映射:输入观测和指令,输出动作。这类模型继承了视觉语言模型的语义理解能力,擅长识别物体、场景和文本含义,但不一定理解动作导致的时空变化。对无人机来说,小的偏航误差会改变后续所有画面,小的高度误差会影响目标尺度和遮挡关系。如果模型没有世界动态先验,连续动作里的小误差就会被放大成轨迹漂移

1.3 论文中的数学形式

论文把空中 VLN 写成部分可观测序列决策问题。给定语言指令 、历史观测  和历史动作 ,策略生成下一步动作 。论文主文中的动作是 ,前三项表示相对三维位移,最后一项表示相对偏航角。动作执行后,位姿和观测更新为 。这组公式表达的核心很简单:动作不是终点,动作会改变下一次看见的世界

2. 本地工程解读

本地仓库 WorldVLN.code/ 可以按功能拆成四层。第一层是 Worldmodel/infinity/ 和 Worldmodel/runtime/,负责潜在自回归视频骨干和流式推理;第二层是 Worldmodel/action_decoder/,负责把视频潜表示转换为动作 token 并输出运动增量;第三层是 infer/,提供在线服务端和客户端协议;第四层是 train/ 与 action_aware_grpo/,分别对应监督训练、rollout 采集和 GRPO 后训练。先按模块边界读代码,比从模型细节硬啃更容易建立全局理解

论文概念 本地代码位置 工程作用
潜在自回归世界骨干 Worldmodel/runtime/Worldmodel/infinity/ 编码真实观测,预测未来 latent world transition
动作解码器 Worldmodel/action_decoder/ 将 VAE decoder feature 映射到 TimesFormer token 并回归动作
在线闭环推理 infer/server.pyinfer/client.py 维护 session_id、接收 RGB 帧、输出动作段
监督训练 train/train/TRAINING.md 微调世界骨干并训练 latent-to-action 映射
Action-aware GRPO action_aware_grpo/Worldmodel/runtime/tools/GRPO/ 采样 rollout、计算片段奖励、构造 replay 权重

3. 总体架构:预测世界转移,再解码动作

3.1 输入:语言指令和真实观测历史

模型输入包括语言指令和已经收到的第一视角观测历史。文本先经过编码器得到 ,图像或视频片段经过视频 VAE 编码器得到潜在表示 。随后,潜在自回归 Transformer 预测下一段世界状态转移,形式为 。这里预测的是 latent segment,不是完整 RGB 视频,因此目标更接近“为动作服务的世界变化”。

3.2 中间层:预测到的 latent 不是拿来欣赏的图像

动作解码器  接收预测出的潜在世界转移,并输出航点动作序列 。这一设计的关键不是让未来画面看起来多逼真,而是让潜在转移保留足够的空间、运动和语义信息,能够被稳定解码为动作。WorldVLN 的世界模型不是为了生成视频而生成视频,而是为了让动作决策知道“下一步可能发生什么”

3.3 闭环:执行后必须用真实观测纠偏

动作执行后,WorldVLN 会接收真实观测 ,再通过视频 VAE 编码成 ,并把真实 latent 放回自回归上下文。也就是说,模型不会把自己预测的  当成永久记忆继续滚动,而是用真实世界反馈覆盖预测状态。

预测只服务当前动作,下一轮决策必须重新锚定真实观测,这是它区别于全序列视频生成式世界模型的关键。

4. 从 VLA 到 WAM:范式差异在哪里

4.1 VLA:从当前观测直接到动作

VLA 模型通常学习 ,也就是把视觉语言理解和动作生成放在一个端到端映射里。这个设定简单,训练和部署都比较直观,但缺点是模型未必知道动作如何改变环境。举个更通俗的例子,VLA 像是看一眼路口就立刻决定往哪走;如果路口简单,它可能表现不错,但如果后面要连续转弯、绕行、升降,它就容易因为没有预判而越走越偏。

4.2 WAM:先预测世界怎样变,再决定动作

World Action Model 更接近  与  的组合。前半部分估计世界如何演化,后半部分从演化中恢复动作。这个结构把“看见什么”和“做什么”之间插入了一个可训练的预测空间,使模型有机会学习运动、视角和几何关系。它不是简单多加一个模块,而是把导航从反应式控制改成预测式控制

4.3 通俗类比:边走边看,而不是闭眼冲完整条路

可以把 WorldVLN 理解成一个会短程预演的飞行员:它先根据当前画面和指令预判下一小段飞行后世界会怎样,然后执行动作,接着马上用真实新画面修正判断。它不会一次性想象完整路线,也不会完全相信自己的想象。这个机制特别适合无人机,因为无人机视角变化太快,一次错误预测如果不及时纠正,后面每一步都会错得更远。

5. 在线闭环推理:服务端如何维护状态

5.1 服务协议:同一个 session 连续推进

WorldVLN 的在线推理使用 session_id 维护轨迹状态。第一次请求通常发送 1 帧 warmup 图像和指令,服务端生成下一段动作;客户端执行这些动作后,收集下一段真实 RGB 帧,再使用同一个 session_id 发回服务端。默认 step 为 16,服务端每次输出一段 16 帧对应的动作。这不是一次性预测完整轨迹,而是严格的分段闭环协议

5.2 接口代码:输入图像,输出 6D delta

# WorldVLN.code/infer/server.py
class PredictDeltaActionsRequest(BaseModel):
    session_id: str = Field(..., description="Trajectory/session identifier")
    instruction: Optional[str] = Field(None, description="Prompt/instruction; used on first call or when updating prompt")
    prompt: Optional[str] = Field(None, description="Alias of instruction (compat)")
    negative_prompt: Optional[str] = Field("", description="Optional negative prompt")
    images_base64: List[str] = Field(..., description="RGB images as base64 strings; first call typically 1 frame, later typically 16 frames")
    action_head_mode: str = Field(
        "tsformer_latent",
        description=(
            "'tsformer_latent' (default): Stage2 latent2action "
            "(decoder-features -> adapter tokens -> TimesFormer sliding windows) -> 16 actions per 16-frame segment."
        ),
    )

class PredictDeltaActionsResponse(BaseModel):
    actions: List[List[float]] = Field(
        ...,
        description="Delta actions list; each is [dx_cm,dy_cm,dz_cm,droll_deg,dyaw_deg,dpitch_deg].",
    )
    segment_index: int
    num_received_frames: int
    prefix_latents: int
    done: bool

这段代码体现了开源实现与论文公式之间的一个重要差异。论文主公式使用 4-DoF 动作,即三维位移加偏航角;而服务端工程接口输出 6D delta,顺序为 [dx_cm,dy_cm,dz_cm,droll_deg,dyaw_deg,dpitch_deg]。复现时如果直接把论文中的  套到工程接口上,会漏掉 roll 和 pitch 两个通道,也可能在单位换算上出错。实际控制链路必须明确坐标系、角度单位和动作执行频率

5.3 缓存机制:把事实和想象分开

InfinityStreamingSession 是闭环推理的关键封装。它把文本前缀缓存写成 t0,把真实观测缓存写成 gt_obs,并把推理过程中产生的 KV-cache 标记为 Pred。执行校正时只清除 Pred cache,保留文本和真实观测缓存。这个实现细节直接对应论文的“预测 latent 只用于当前动作,后续上下文由真实观测重建”。

# WorldVLN.code/Worldmodel/runtime/tools/infinity_streaming_session.py
"""
Key conventions:
- Use 't0' as the text-prefix cache key and write it as GT (is_pred=False) so it won't be removed by clear_pred_cache().
- Use 'gt_obs' as the observation-frame cache key and write it as GT (is_pred=False).
- KV-cache entries written during inference are treated as Pred (is_pred=True) and are cleared in one shot during correction.
"""

def correction_clear_pred(self):
    """Step 4: clear Pred KV cache in one shot (GT caches are kept)."""
    self.infinity.clear_pred_cache()

控制系统角度看,这相当于把“可靠事实”和“临时想象”分开管理。语言指令和真实观测是可靠事实,需要保留在上下文中;模型预测出的未来 latent 只是为了当前动作决策服务,不能长期污染记忆。对无人机这种视角变化剧烈的主体来说,错误想象如果被持续滚入上下文,就会导致场景语义漂移和几何漂移。WorldVLN 的缓存设计,就是为了让每轮决策重新锚定真实传感器输入

6. 动作解码器:从潜在世界转移到 6D 动作

6.1 为什么还需要动作解码器

动作解码器是 WorldVLN 中容易被忽略但非常关键的部分。世界模型输出的是 summed_codes 这样的潜在表示,不能直接交给飞控系统。开源实现先把 summed_codes 转成 Stage-2 VAE decode 需要的 z_ext,再通过 VAE decoder 抽取中间特征,并使用 adapter 把特征转换为 TimesFormer patch tokens。最后,TimesFormer 以滑动窗口方式输出每一帧对应的动作增量。

6.2 Adapter:把 VAE 特征翻译成 TimesFormer token

# WorldVLN.code/Worldmodel/action_decoder/src/models/vae96_to_tsformer_adapter.py(节选)
class Vae96ToTSformerEmbedAdapter(nn.Module):
    """
    Map InfinityStar decoder `up_block_3` feature (B,96,T,256,256) to TSformer patch tokens.

    Output tokens match TSformer `PatchEmbed` output:
      - patch_tokens: (B*T, N=12*40=480, D=384)
      - returns (patch_tokens, T, W_grid=40)
    """

    def forward(self, f96_up3: torch.Tensor) -> Tuple[torch.Tensor, int, int]:
        if f96_up3.ndim != 5:
            raise ValueError(f"expected f96_up3 shape (B,96,T,H,W), got {tuple(f96_up3.shape)}")
        B, C, T, H, W = f96_up3.shape
        if int(C) != 96:
            raise ValueError(f"expected channel=96, got C={C}")

        x = f96_up3.permute(0, 2, 1, 3, 4).reshape(B * T, C, H, W)
        x = _resize_to_192x640(x)
        h = self.conv_a(x)
        h = self.patch(h)

        if self.skip is not None:
            s = self.skip(x)
            s = F.avg_pool2d(s, kernel_size=self.patch_size, stride=self.patch_size)
            xg = h + 0.1 * s
        else:
            xg = h

        tokens = xg.flatten(2).transpose(1, 2).contiguous()
        tokens = self.out_norm(tokens)
        grid_w = int(xg.shape[-1])
        return tokens, int(T), grid_w

这段 adapter 代码说明了表示对齐的具体形式:输入是 VAE decoder 的五维特征 (B,96,T,H,W),输出是 TimesFormer 使用的 patch token (B*T,480,384)。从直觉上看,它就像一个“翻译层”:世界模型说的是 latent 语言,动作头听得懂的是时空 token 语言,adapter 负责把两者接起来。没有这层对齐,动作头很难稳定地从视频生成特征中读出运动信息

6.3 因果滑窗:不能偷看未来

# WorldVLN.code/infer/server.py
def _stage2_predict_16_actions_for_segment_cm_deg(
    *,
    st: "TrajectoryState",
    infer_res: "SegmentInferResult",
    stride: int = 1,
) -> List[List[float]]:
    """
    Stage-2 latent2action path:
    - Build full tokens_tnd for the whole predicted horizon from summed_codes (z_ext).
    - For the current segment, take only left-context frames [ctx_start .. clip_end] (NO right-context),
      run window=4 sliding inference with overlap averaging, and slice the 16 actions for this segment.
    """

这里的 “NO right-context” 很重要。在线控制不能使用还没有发生的真实未来帧,否则离线评估和真实部署会出现接口不一致。WorldVLN 的默认 tsformer_latent 路径只使用左侧上下文,并以窗口大小 4 的滑窗做动作预测,重叠位置再做平均。动作解码器遵守因果约束,才能真正用于闭环部署

7. 两阶段训练:先对齐世界先验,再优化动作后果

7.1 第一阶段:先学会“看懂导航视频”

第一阶段是监督训练,目标是把视频生成骨干中的时空先验迁移到导航数据上,并让潜在世界表示变得 action-decodable。对世界模型骨干,训练目标可以写成 ,即给定指令和历史真实 latent,预测下一段真实 latent。对动作解码器,训练目标可以写成 ,即从真实视频片段的 latent 中恢复专家动作。

7.2 本地训练入口

本地 train/TRAINING.md 提供了第一阶段训练的工程约束。默认设置包括 Python 3.10、视频帧数 49、fps 为 16、分辨率预设 0.40M、模型 infinity_qwen8b、学习率 1e-5,并需要准备 T5 文本编码器、InfinityStar video VAE 和 8B 基座权重。GitHub README 还说明动作解码器训练分为 Stage A 和 Stage B,前者进行 adapter distillation,后者进行 latent-to-action training。这说明训练流程不是一个脚本跑到底,而是先对齐表征,再学习动作输出

# WorldVLN.code README 中的训练入口
bash train/scripts/train_from_base.sh

# Action decoder: Stage A + Stage B
bash train/action_decoder/scripts/train_stageA_ddp.sh
bash train/action_decoder/scripts/train_stageB_ddp.sh

7.3 第二阶段:Action-aware GRPO 让模型看动作后果

第二阶段是 Action-aware GRPO。监督学习能够让模型模仿专家轨迹,但真实闭环导航关注的是动作执行后的后果,因此 WorldVLN 在模拟器中采样一组在线 rollout,并对每个片段计算奖励。论文给出的片段奖励形式为 。其中 trajectory reward 关注动作与专家轨迹的几何一致性,task reward 关注终点或阶段目标进度,reference reward 约束策略不要偏离已学到的世界模型先验。

# WorldVLN.code/Worldmodel/runtime/tools/GRPO/reward_uavflow.py
def _reward_act_with_clip_decay(
    pred_poses: List[List[float]],
    gt_poses: List[List[float]],
    clip_len: int,
    num_clips: int,
    clip_alpha: float,
    alpha_xyz: float,
    alpha_yaw: float,
    alpha_all6: float,
) -> Dict[str, Any]:
    """
    Compute action-level reward by summing per-clip rewards with temporal decay:
      r_act = r0 * 1 + r1 * alpha + r2 * alpha^2
    """

代码中的 clip_alpha 对应时间衰减思想,默认值为 0.9。早期动作被赋予更高权重,是因为无人机前几步的偏差会改变后续观测,从而影响后面所有动作。reward_uavflow.py 还同时计算 xyz、yaw 和全 6D 表示上的误差,并在 task reward 中评估 endpoint 距离和 yaw 误差。这比只看最终成功失败更细,因为每个片段都能获得训练信号

# WorldVLN.code/Worldmodel/runtime/tools/GRPO/build_replay_dataset.py
r = float(args.lambda_act) * r_act + float(args.lambda_task) * r_task + float(args.lambda_ce) * r_ce
mode = str(args.mode or "raw_reward").strip().lower()
has_precomputed_adv = all("grpo_adv_final" in rows[i] for i in idx.tolist())
adv_pre = np.asarray([float(rows[i].get("grpo_adv_final", 0.0)) for i in idx], dtype=np.float64)
if mode == "precomputed_adv" and has_precomputed_adv:
    s = r.copy()
    w = adv_pre.copy()
    m = (w > 0).astype(np.float64)

这段 replay 构造代码体现了 GRPO 阶段的工程取舍:动作奖励、任务奖励和 CE/reference 奖励可以按权重组合,若已有预计算优势值,则直接使用 grpo_adv_final 作为训练权重。它不是简单地把所有成功轨迹都当正样本,也不是只惩罚失败轨迹,而是把片段质量、任务进展和策略稳定性一起考虑。对一个 8B 级自回归世界骨干来说,保留世界模型先验和提升动作结果同样重要

8. 小结

WorldVLN 的主要贡献不是把一个视频生成模型简单接到无人机控制上,而是把空中视觉语言导航重新组织成“预测世界转移、解码动作、真实观测回填、再预测”的闭环过程。自回归世界骨干提供短时空间演化先验,动作解码器把 latent transition 转成可执行航点,Action-aware GRPO 则通过在线 rollout 后果继续优化动作质量。这三部分组合起来,使模型不只理解当前画面,还能利用对后续状态的预测来做决策

参考资料

    • arXiv: WorldVLN: Autoregressive World Action Model for Aerial Vision-Language Navigation• Project page: https://embodiedcity.github.io/WorldVLN/• GitHub code: https://github.com/EmbodiedCity/WorldVLN.code• Hugging Face weights: https://huggingface.co/EmbodiedCity/WorldVLN

相关推荐