LingBot-World: Advancing Open-source World Models

GitHub: Robbyant/lingbot-world Year: 2026

1. Motivation (研究动机)

LingBot-World 是蚂蚁集团 Robbyant 团队推出的开源交互式世界模型,从视频生成出发,构建了一个能够实时交互的世界模拟器。其核心定位是弥合开源与闭源世界模型之间的差距。

核心亮点

特性描述
高保真多域生成覆盖写实、科幻、卡通等多种环境风格
分钟级长时一致性支持长达 ~10 分钟的连续视频生成,具备”长期记忆”
实时交互16 FPS 吞吐量,端到端延迟 < 1秒
完全开源代码、模型权重、推理管线全部开源

与现有方法对比 (Table 1)

模型领域生成时长动态程度分辨率实时开源
Matrix-Game 2.0游戏480pYesYes
Yume-1.5通用480pNoYes
HY-World 1.5通用720pYesYes
Mirage 2通用480pYesNo
Genie 3通用720pYesNo
LingBot-World通用720pYesYes

Figure 1 解读:展示 LingBot-World 在多种域(写实风景、古建筑、科幻、动物等)下的高保真生成样本。右下角 W/A/S/D 键盘图标强调了用户可通过键盘实时控制角色/相机的交互能力。

2. Idea (核心思想)

整体系统由两大模块构成:数据引擎 (Data Engine) + 多阶段训练管线 (Multi-stage Training Pipeline)。核心思路是先用高质量、多样化的长视频与交互数据建立强视频先验,再通过分阶段训练把模型从“视频生成器”推进为“可实时交互的世界模拟器”。

Figure 2 解读:这是数据引擎的总体管线图,体现了“采集—画像—标注”的闭环设计,用数据筛选和层次化描述为后续世界建模提供高质量输入。

数据引擎包含三个协同组件:

(1) 数据采集 (Data Acquisition)

三路数据来源的混合采集策略:

  • 通用视频采集器 (General Video Curator):从海量原始视频中筛选高质量、运动多样的片段(步行、骑行、第一/第三人称视角等)
  • 游戏数据采集平台:从游戏引擎中捕获 RGB 帧 + 用户控制信号 (W/A/S/D) + 相机参数,保证时间戳严格同步。采集策略包括:
    • Navigation(自由/循环/场景切换)
    • Sightseeing(环绕观察)
    • Long-tail(静态旋转、后退)
    • World interaction(开门、战斗等因果交互)
  • 合成渲染管线 (Unreal Engine):自动生成无碰撞的随机化相机轨迹,提供精确的 ground-truth 相机位姿

Figure 3 解读:该图对应数据采集中的不同来源与控制信号形式,强调了自然视频、游戏引擎数据和合成渲染数据的互补性。

(2) 数据画像 (Data Profiling)

Figure 4 解读:展示数据画像的三级筛选流程,从基础元信息、语义分析到语义过滤,逐步清洗并保留适合训练世界模型的视频片段。

三级粒度的数据分析:

  • 基础过滤 & 切片:提取时长/分辨率等元数据,用 Koala + TransNet v2 进行场景切片
  • 语义分析:VLM 评估画面质量、运动幅度、场景类型;MegaSAM 为缺乏几何信息的视频生成相机位姿伪标注
  • 语义过滤:基于亮度/清晰度/运动/视角等属性做精细筛选

(3) 层次化标注 (Hierarchical Captioning)

为每个视频生成三层描述:

  1. 叙事描述 (Narrative Caption):全局描述视频内容 + 相机运动 + 时间演化
  2. 场景静态描述 (Scene-Static Caption):仅描述环境和美学细节,刻意省略动作描述——这是将运动控制与场景生成解耦的关键设计
  3. 密集时间描述 (Dense Temporal Caption):按时间段切分的细粒度事件描述(JSON 格式)

3. Method (方法)

Figure 5 解读:该图概览了三阶段训练管线,体现 LingBot-World 从通用视频先验逐步过渡到双向世界模型,再到因果实时模型的演化路径。

LingBot-World 采用三阶段渐进式训练策略,将视频生成器逐步演化为实时交互式世界模拟器。

