← 返回文章库

世界模型加动作:机器人先在脑子里预演一遍

最后更新 2026-08-23
⏱ 约 15 分钟 🟡 涉接线/强电
你将学到
  • 理解世界模型的定义与它在具身智能里的三重价值,不再把它当成「会做梦的黑盒」
  • 看懂「世界模型 + 动作头」这种双目标结构,以及它和纯 VLA 的路线差异
  • 掌握 unifolm-world-model-action 提供了什么:模型、训练、推理、部署、数据接口各在哪

你伸手去端一杯满水的马克杯。手还没碰到杯子,脑子里已经过了一遍:抓这个角度会不会洒、杯壁烫不烫、抬起来手腕要不要转。这一遍预演不花你几毫秒,但它挡掉了大量本来会发生的失误。

机器人学里有一整条路线,就是想把这件事装进模型:让它学会预测「如果我这样做,接下来会发生什么」,然后在脑子里试几种做法,挑最好的那个真的去做。 这条路线叫世界模型(world model)。

世界模型是具身智能里被提及很多、被讲清楚很少的一个词。很多介绍停在「它能想象未来」这句话上,听着像科幻,落不到代码。这篇想干的事是两件:把这个思路的原理讲透,再落到一个具体的开源实现上看看它长什么样——宇树的 unifolm-world-model-action 仓库,也就是 UnifoLM 家族里的 WMA。

先把边界说清楚:本文全部基于该仓库的公开 README、目录结构与配置说明。我手上没有对应的机器人,也没有跑过训练或推理,所以文中不会出现任何实测效果、成功率、性能对比的描述。仓库文档没写的能力,这里一律不评价。

一、先说原理:世界模型到底在学什么

定义比想象中朴素

剥掉所有包装,世界模型学的是这么一个函数:

输入:当前观测 o_t,以及一个动作 a_t
输出:下一时刻的观测 o_{t+1}

就这么简单。它学的是环境的动力学——世界在你施加一个动作之后,会怎么变。

在经典控制里,这个函数是人写出来的:列微分方程,标定参数,得到一个状态空间模型。这条路在观测是低维状态(关节角、速度、位姿)的时候非常好用。麻烦出在观测变成图像之后——没人写得出「一张 RGB 图像在夹爪合拢 20 毫秒后会变成哪张 RGB 图像」的解析式。

所以现在这批世界模型的做法是:直接用深度网络在高维观测上建模,把「预测下一帧」当成一个学习任务硬训。视频生成模型这几年的进步,恰好给这件事提供了现成的地基。WMA 的 README 里训练策略第一步写得很直白:先拿 Open-X 数据集把一个视频生成模型微调成世界模型。这句话值得停一秒——世界模型的出身是视频生成模型,只不过它生成的不是好看的视频,是「机器人做了这个动作之后的画面」。

为什么值得学:三个理由

理由一,能在模型内部做规划,不必真的去试。

这是最直觉的价值。有了预测函数,你就能在内部推演:假设我执行动作序列 A,画面会怎么演化;换成序列 B 呢。挑一个预测结果最接近目标的去执行。真机上试错的代价是撞坏东西、磨损关节、耗时间;模型内部试错的代价只是一点算力。这个差价就是世界模型的核心卖点。

理由二,它可以当成一个学出来的仿真器。

传统仿真器是人建出来的:写 URDF、调摩擦系数、配接触模型。它的天花板是「你对物理的建模有多准」,而柔性物体、颗粒、复杂接触这些恰恰是最难建的。世界模型换了个思路——不建模,从真实数据里学。学到之后,它就能生成新的交互序列,用来喂给下游的策略训练。WMA 的 README 把这个功能明确列为世界模型的两大作用之一,叫 Simulation Engine:作为交互式仿真器,生成用于机器人学习的合成数据。

理由三,「预测未来」这个任务本身就在逼模型学表征。

这一条最容易被忽略,但可能是最重要的。想准确预测下一帧,模型不得不隐式地搞明白一堆事:哪些像素属于同一个刚体、物体之间谁挡着谁、被推的东西会往哪个方向倒、手和物体接触之后运动会怎么耦合。这些是没人给标签的,但预测任务会把它们逼出来。

这跟语言模型的逻辑是同构的:下一词预测这个看似无聊的目标,逼出了语法、常识和推理。在具身智能里,下一帧预测扮演的是同样的角色。理解这一点,你就明白为什么有人把世界模型当作通往具身智能的一条主干道——它提供了一个可以在海量无标注交互数据上做的自监督目标。

和纯 VLA 的区别:反射 vs 预演

VLA(视觉-语言-动作)模型的基本形态是「观测 + 指令 → 动作」,中间不显式经过未来。你可以把它理解成一种训练出来的反射:看到这个画面,听到这句话,手就该这么动。反射的好处是快、结构简单;代价是模型没有被要求解释「为什么这么动」,它对世界演化的理解只能藏在权重里,你无从检查。

