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 | 游戏 | 短 | 低 | 480p | Yes | Yes |
| Yume-1.5 | 通用 | 短 | 低 | 480p | No | Yes |
| HY-World 1.5 | 通用 | 中 | 低 | 720p | Yes | Yes |
| Mirage 2 | 通用 | 长 | 中 | 480p | Yes | No |
| Genie 3 | 通用 | 长 | 中 | 720p | Yes | No |
| LingBot-World | 通用 | 长 | 高 | 720p | Yes | Yes |
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)
为每个视频生成三层描述:
- 叙事描述 (Narrative Caption):全局描述视频内容 + 相机运动 + 时间演化
- 场景静态描述 (Scene-Static Caption):仅描述环境和美学细节,刻意省略动作描述——这是将运动控制与场景生成解耦的关键设计
- 密集时间描述 (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) # 端到端延迟 < 1s4. 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-A14B | Image-to-video 任务,14B 激活参数 |
--size 720P | 输出分辨率 |
--frame_num 961 | 最大帧数(~60s @16FPS) |
--t5_cpu | T5 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.5 | HY-World 1.5 | LingBot-World |
|---|---|---|---|
| Imaging Quality | 0.5838 | 0.6512 | 0.6683 |
| Aesthetic Quality | 0.5185 | 0.5487 | 0.5660 |
| Dynamic Degree | 0.7612 | 0.7217 | 0.8857 |
| Motion Smoothness | 0.9709 | 0.9897 | 0.9895 |
| Temporal Flickering | 0.9545 | 0.9773 | 0.9648 |
| Overall Consistency | 0.1994 | 0.2016 | 0.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 局限性与未来方向
- 记忆稳定性:当前的空间记忆是上下文窗口的涌现能力而非显式存储模块,长时间模拟中存在不一致性
- 计算成本:推理仍需企业级 GPU,难以在消费级硬件上运行
- 动作空间有限:目前主要支持导航和基础移动,缺乏复杂交互(如物体操纵)的支持