Stage I: Pre-training —— 建立通用视频先验

  • 基座模型:Wan2.2 14B image-to-video 扩散模型
  • 目标:学习开放域视觉动态的无条件分布,获得强大的时空一致性和高保真纹理合成能力
  • 此阶段模型是通用的”视觉画布”,尚不具备交互逻辑

Stage II: Middle-training —— 注入世界知识与长期动态

这一阶段将预训练模型提升为双向世界模型 (Bidirectional World Model)

Figure 6 解读:该图展示中后期训练与架构适配的关键模块,包括双向世界模型、因果生成器以及用于蒸馏和对抗优化的判别结构。

关键技术:

(a) MoE 架构:继承 Wan2.2 的 Mixture-of-Experts 设计

  • High-noise expert (14B):早期时间步激活,负责全局结构和粗布局
  • Low-noise expert (14B):后期时间步激活,负责精细空间和时间细节
  • 总参数 28B,但推理时每步只激活一个 14B expert,计算开销等价于 dense 14B

(b) 渐进式课程训练

  • 第一轮:5 秒视频序列 → 拓展生成域
  • 逐步延长至 60 秒 → 学习长期一致性与空间记忆
  • 同时渐进调整噪声时间步的 flow shift,增加 high-noise 时间步比例以稳定长视频的场景结构

(c) 多任务训练:同时训练 image-to-video 和 video-to-video 任务

(d) 动作注入机制

  • 动作表示:Plucker 坐标(连续相机旋转) + multi-hot 向量(离散键盘输入 W/A/S/D)→ channel 维度拼接
  • 注入方式:通过 AdaLN (Adaptive Layer Normalization) 将动作嵌入投影为 scale & shift 因子,注入 DiT blocks
  • 微调策略:冻结 DiT 主干,仅训练新增的动作适配层(action embedding projections + AdaLN 参数),避免灾难性遗忘

(e) 并行训练基础设施

  • FSDP2:fully sharded data parallel 训练 28B 模型
  • Ulysses Context Parallel:沿序列(时间)维度分片,支持超长 token 序列

Stage III: Post-training —— 因果架构适配 & 少步蒸馏

将双向世界模型转换为高效的自回归因果模型,实现实时交互。

(a) 因果架构适配 (Causal Architecture Adaptation)

  • Block Causal Attention 替换全双向注意力:chunk 内双向注意力 + chunk 间因果注意力
  • 从 high-noise expert 初始化因果学生模型(因其动态建模能力更强)
  • 使用 Diffusion Forcing 机制训练:每个 chunk 分配独立噪声时间步
  • 推理时通过 KV caching 实现流式生成

(b) 少步蒸馏与长时训练 (Few-Step Distillation)

训练损失 (Eq. 2):

  • Self-rollout 扩展训练:学生模型在自身生成的序列上继续训练(self-forcing),通过 rolling KV cache 维护上下文,使用随机梯度截断控制计算开销
  • Distribution Matching Distillation (DMD):用 MoE 教师模型作为 real score function,配合 fake score network 做分布匹配

DMD 损失 (Eq. 4):

  • 对抗训练:在 fake score network 上附加 GAN 判别器头 ,使用 cross-attention 架构区分真实与合成序列

对抗损失 (Eq. 5-6):

3.1 核心算法 Python 伪代码

