从 Hub 加载环境

EnvHub 功能允许你用一行代码直接从 Hugging Face Hub 加载 simulation environment。这开启了一种强大的协作新模式:环境不再被锁在庞大的库内部,任何人都可以发布自定义环境并与社区分享。

什么是 EnvHub?

EnvHub 让你可以使用自己的机器人模型和场景创建自定义的机器人 simulation environment,并通过 LeRobot 框架让任何人都能轻松使用它们。

EnvHub 包存储在 Hugging Face Hub 上,可以通过 LeRobot 用一行代码无缝拉取并在你的 AI 机器人项目中使用。

借助 EnvHub,你可以:

  1. 创建并发布环境到 Hugging Face Hub 作为 Git 仓库,无需应付打包问题即可分发复杂的物理 simulation
  2. 动态加载环境,无需将它们作为软件包安装
  3. 使用 Git 语义对环境变更进行版本管理和跟踪
  4. 发现社区共享的新 simulation 任务

这种设计意味着你可以在几秒钟内从在 Hub 上发现有趣的环境,到运行实验;或者创建自己的自定义机器人和环境,而无需担心依赖冲突或复杂的安装流程。

创建 EnvHub 包时,你可以在其中构建任何你想要的内容,并使用任何你喜欢的 simulation 工具:这是你自己的发挥空间。唯一的要求是该包包含一个定义环境的 env.py 文件,使 LeRobot 能够加载和使用你的 EnvHub 包。

这个 env.py 文件需要暴露一个小的 API,以便 LeRobot 加载和运行它。具体来说,你必须提供一个 make_env(n_envs: int = 1, use_async_envs: bool = False)make_env(n_envs: int = 1, use_async_envs: bool = False, cfg: EnvConfig) 函数,它是 LeRobot 的主要入口点。它应返回以下之一:

  • 一个 gym.vector.VectorEnv(最常见)
  • 单个 gym.Env(将被自动包装)
  • 一个映射 {suite_name: {task_id: VectorEnv}} 的字典(用于多任务 benchmark)

你还可以向 make_env 传递一个 EnvConfig 对象来配置环境(例如环境数量、任务、相机名称、初始 state、控制模式、episode 长度等)。

最后,你的环境必须实现标准的 gym.vector.VectorEnv 接口,才能与 LeRobot 配合使用,包括诸如 resetstep 之类的方法。

快速开始

从 Hub 加载环境非常简单:

from lerobot.envs import make_env

# Load a hub environment (requires explicit consent to run remote code)
env = make_env("lerobot/cartpole-env", trust_remote_code=True)
**安全须知**:从 Hub 加载环境会执行第三方仓库中的 Python 代码。请仅对你信任的仓库使用 `trust_remote_code=True`。我们强烈建议固定到特定的提交哈希,以保证可复现性和安全性。

仓库结构

要让你的环境可以从 Hub 加载,你的仓库至少必须包含:

必需文件

env.py(或自定义 Python 文件)

  • 必须暴露一个 make_env(n_envs: int, use_async_envs: bool) 函数
  • 该函数应返回以下之一:
    • 一个 gym.vector.VectorEnv(最常见)
    • 单个 gym.Env(将被自动包装)
    • 一个映射 {suite_name: {task_id: VectorEnv}} 的字典(用于多任务 benchmark)

可选文件

requirements.txt

  • 列出你的环境需要的任何额外依赖
  • 用户在加载你的环境之前需要手动安装这些依赖

README.md

  • 记录你的环境:实现的任务、observation/action space、奖励等。
  • 包含使用示例和任何特殊设置说明

.gitignore

  • 从你的仓库中排除不必要的文件

示例仓库结构

my-environment-repo/
├── env.py                 # Main environment definition (required)
├── requirements.txt       # Dependencies (optional)
├── README.md             # Documentation (recommended)
├── assets/               # Images, videos, etc. (optional)
│   └── demo.gif
└── configs/              # Config files if needed (optional)
    └── task_config.yaml

创建你的环境仓库

第 1 步:定义你的环境

创建一个包含 make_env 函数的 env.py 文件:

# env.py
import gymnasium as gym

