借助我们的 SmolVLA,我们引入了一种在真实机器人上运行 inference 的新方式,将 action prediction 与 action 执行解耦。 在本教程中,我们将展示如何使用 SmolVLA 的 fine-tune 版本以及 LeRobot 支持的所有 policy 进行 async inference(async inference)。 在 LeRobot 支持的所有 policy 上尝试 async inference!
你将学到:
PolicyServer 并连接 RobotClient,既可从同一台机器连接,甚至也可通过网络连接。actions_per_chunk、chunk_size_threshold)。如果遇到困难,欢迎加入我们的 Discord 社区!
简而言之:使用 async inference 时,你的机器人会持续 action,而 policy server 已经忙于计算下一个 action chunk——从而消除“等待 inference”的延迟,并释放更平滑、更灵敏的行为。 这与同步 inference(sync)有本质区别:在同步 inference 中,机器人在 policy 计算下一个 action chunk 时保持空闲。
你可以在我们的博客文章中阅读有关 async inference 的更多信息。本指南旨在帮助你快速在环境中设置并运行 async inference。
首先,安装带 async 标签的 lerobot,以安装运行 async inference 所需的额外依赖项。
pip install -e ".[async]"
然后,启动一个 policy server(在一个终端中,或在另一台机器上),指定客户端要连接的主机地址和端口。 你可以通过运行以下命令启动 policy server:
python -m lerobot.async_inference.policy_server \
--host=127.0.0.1 \
--port=8080这将启动一个监听 127.0.0.1:8080(localhost,端口 8080)的 policy server。在此阶段,policy server 是空的,因为有关运行哪个 policy 以及使用哪些参数的所有信息都在与客户端的首次握手期间指定。使用以下命令启动客户端:
python -m lerobot.async_inference.robot_client \
--server_address=127.0.0.1:8080 \ # SERVER: the host address and port of the policy server
--robot.type=so100_follower \ # ROBOT: your robot type
--robot.port=/dev/tty.usbmodem585A0076841 \ # ROBOT: your robot port
--robot.id=follower_so100 \ # ROBOT: your robot id, to load calibration file
--robot.cameras="{ laptop: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}, phone: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \ # POLICY: the cameras used to acquire frames, with keys matching the keys expected by the policy
--task="dummy" \ # POLICY: The task to run the policy on (`Fold my t-shirt`). Not necessarily defined for all policies, such as `act`
--policy_type=your_policy_type \ # POLICY: the type of policy to run (smolvla, act, etc)
--pretrained_name_or_path=user/model \ # POLICY: the model name/path on server to the checkpoint to run (e.g., lerobot/smolvla_base)
--policy_device=mps \ # POLICY: the device to run the policy on, on the server (cuda, mps, xpu, cpu)
--actions_per_chunk=50 \ # POLICY: the number of actions to output at once
--chunk_size_threshold=0.5 \ # CLIENT: the threshold for the chunk size before sending a new observation to the server
--aggregate_fn_name=weighted_average \ # CLIENT: the function to aggregate actions on overlapping portions
--debug_visualize_queue_size=True # CLIENT: whether to visualize the queue size at runtime总而言之,你需要为以下各项指定指令:
SERVER:policy server 的地址和端口ROBOT:要连接的机器人类型、要连接的端口,以及机器人的本地 idPOLICY:要运行的 policy 类型,以及服务器上要运行的 checkpoint 的模型名称/路径。你还需要指定服务器应使用哪个设备,以及一次输出多少个 action(上限为 policy 的最大 action 数)。CLIENT:在向服务器发送新 observation 之前的块大小阈值,以及用于在重叠部分聚合 action 的函数。可选地,你还可以在运行时可视化队列大小,以帮助你调优 CLIENT 参数。重要的是,
actions_per_chunk 和 chunk_size_threshold 是为你的设置调优的关键参数。aggregate_fn_name 是用于在重叠部分聚合 action 的函数。你可以向函数注册表中添加一个新函数,或在 robot_client.py 中添加你自己的函数(参见此处)debug_visualize_queue_size 是调优 CLIENT 参数的实用工具。同步 inference 依赖于 action chunk 预测与 action 执行的交替进行。这从根本上导致 空闲帧,即机器人空闲等待 policy 输出(新的 action chunk)的帧。 反过来,inference 受到明显的实时延迟困扰,机器人仅仅因为缺少可用 action 而停止 action。 随着机器人模型规模不断增大,这个问题只会变得更加严重。

同步 inference 使机器人在 policy 计算下一个 action chunk 时处于空闲 state。
为了克服这一点,我们设计了 async inference,这是一种将 action 规划与执行解耦的范式,从而实现 (1) 更高的适应性,以及最重要的 (2) 无空闲帧。 关键在于,使用 async inference 时,下一个 action chunk 会在当前 action chunk 耗尽 之前 计算出来,因此不会出现空闲。 通过在重叠部分聚合不同的 action chunk,可以获得最新的计划和更紧密的控制循环,从而确保更高的适应性。