class LingBotWorld:
    """LingBot-World: 三阶段世界模型训练管线"""
 
    def __init__(self):
        # Stage I: 基座模型 — Wan2.2 14B I2V diffusion model
        self.base_model = Wan2_2_I2V(params="14B")
 
        # Stage II: MoE 双向世界模型
        self.high_noise_expert = copy.deepcopy(self.base_model)  # 14B
        self.low_noise_expert = copy.deepcopy(self.base_model)   # 14B
        # 总参数 28B,推理时每步只激活一个 14B
 
        self.plucker_encoder = PluckerEncoder()   # 连续相机旋转编码
        self.action_encoder = ActionEncoder()      # 离散键盘输入编码
        self.adaln = AdaptiveLayerNorm()           # 动作注入
 
    def middle_training(self, video_data, action_data):
        """Stage II: 注入世界知识 + 长期动态"""
        # 渐进式课程训练: 5s → 60s
        for duration in [5, 10, 20, 40, 60]:  # seconds
            clips = sample_clips(video_data, duration=duration)
 
            # 多任务: i2v + v2v
            for clip, actions in zip(clips, action_data):
                # 动作表示: Plucker坐标 + multi-hot
                cam_embed = self.plucker_encoder(actions.camera_pose)  # 连续旋转
                key_embed = self.action_encoder(actions.keyboard)       # W/A/S/D multi-hot
                action_embed = concat([cam_embed, key_embed], dim=-1)
 
                # 冻结DiT主干, 仅训练动作适配层
                with freeze(self.high_noise_expert.dit_backbone):
                    with freeze(self.low_noise_expert.dit_backbone):
                        noise = torch.randn_like(clip)
                        t = sample_timestep()
                        x_t = add_noise(clip, noise, t)
 
                        # MoE路由: 根据噪声时间步选择expert
                        if t > threshold:
                            pred = self.high_noise_expert(x_t, t, action_embed)
                        else:
                            pred = self.low_noise_expert(x_t, t, action_embed)
 
                        loss = F.mse_loss(pred, clip)
                        loss.backward()
 
    def post_training(self, teacher_model):
        """Stage III: 因果适配 + 少步蒸馏"""
        # (a) 从high-noise expert初始化因果学生模型
        student = CausalGenerator(init_from=self.high_noise_expert)
 
        # (b) Block Causal Attention 适配
        student.replace_attention(BlockCausalAttention(
            intra_chunk="bidirectional",  # chunk内双向
            inter_chunk="causal"          # chunk间因果
        ))
 
        # (c) Diffusion Forcing训练
        target_timesteps = [t_1, t_2, ..., t_m]  # 少量策略性选择的时间步
        for video_chunks in dataloader:
            # 每个chunk独立噪声时间步
            for i, chunk in enumerate(video_chunks):
                t_i = random.choice(target_timesteps)
                chunk_noisy = add_noise(chunk, noise, t_i)
 
            pred = student(chunks_noisy, timesteps, actions)
            loss_forcing = F.mse_loss(pred, chunks_clean)  # Eq. (2)
 
        # (d) DMD + 对抗训练
        self._distill_with_dmd(student, teacher_model)
 
    def _distill_with_dmd(self, student, teacher):
        """Distribution Matching Distillation + 对抗优化"""
        fake_score_net = copy.deepcopy(teacher)
        real_score_net = teacher  # frozen
        discriminator = DiscriminatorHead()  # cross-attention + MLP
 
        for x_real, actions in dataloader:
            # 学生生成
            x_fake = student.generate(actions)
 
            # Self-rollout: 学生在自身生成上继续训练
            with rolling_kv_cache(student) as cache:
                x_rollout = student.autoregressive_generate(
                    x_fake, actions, cache,
                    grad_steps=K  # 随机梯度截断: 仅最近K步反传
                )
 
            # DMD loss (Eq. 4)
            t = sample_timestep()
            x_hat_t = add_noise(x_fake, noise, t)
            s_real = real_score_net(x_hat_t, t, actions)
            s_fake = fake_score_net(x_hat_t, t, actions)
            loss_dmd = 0.5 * ||x_fake - sg(x_fake - (s_real - s_fake))||^2
 
            # 对抗 loss (Eq. 5-6)
            loss_G = softplus(1 - discriminator(fake_score_net(x_fake_t, t, actions)))
            loss_D = (softplus(discriminator(fake_score_net(x_real_t, t, actions)))
                     - softplus(1 - discriminator(fake_score_net(x_fake_t, t, actions))))
 
            # 两时间尺度更新: fake_score_net 多次更新 per student update
            update(student, loss_dmd + loss_G)
            for _ in range(n_critic):
                update(fake_score_net, loss_dmd)
                update(discriminator, loss_D)

3.2 Block Causal Attention