世界模型这条路多了一个中间环节:先预测会发生什么,再决定做什么。这就是「预演」。

两者不是对立的。宇树自己也同时开了两个仓库:一个是纯 VLA 路线的 UnifoLM-VLA,一个就是本文这个 WMA。它们同属 UnifoLM 家族,共用同一套 unitree_deploy 部署代码——VLA 那边的 README 在客户端配置一节里直接把读者指向了 WMA 仓库的 unitree_deploy/README.md。这个细节说明两条路线在工程上共享同一个真机接口层,差别在模型内部。

和传统基于模型的强化学习是什么关系

如果你学过强化学习,会觉得这套说辞耳熟。model-based RL 早就在做同样的事:学一个环境模型,然后在模型里做规划或者生成想象轨迹来训练策略。思路一脉相承,没有断代。

区别主要在两处。一是观测的维度:经典 model-based RL 大多在低维状态空间上工作,现在这批世界模型直接吃图像。二是模型的形态:过去是高斯过程、线性模型、小型神经网络,现在是从大规模视频数据预训练来的生成模型。从 WMA 的源码目录能看到这种形态变化的痕迹——src/unifolm_wma/models/ 下有 ddpms.pysamplers/ddim.pymodules/ 下有 attention.pyencoders/resampler.pyvision/dinosiglip_vit.py。这是一套典型的扩散生成模型 + 视觉编码器的组合,跟十年前 model-based RL 论文里的模型完全不是一个物种。

致谢里列的上游也印证了这个血统:DynamiCrafter(视频生成)、Diffusion Policy、ACT、HPT。前一个给世界模型的骨架,后三个是机器人操作策略这条线上的常见基础。

三个绕不过去的困难

讲价值容易,讲困难才诚实。

误差累积。 预测一步的误差也许不大,但你把预测结果再喂回去预测下一步,误差会滚雪球。预演十步和预演一百步,可信度差着量级。所有做长程规划的世界模型都要正面回答这个问题,工程上的常见做法是限制预演的步数——只在一个短窗口里相信自己的预测。

图像预测的算力开销。 生成一帧图像的代价远高于回归一个动作向量。你要在控制回路里做实时预演,这笔账很难算平。这也是为什么 WMA 的真机部署是服务端推理 + 机器人客户端取动作的架构,而不是把模型塞进机器人本体。

怎么评价一个世界模型好不好,本身就是难题。 预测出来的图像和真实图像的像素差小,不代表这个模型对决策有用——它可能把背景纹理拟合得很好,却搞错了物体有没有被抓起来。反过来,预测画面看着糊,但关键的因果关系是对的,对下游策略反而更有价值。图像生成领域那套评价指标在这里并不天然适用。这个问题目前没有公认答案,我也不去替作者猜他们的取舍。

二、这个仓库到底提供了什么

原理讲完,来核对清单。README 的开源计划一节列了四项,全部标记为已完成:训练、推理、模型权重、部署。逐项看。

模型权重

README 的 Model Checkpoints 表格里给了两个:

  • UnifoLM-WMA-0_Base:在 Open-X 数据集上微调得到
  • UnifoLM-WMA-0_Dual:在五个宇树开源数据集上、以决策与仿真两种模式微调得到

两者都托管在 HuggingFace。这里能读出的信息是层级关系:Base 是通用地基,Dual 是接了下游任务之后的产物。文档在训练配置一节也推荐把 pretrained_checkpoint 指向 Base。

数据接口

数据这块的约定是对齐 LeRobot V2.1 格式。README 给出的路径是:把你的数据整理成 LeRobot 格式,然后用 prepare_data/prepare_training_data.py 转换成训练需要的结构。

转换后的目录长这样:

target_dir/
    ├── videos
    │     └── dataset1_name
    │          └── camera_view_dir
    │               ├── 0.mp4
    │               └── ...
    ├── transitions
    │    └── dataset1_name
    │         ├── meta_data
    │         ├── 0.h5
    │         └── ...
    └── dataset1_name.csv

这个结构本身就说明了模型吃什么:一路视频,一路状态-动作转移(transitions),外加一张 CSV 做索引。 视频对应观测,h5 对应机器人状态和动作,meta_data 里存归一化用的统计量。

有一条限制写在括号里,很容易被跳过:模型训练只支持主视角相机的输入,如果数据集里有多个视角,需要从 CSV 的 data_dir 列里把对应的值删掉。这是个会实实在在卡住人的细节——多相机采集是常规做法,而这里明确只用一路。

转换脚本还要求传一个 --robot_name 参数,README 举的例子是形如「Unitree Z1 Robot Arm」这样的机器人标签。这暗示了模型对本体是有感知的:同样的画面,不同本体应该有不同的动力学。