def make_env(n_envs: int = 1, use_async_envs: bool = False):
    """
    Create vectorized environments for your custom task.

    Args:
        n_envs: Number of parallel environments
        use_async_envs: Whether to use AsyncVectorEnv or SyncVectorEnv

    Returns:
        gym.vector.VectorEnv or dict mapping suite names to vectorized envs
    """
    def _make_single_env():
        # Create your custom environment
        return gym.make("CartPole-v1")

    # Choose vector environment type
    env_cls = gym.vector.AsyncVectorEnv if use_async_envs else gym.vector.SyncVectorEnv

    # Create vectorized environment
    vec_env = env_cls([_make_single_env for _ in range(n_envs)])

    return vec_env

第 2 步:本地测试

上传之前,请先在本地测试你的环境:

from lerobot.envs.utils import _load_module_from_path, _call_make_env, _normalize_hub_result

# Load your module
module = _load_module_from_path("./env.py")

# Test the make_env function
result = _call_make_env(module, n_envs=2, use_async_envs=False)
normalized = _normalize_hub_result(result)

# Verify it works
suite_name = next(iter(normalized))
env = normalized[suite_name][0]
obs, info = env.reset()
print(f"Observation shape: {obs.shape if hasattr(obs, 'shape') else type(obs)}")
env.close()

第 3 步:上传到 Hub

将你的仓库上传到 Hugging Face:

# Install huggingface_hub if needed
pip install huggingface_hub

# Login to Hugging Face
hf auth login

# Create a new repository
hf repo create my-org/my-custom-env

# Initialize git and push
git init
git add .
git commit -m "Initial environment implementation"
git remote add origin https://huggingface.co/my-org/my-custom-env
git push -u origin main

或者,使用 huggingface_hub Python API:

from huggingface_hub import HfApi

api = HfApi()

# Create repository
api.create_repo("my-custom-env", repo_type="space")

# Upload files
api.upload_folder(
    folder_path="./my-env-folder",
    repo_id="username/my-custom-env",
    repo_type="space",
)

从 Hub 加载环境

基本用法

from lerobot.envs import make_env

# Load from the hub
envs_dict = make_env(
    "username/my-custom-env",
    n_envs=4,
    trust_remote_code=True
)

# Access the environment
suite_name = next(iter(envs_dict))
env = envs_dict[suite_name][0]

# Use it like any gym environment
obs, info = env.reset()
action = env.action_space.sample()
obs, reward, terminated, truncated, info = env.step(action)

高级:固定到特定版本

为了保证可复现性和安全性,请固定到特定的 Git 修订版本:

# Pin to a specific branch
env = make_env("username/my-env@main", trust_remote_code=True)

# Pin to a specific commit (recommended for papers/experiments)
env = make_env("username/my-env@abc123def456", trust_remote_code=True)

# Pin to a tag
env = make_env("username/my-env@v1.0.0", trust_remote_code=True)

自定义文件路径

如果你的环境定义不在 env.py 中:

# Load from a custom file
env = make_env("username/my-env:custom_env.py", trust_remote_code=True)

# Combine with version pinning
env = make_env("username/my-env@v1.0:envs/task_a.py", trust_remote_code=True)

异步环境

为了在多个环境下获得更好的性能:

envs_dict = make_env(
    "username/my-env",
    n_envs=8,
    use_async_envs=True,  # Use AsyncVectorEnv for parallel execution
    trust_remote_code=True
)

URL 格式参考

Hub URL 格式支持多种模式:

模式描述示例
user/repo从 main 分支加载 env.pymake_env("lerobot/pusht-env")
user/repo@revision从特定修订版本加载make_env("lerobot/pusht-env@main")
user/repo:path加载自定义文件make_env("lerobot/envs:pusht.py")
user/repo@rev:path修订版本 + 自定义文件make_env("lerobot/envs@v1:pusht.py")

多任务环境

对于具有多个任务的 benchmark(如 LIBERO),请返回一个嵌套字典:

def make_env(n_envs: int = 1, use_async_envs: bool = False):
    env_cls = gym.vector.AsyncVectorEnv if use_async_envs else gym.vector.SyncVectorEnv

    # Return dict: {suite_name: {task_id: VectorEnv}}
    return {
        "suite_1": {
            0: env_cls([lambda: gym.make("Task1-v0") for _ in range(n_envs)]),
            1: env_cls([lambda: gym.make("Task2-v0") for _ in range(n_envs)]),
        },
        "suite_2": {
            0: env_cls([lambda: gym.make("Task3-v0") for _ in range(n_envs)]),
        }
    }