class BlockCausalAttention(nn.Module):
    """Block Causal Attention: chunk内双向 + chunk间因果"""
 
    def __init__(self, chunk_size, dim, num_heads):
        super().__init__()
        self.chunk_size = chunk_size
        self.attn = nn.MultiheadAttention(dim, num_heads)
 
    def forward(self, x, kv_cache=None):
        """
        x: (B, T, D) - 当前及历史帧的token序列
        """
        B, T, D = x.shape
        chunks = x.reshape(B, -1, self.chunk_size, D)  # (B, num_chunks, chunk_size, D)
 
        outputs = []
        for i in range(chunks.shape[1]):
            chunk_i = chunks[:, i]  # (B, chunk_size, D)
 
            # chunk内: 完全双向注意力
            # chunk间: 只能attend到当前及之前的chunks
            if kv_cache is not None:
                # 推理时: 复用之前chunk的KV cache
                kv = concat([kv_cache, self.to_kv(chunk_i)], dim=1)
            else:
                # 训练时: 构建block causal mask
                past_chunks = chunks[:, :i+1].reshape(B, -1, D)
                kv = self.to_kv(past_chunks)
 
            out = self.attn(
                query=self.to_q(chunk_i),
                key=kv, value=kv
            )
            outputs.append(out)
 
            # 更新KV cache
            if kv_cache is not None:
                kv_cache = concat([kv_cache, self.to_kv(chunk_i)], dim=1)
 
        return concat(outputs, dim=1)  # (B, T, D)

3.3 推理管线

@torch.no_grad()
def interactive_inference(model, initial_image, text_prompt):
    """实时交互式世界模拟推理"""
    # 编码初始帧
    latent = vae_encode(initial_image)
    text_emb = t5_encode(text_prompt)
    kv_cache = None
 
    while user_is_interacting():
        # 获取用户实时输入
        keyboard = get_keyboard_input()    # W/A/S/D
        mouse = get_mouse_delta()          # 连续旋转
 
        # 编码动作
        cam_plucker = compute_plucker_coordinates(mouse)
        action_multihot = encode_keyboard(keyboard)
        action = concat([cam_plucker, action_multihot])
 
        # 自回归生成下一个chunk (少步去噪)
        noise = torch.randn(chunk_shape)
        for t in [t_1, t_2, ..., t_m]:  # 少量去噪步
            pred = model.causal_forward(
                noise, t, action, text_emb,
                kv_cache=kv_cache  # 复用历史chunk的KV
            )
            noise = denoise_step(noise, pred, t)
 
        # 更新KV cache (仅新chunk的KV)
        kv_cache = model.update_cache(kv_cache, pred)
 
        # 解码输出 ~16 FPS
        frames = vae_decode(pred)
        display(frames)  # 端到端延迟 < 1s

4. Experimental Setup (实验设置)

4.1 代码仓库映射

仓库地址: github.com/Robbyant/lingbot-world

lingbot-world/
├── generate.py              # 主推理入口,支持 torchrun 多卡分布式推理
│                            # 任务: i2v-A14B (image-to-video)
│                            # 分辨率: 480P/720P,最长 961 帧 (~1分钟@16FPS)
├── wan/                     # Wan2.2 框架核心代码
│   ├── ...                  # DiT blocks, MoE routing, attention 等
├── examples/                # 示例输入(图片 + 控制信号)
├── assets/                  # 项目资源
├── requirements.txt         # 依赖: PyTorch>=2.4.0, Flash Attention
├── pyproject.toml           # 项目配置
└── LICENSE.txt              # Apache 2.0

4.2 关键推理参数

参数说明
--task i2v-A14BImage-to-video 任务,14B 激活参数
--size 720P输出分辨率
--frame_num 961最大帧数(~60s @16FPS)
--t5_cpuT5 encoder 放 CPU 以节省 GPU 显存
控制信号intrinsics.npy + poses.npy(ViPE 相机估计)

4.3 模型变体

模型控制方式说明
lingbot-world-base-cam相机位姿 (Plucker)连续相机控制
lingbot-world-base-act离散动作 (WASD)键盘交互控制
4-bit 量化版同上降低显存需求,推理质量有一定损失

4.4 评估设置

在 100 个 >30 秒的生成视频上进行 VBench 评估,比较对象包括 Yume-1.5 和 HY-World 1.5。该设置关注图像质量、美学、动态程度、运动平滑度、时间闪烁和整体一致性等指标。

5. Experimental Results (实验结果)