async inference 不会出现空闲,因为下一个块在 当前块耗尽之前就已计算完成。
policy server 是 PreTrainedPolicy 的封装,将它们与来自机器人客户端的 observation 对接。
policy server 初始化为空容器,随后用机器人客户端与 policy server 之间初始握手中指定的所请求 policy 来填充。
因此,启动 policy server 就像指定主机地址和端口一样简单。如果你在与机器人客户端相同的机器上运行 policy server,可以使用 localhost 作为主机地址。
python -m lerobot.async_inference.policy_server \
--host=127.0.0.1 \
--port=8080它监听 localhost:8080,等待来自关联 RobotClient 的传入连接,后者将在首次客户端-服务器握手期间告知要运行哪个 policy。
RobotClient 是 Robot 实例的封装,RobotClient 会将其连接到(可能是远程的)PolicyServer。 RobotClient 将 observation 流式传输到 PolicyServer,并接收在服务器上运行 inference 得到的 action chunk(我们假设服务器拥有比机器人控制器更好的计算资源)。
python -m lerobot.async_inference.robot_client \
--server_address=127.0.0.1:8080 \ # SERVER: the host address and port of the policy server
--robot.type=so100_follower \ # ROBOT: your robot type
--robot.port=/dev/tty.usbmodem585A0076841 \ # ROBOT: your robot port
--robot.id=follower_so100 \ # ROBOT: your robot id, to load calibration file
--robot.cameras="{ laptop: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}, phone: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \ # POLICY: the cameras used to acquire frames, with keys matching the keys expected by the policy
--task="dummy" \ # POLICY: The task to run the policy on (`Fold my t-shirt`). Not necessarily defined for all policies, such as `act`
--policy_type=your_policy_type \ # POLICY: the type of policy to run (smolvla, act, etc)
--pretrained_name_or_path=user/model \ # POLICY: the model name/path on server to the checkpoint to run (e.g., lerobot/smolvla_base)
--policy_device=mps \ # POLICY: the device to run the policy on, on the server
--actions_per_chunk=50 \ # POLICY: the number of actions to output at once
--chunk_size_threshold=0.5 \ # CLIENT: the threshold for the chunk size before sending a new observation to the server
--aggregate_fn_name=weighted_average \ # CLIENT: the function to aggregate actions on overlapping portions
--debug_visualize_queue_size=True # CLIENT: whether to visualize the queue size at runtime以下两个参数在每种设置中都很关键:
| 超参数 | 默认值 | 作用 |
|---|---|---|
actions_per_chunk | 50 | policy 一次输出多少个 action。典型值:10-50。 |
chunk_size_threshold | 0.7 | 当队列填充度 ≤ 50% 时,客户端发送一个新 observation。 取值在 [0, 1]。 |
`actions_per_chunk` 和 `chunk_size_threshold` 的不同取值确实会导致 不同的行为。
一方面,增大 actions_per_chunk 的值会降低最终没有 action 可执行的可能性,因为在计算新块时会有更多可用 action。
然而,actions_per_chunk 的较大值也可能导致 action 精度降低,这是由于在更长时间跨度上预测 action 所带来的复合误差。
另一方面,增大 chunk_size_threshold 的值会导致更频繁地向 PolicyServer 发送 observation 以进行 inference,从而产生更多更新的 action chunk,它们在相当大的部分上重叠。这带来了高适应性,极限情况下为每个 observation 预测一个 action chunk,而该 action chunk 在新块产生时只被少量消耗。
由于请求众多,此选项也会给 inference 流水线带来更大压力。相反,chunk_size_threshold 的值接近 0.0 时会退化为同步的边界情况,即仅在当前块耗尽时才发送新 observation。
在我们为 SmolVLA 论文开发的实验中,我们发现 actions_per_chunk 和 chunk_size_threshold 的默认值效果良好,但建议尝试不同的值,以找到最适合你设置的值。
fps。 当服务器生成新 action chunk 时,客户端并不空闲,而是逐步执行其当前 action 队列。如果这两个过程以根本不同的速度发生,客户端可能会以空队列告终。因此,如果你持续耗尽队列中的 action,应降低你的 fps。chunk_size_threshold。 0.0 的值会导致几乎顺序的行为。接近 1.0 的值 → 每一步都发送 observation(更多带宽,依赖良好的世界模型)。RobotClient,将 --debug_visualize_queue_size 设置为 True。这将在运行时绘制 action 队列大小的变化,你可以用它来找到最适合你设置的 chunk_size_threshold 值。
当传入 `--debug_visualize_queue_size` 标志时,会在运行时绘制 action 队列大小,对应不同的 `chunk_size_threshold` 水平(SmolVLA 论文中为 `g`)。
async inference 代表了实时机器人控制的一项重大进步,解决了长期困扰机器人应用的 inference latency 这一根本挑战。通过本教程,你已学会如何实现一个完整的 async inference 流水线,它消除了空闲帧,并实现更平滑、更灵敏的机器人行为。
要点回顾:
actions_per_chunk 和 chunk_size_threshold从默认参数开始实验,监控你的 action 队列大小,并迭代改进你的设置,以实现特定用例的最佳性能。 如果你想进一步讨论,欢迎加入我们的 Discord 社区,或在我们的 GitHub 仓库上提交 issue。
在 GitHub 上更新