安全注意事项

**重要**:执行来自 Hub 的环境代码需要 `trust_remote_code=True` 标志。这是出于安全考虑的设计。

从 Hub 加载环境时:

  1. 先审查代码:加载之前访问仓库并检查 env.py
  2. 固定到提交:为了可复现性使用特定的提交哈希
  3. 检查依赖:审查 requirements.txt 中是否有可疑的包
  4. 使用可信来源:优先选择官方组织或知名研究者的仓库
  5. 必要时使用沙箱:在隔离的环境中运行不受信任的代码(容器、虚拟机)

安全用法示例:

# ❌ BAD: Loading without inspection
env = make_env("random-user/untrusted-env", trust_remote_code=True)

# ✅ GOOD: Review code, then pin to specific commit
# 1. Visit https://huggingface.co/trusted-org/verified-env
# 2. Review the env.py file
# 3. Copy the commit hash
env = make_env("trusted-org/verified-env@a1b2c3d4", trust_remote_code=True)

示例:从 Hub 加载 CartPole

下面是使用参考 CartPole 环境的完整示例:

from lerobot.envs import make_env
import numpy as np

# Load the environment
envs_dict = make_env("lerobot/cartpole-env", n_envs=4, trust_remote_code=True)

# Get the vectorized environment
suite_name = next(iter(envs_dict))
env = envs_dict[suite_name][0]

# Run a simple episode
obs, info = env.reset()
done = np.zeros(env.num_envs, dtype=bool)
total_reward = np.zeros(env.num_envs)

while not done.all():
    # Random policy
    action = env.action_space.sample()
    obs, reward, terminated, truncated, info = env.step(action)
    total_reward += reward
    done = terminated | truncated

print(f"Average reward: {total_reward.mean():.2f}")
env.close()

EnvHub 的优势

对环境作者而言

  • 易于分发:无需 PyPI 打包
  • 版本控制:使用 Git 对环境进行版本管理
  • 快速迭代:即时推送更新
  • 文档:Hub README 渲染效果出色
  • 社区:直接触达 LeRobot 用户

对研究人员而言

  • 快速实验:一行代码加载任何环境
  • 可复现性:固定到特定提交
  • 发现:在 Hub 上浏览环境
  • 无冲突:无需安装相互冲突的包

对社区而言

  • 不断增长的生态:更多样化的 simulation 任务
  • 标准化:统一的 make_env API
  • 协作:分叉并改进现有环境
  • 易用性:降低共享研究的门槛

故障排查

“拒绝执行远程代码”

你必须显式传递 trust_remote_code=True

env = make_env("user/repo", trust_remote_code=True)

“找不到模块 X”

Hub 环境有你需要安装的依赖:

# Check the repo's requirements.txt and install dependencies
pip install gymnasium numpy

“在模块中找不到 make_env”

你的 env.py 必须暴露一个 make_env 函数:

def make_env(n_envs: int, use_async_envs: bool):
    # Your implementation
    pass

环境返回了错误的类型

make_env 函数必须返回:

  • 一个 gym.vector.VectorEnv,或
  • 单个 gym.Env,或
  • 一个字典 {suite_name: {task_id: VectorEnv}}

最佳实践

  1. 记录你的环境:在 README 中包含 observation/action space 描述、奖励结构和终止条件
  2. 添加 requirements.txt:列出所有依赖及其版本
  3. 全面测试:推送之前确认你的环境在本地能正常工作
  4. 使用语义化版本:用版本号标记发布
  5. 添加示例:在 README 中包含使用示例
  6. 保持简单:尽可能减少依赖
  7. 为你作品授权:添加 LICENSE 文件以明确使用条款

未来方向

EnvHub 生态系统带来了令人兴奋的可能性:

  • GPU 加速物理:共享 Isaac Gym 或 Brax 环境
  • 照片级渲染:分发具有先进图形效果的环境
  • 多智能体场景:复杂的交互任务
  • 真实世界 simulation 器:物理设置的数字孪生
  • 程序化生成:无限的任务变体
  • 域随机化:预配置的 DR 流水线

随着越来越多的研究人员和开发者做出贡献,可用环境的多样性和质量将不断提升,造福整个机器人学习社区。

另请参阅

在 GitHub 上更新