训练:三步走,且可以只走一部分

README 的训练策略写得相当清楚:

  • 第一步:用 Open-X 把视频生成模型微调成世界模型
  • 第二步:在下游任务数据上,以决策模式(decision-making mode)继续训练
  • 第三步:在下游任务数据上,以仿真模式(simulation mode)继续训练

紧跟着一句注解:如果你只需要其中一种模式,对应的那一步可以跳过。

这个开关在配置文件里有直接对应物。configs/train/config.yaml 里有一项:

model:
    pretrained_checkpoint: /path/to/pretrained/checkpoint
    ...
    decision_making_only: True  # 只训练决策模式;设为 False 则两种模式联合训练

一个布尔值,把整个架构的双重身份摊开了:同一个世界模型,既可以专心当决策器的辅助,也可以两种模式一起练。

配置里还有几处需要动手的地方:configs/train/meta.json 定义各个模态的输入形状;config.yaml 里对状态与动作的维度设了一个上限默认值,超过就要自己改 agent_state_dimagent_action_dim(具体数值以官方仓库当前的 config.yaml 为准);多数据集混合训练时用 dataset_and_weights 列出每个数据集的权重,README 要求权重之和为 1.0。

训练入口是 scripts/train.sh,需要先设好 experiment_namesave_root

推理:两个模式,两条命令

交互式仿真模式scripts/run_world_model_interaction.sh。它需要一份 prompt,格式在 examples/world_model_interaction_prompts/ 下有现成的:

world_model_interaction_prompts/
    ├── images        # 图像 prompt
    ├── transitions   # 机器人状态与动作;交互模式下只用来取图像 prompt 对应的状态
    └── dataset1_name.csv   # 索引图像 prompt、文字指令与对应状态

注意 transitions 那一行的注释——交互模式下它只被用来取出图像 prompt 对应的那个机器人状态。也就是说,这个模式的输入是「一张起始画面 + 一句文字指令 + 一个起始状态」,然后让世界模型往下演化。这就是「在脑子里放电影」的具体形态。

决策模式则是完整的真机推理链路,README 给的是服务端 / 客户端分离的架构:推理跑在服务器上,机器人客户端采集观测发过去、取回动作。

服务端跑 scripts/run_real_eval_server.sh,配置在 configs/inference/world_model_decision_making.yaml。客户端要先按 unitree_deploy/README.md 建好环境,然后打一条 SSH 隧道过去:

ssh user_name@remote_server_IP -CNg -L 8000:127.0.0.1:8000

再运行 unitree_deploy/scripts/robot_client.py。这个脚本的参数很值得看,因为它们直接暴露了模型的工作方式:

--robot_type            机器人类型
--action_horizon        一次预测多少步动作
--exe_steps             这些动作里实际执行多少步
--observation_horizon   喂进去几帧历史观测
--language_instruction  文字指令,比如把某个物体装进盒子
--control_freq          控制频率

(README 的示例命令里给了具体数值,以仓库当前文档为准。)

action_horizonexe_steps 分开这件事,是动作分块(action chunking)这类做法的典型标志:模型一次输出一段动作序列,但不一定全执行完,执行掉一部分就重新观测、重新预测。这么设计的原因不难想:一次预测一步的话,推理延迟会直接卡住控制频率;一次预测一大段又会让机器人对环境变化反应迟钝。这两个参数就是让你在这两头之间调。

observation_horizon 大于一,说明模型看的不只是当前这一帧,而是一小段历史。对需要判断速度、判断东西有没有被抓稳的任务来说,单帧信息本来就不够。

部署侧的代码

unitree_deploy/ 是一个相对独立的子项目,有自己的 pyproject.toml 和文档。从它的目录能看出真机那一侧要操心的东西:

unitree_deploy/unitree_deploy/
    ├── real_unitree_env.py       # 真机环境封装
    ├── eval_dataset_env.py       # 数据集回放环境
    ├── robot/                    # 机器人抽象与配置
    └── robot_devices/
         ├── arm/                 # 各型号手臂驱动与逆运动学
         ├── cameras/             # 相机接入
         ├── endeffector/         # 末端执行器
         └── assets/              # URDF / MJCF 与网格模型

arm/ 下每个型号都配了一个 *_arm.py 和一个 *_arm_ik.py——驱动归驱动,逆运动学归逆运动学,分得很干净。安装步骤里要用 conda 装 pinocchio 这个刚体动力学库,正好对得上:模型输出的动作要落到关节上,中间这段运动学换算是绕不开的。

cameras/ 下并列着 intelrealsense.pyopencv.pyimageclient.py 三种接入方式,test/camera/ 下也有对应的测试脚本。这种「同一个抽象接三种实现」的写法,在宇树 SDK2 的架构里也能看到,是这类部署层的常见组织方式。