5.1 定量结果 (VBench, Table 2)

指标Yume-1.5HY-World 1.5LingBot-World
Imaging Quality0.58380.65120.6683
Aesthetic Quality0.51850.54870.5660
Dynamic Degree0.76120.72170.8857
Motion Smoothness0.97090.98970.9895
Temporal Flickering0.95450.97730.9648
Overall Consistency0.19940.20160.2178

关键发现:Dynamic Degree 指标大幅领先(0.8857 vs 0.7612),说明模型能生成远比基线更丰富的场景变化和运动响应。

5.2 定性分析

涌现记忆能力 (Emergent Memory)

Figure 7 解读:该图展示模型的涌现记忆能力,包括静态地标的结构保持、远处目标的正确尺度变化,以及物体离开视野后的合理再出现。

模型展现出无需显式 3D 表示的空间记忆能力:

  • 静态地标(如巨石阵、雕像)离开视野 60 秒后重新出现时保持结构完整性
  • 远处桥梁在前进过程中正确渐近放大
  • 车辆离开视野后在物理合理的位置重新出现

超长视频生成

模型可生成长达 10 分钟的连贯视频序列,无显著质量退化。

5.3 下游应用

(1) Promptable World Events

Figure 8 解读:该图说明模型可以通过文本提示控制全局事件和局部事件,例如天气、风格以及特定对象的注入。

通过文本提示控制世界事件:

  • 全局事件:天气变化(“winter”、“night”)、风格迁移(“pixel art”、“steampunk”)
  • 局部事件:注入特定对象(“fireworks”、“birds”、“fish”)

(2) Action Agent

Figure 9 解读:该图展示动作代理如何从单张图像预测未来控制信号,并用离散键盘与鼠标方向驱动世界模型进行自主探索。

基于 Qwen3-VL-2B 微调的动作代理,从单张图像预测未来 10 秒的离散键盘控制 (W/A/S/D) + 鼠标方向 (I/J/K/L),驱动世界模型自主探索。

(3) 3D 重建

Figure 10 解读:该图说明生成视频可用于点云重建,侧面验证了模型在视角变化下的几何一致性。

生成视频可直接用于高质量点云重建,验证了模型的几何一致性。

5.4 论文图示补充解读

Figure 11 解读:这张图再次概括三阶段训练流程,强调从预训练到中间训练再到后训练的能力递进。

  • Stage I (Pre-training):在大规模开放域视频上建立通用视频先验 → General Video Foundation
  • Stage II (Middle-training):注入动作控制、长期一致性、领域规则 → Physical World Model(双向注意力,高质量但慢)
  • Stage III (Post-training):因果注意力适配 + 少步蒸馏 → Real-time World Model(自回归,16 FPS)

DiT Block 架构细节

模型管线左半部分:输入图像/视频 + 噪声 latent + 动作序列 → DiT Block x N (MoE) → 视频输出。右半部分展示单个 DiT Block 内部:Video latent → Self Attn → Action Scale & Shift (AdaLN, 由 Plucker Encoder 编码的动作驱动) → Cross Attn (与 text embedding) → FFN → 输出。

Post-training 架构

(a) 因果生成器:Block Causal Attention — chunk 内双向 + chunk 间因果,从 high-noise expert 初始化。 (b) 判别器架构:多层 Cross Attention 结构,Video latents 作为 Key-Value,生成序列作为 Query,顶部接 MLP 分类头

Figure 13 解读:这张图与前面的记忆示意一致,强调模型在长时间后恢复地标和对象结构的能力,也支持其世界状态保持的直观展示。

模型在物体离开视野长达 60 秒后仍能正确恢复其结构(巨石阵、雕像)。更惊人的是,模型能推理未观测状态的演化:前进时远处桥梁正确变近,车辆离开视野后沿物理合理轨迹继续行驶。

5.5 局限性与未来方向

  1. 记忆稳定性:当前的空间记忆是上下文窗口的涌现能力而非显式存储模块,长时间模拟中存在不一致性
  2. 计算成本:推理仍需企业级 GPU,难以在消费级硬件上运行
  3. 动作空间有限:目前主要支持导航和基础移动,缺乏复杂交互(如物体操纵)的支持