utils/ 里有几个文件挺说明问题:joint_trajcetory_inter.py(关节轨迹插值)、weighted_moving_filter.py(加权滑动滤波)、trajectory_generator.py。模型输出的动作序列是离散的、可能带抖动的,直接发给关节会很难看甚至危险,中间这层平滑处理是必需品。文档里还专门有 docs/add_robot_arm.mdadd_robot_camera.mdadd_robot_endeffector.mdbuild_robot.md 四篇,说明部署层是按「让你接入自己的硬件」来设计的。

一个读代码时发现的小细节

README 里那张代码结构图,顶层写的是 unitree-world-model/,核心包写的是 src/unitree_worldmodel。但实际文件树里,核心包的路径是 src/unifolm_wma/。文档中若干配置文件的链接也还指向旧的仓库路径。

这不是什么大问题,但它透露了项目的演进轨迹:这个仓库早期叫 unitree-world-model,后来被收编进 UnifoLM 家族,改名成了 unifolm-world-model-action,README 的部分内容没同步更新。照着文档里的包名去 import 会失败,以文件树为准。 读任何一个活跃演进的开源项目,这类文档与代码的时间差都值得留个心眼。

三、「世界模型 + 动作」这个组合,多出来的是什么

回到标题里那个 A 字母。WMA 不是纯粹的世界模型,它是 World-Model-Action

README 对世界模型的定位给了两个功能,第二个叫 Policy Enhancement:世界模型连接一个动作头(action head),通过预测未来的交互过程,来进一步优化决策表现。

源码里能找到这个动作头:src/unifolm_wma/models/diffusion_head/。里面有 conditional_unet1d.pyconv1d_components.pypositional_embedding.pyema_model.py,还有一个 vision/multi_image_obs_encoder.py。一维卷积 + 条件 UNet 的组合,是动作序列生成这条线上很典型的结构;ema_model.py 则是训练时维护参数滑动平均的常规做法。

结构层面的含义是:这套模型有两个输出口。 一个口吐未来的画面,一个口吐该做的动作。两个目标一起训练,会互相约束——

动作那边约束画面:预测的未来必须是「这个动作真的会导致的未来」,而不是随便一个看着合理的未来。

画面那边约束动作:模型要输出动作,就得对这个动作的后果负责,因为它同时被要求把后果画出来。这就堵住了纯反射式策略的一个口子——模型没法在完全不理解因果的情况下靠拟合蒙对动作。

README 里那句关于演示视频的注解,把这件事说得很具体:演示画面右上角那个小窗口,显示的是世界模型对未来动作视频的预测。机器人在动的同时,模型在旁边画它以为接下来会发生什么。 这就是「预演」两个字最字面的呈现。

至于这种双目标结构在效果上比纯 VLA 好多少、在什么任务上更有优势——仓库文档没有给出这方面的评测数据,我不做推断。这里能确认的只是架构层面的事实:两个目标确实是一起训练的,配置里的 decision_making_only 开关控制着是否联合。

四、这条路线在具身智能里的位置

读完这个仓库,有三件事值得带走。

第一,世界模型的门槛在数据,不在想法。 「学一个预测未来的模型」这个想法几十年前就有了,真正让它现在可行的,是两样东西:视频生成模型提供的地基,和大规模真实机器人交互数据的积累。这个仓库明确列了它用的开源数据集,也把自有数据的转换脚本给了出来。你要走这条路,第一个卡点大概率是数据,不是模型代码。

第二,「仿真器」这个词正在被重新定义。 传统仿真器是人写的物理引擎,世界模型是学出来的预测器。两者的能力边界完全不同——前者在刚体动力学上又快又准且完全可控,后者在难以建模的柔性、接触、杂乱场景上有机会。它们大概率不会互相取代,而是各占一段。做足式运动控制那类任务,强化学习那套仿真训练流水线仍然是主力;做桌面操作、接触密集的任务,学出来的世界模型才有用武之地。

第三,别把「预演」神化。 误差累积、算力开销、评价困难这三个问题都还在。世界模型现在更像是一个有前景的方向,而不是一个已经定型的方案。任何看到「机器人会想象了」就断言问题已经解决的说法,都值得打个折扣。

如果你打算顺着这条线读下去,建议的顺序是:先把具身智能的整体图景过一遍,再看纯 VLA 路线是怎么做的,最后回到本文这个 WMA,对着看两条路线在数据接口、训练目标、部署架构上分别做了什么取舍。同一家机构在同一时期开源的两套东西,这种对照本身就是很好的学习材料。整卷的其他文章可以从宇树专题页进入。

📄 来源 / 自校链接

本文为公开资料整理,非亲测。关键参数与代码请结合实物与下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为公开资料的学习整理,非亲测。涉接线/花钱/合规的步骤请结合实物与官方最新资料验证,风险自负。见免责声明