前言

25年2.4日,几个月前推出π0的公司Physical Intelligence (π)宣布正式开源π0及π0-FAST,如之前所介绍的,他们对用超过 10,000 小时的机器人数据进行了预训练

该GitHub代码仓库「 π0及π0-FAST的GitHub地址:github.com/Physical-Intelligence/openpi」包括4个方面:简言之,就是

  1. π0本身的代码和权重
  2. 特定平台上特定任务的微调checkpoint
  3. 推理代码
  4. 微调代码

注意

顺带,值得一提的是,我司「七月在线」也是目前国内具身落地经验最丰富的团队之一了

  • 比如每个月都在并行开发多个具身订单,全职开发者和合作开发者总计百余人,还有我联合带的来自多个985的十几个具身研究生
  • 再比如包括且不限于在机械臂上的一系列探索(比如openpi在国产臂上的探索,详见下文的2.2节)

    vla openpi实现自主智能分拣​

如​有兴趣或也在对π0做微调的,欢迎私我一两句自我简介(比如在哪个公司做什么,或在哪个高校研几什么专业),邀请进:『七月具身:π0复现微调交流群』,更多见《具身智能线上营(偏机械臂)

第一部分 如何基于各种开源数据集微调π0

1.1 π0及π0-FAST对外开源的具体内容:2套代码、4+3套权重且支持远程推理

1.1.1 开源基础模型π0及π0-FAST,可自行微调

  1. π0基础模型的代码及权重
    可用于微调的扩散π0「标准的预训练π 0模型,该模型在 OXE 和他们的 7 个机器人平台上进行训练
    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_base
    注意,这个π0基础版 本身就已经具备了一定的指令跟随能力
  2. π0-FAST基础模型的代码及权重
    可用于微调的π0_FAST——基于FAST分词器的自回归模型
    该模型使用FAST tokenizer通过自回归离散化实现控制
    它提供了更好的语言跟踪性能,但推理成本更高(根据他们的经验,大约高出 4-5 倍),如果你更喜欢使用discretization而不是流匹配,这是一个不错的选择

    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_fast_base

1.1.2 已经微调好的模型分类:可直接推理——π0 DROID/π0 ALOHA/π0 Libero

且他们还提供了专门为ALOHA和DROID平台上一些简单任务做了微调的checkpoint,相当于在ALOHA 和 DROID 收集的相对较小的数据集上进行了微调

即several checkpoints that are fine-tuned for a few simple tasks on a few widely available platforms such as ALOHA and DROID,当然,它们可能无法推广到你的特定设置

  1. π0 DROID:在DROID 数据集上微调过的扩散π0
    DROID数据集由 Franka 机械臂在不同环境中执行的不同任务组成的开源数据集,且他们通过视频展示了 openpi 在训练数据中从未见过的环境中运行,这些环境遍布世界各地,包括蒙特利尔大学、华盛顿大学、韩国科学技术研究院等

    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_droid
    推理速度比π0-FAST-DROID快,但可能不遵循语言命令
  2. π0-FAST DROID:在DROID数据集微调过的π0-FAST
    可以在DROID机器人平台上的新场景中执行各种简单的零样本桌面操控任务,例如“从烤面包机中取出面包”任务

    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_fast_droid
  3. π0 ALOHA:含三套权重
    根据 ALOHA(适合灵巧操作的低成本双臂系统) 数据进行了微调,可以在ALOHA机器人平台上进行毛巾折叠、食物舀取和其他任务,相当于提供了一套针对 ALOHA 平台上的任务进行微调的检查点「这些检查点可能对整体机器人设置非常敏感,但能够在完全未出现在训练数据中的全新 ALOHA 站点上运行它们

    不同任务对应的不同checkpoint路径分别为
    折叠毛巾:s3://openpi-assets/checkpoints/pi0_aloha_towel
    从容器中取出食物:s3://openpi-assets/checkpoints/pi0_aloha_tupperware
    打开笔帽:s3://openpi-assets/checkpoints/pi0_aloha_pen_uncap
  4. π0 Libero
    此检查点针对 Libero 基准进行了微调,并且可以在 Libero 任务上进行开箱即用的评估

1.1.3 对预训练模型进行推理:还可连远程GPU进行推理

他们还开源了在多个显示世界和仿真机器人平台上推理运行的示例代码(example code to run inference on several real-world and simulated robot platforms)

 以下是跑π0-FAST-DROID模型的预训练检查点

from openpi.training import config
from openpi.policies import policy_config
from openpi.shared import download

config = config.get_config("pi0_fast_droid")
checkpoint_dir = download.maybe_download("s3://openpi-assets/checkpoints/pi0_fast_droid")

# Create a trained policy.
policy = policy_config.create_trained_policy(config, checkpoint_dir)

# Run inference on a dummy example.
example = {
    "observation/exterior_image_1_left": ...,
    "observation/wrist_image_left": ...,
    ...
    "prompt": "pick up the fork"
}
action_chunk = policy.infer(example)["actions"]

且也可以在示例笔记本中测试这一点,他们还提供了在DROIDALOHA机器人上运行预先训练的检查点的推理的详细分步示例

此外,特别值得一提的是:他们还提供了远程推理的示例和代码

  1. 远程推理详见远程运行π0模型
    模型可以在不同的服务器上运行,并通过 websocket 连接将操作传输到机器人。这样可以轻松在机器人外使用更强大的 GPU,并将机器人和策略环境分开

    \rightarrow  要启动远程策略服务器,只需运行以下命令:
    uv run scripts/serve_policy.py --env=[DROID | ALOHA | LIBERO]
          其中,参数env指定哪个π0 checkpoint 应该被加载,比如是ALOHA还是LIBERO

    \rightarrow  事实上,在后台,这个脚本将执行如下命令,可以使用它来启动策略服务器,例如用于你自己训练的检查点——这里是 DROID 环境的一个示例
    uv run scripts/serve_policy.py policy:checkpoint --policy.config=pi0_fast_droid --policy.dir=s3://openpi-assets/checkpoints/pi0_fast_droid
          其中,config这将启动一个策略服务器,该服务器将执行和参数指定的策略dir。该策略将在指定端口(默认值:8000)上执行
  2. 接下来,安装openpi-client
    cd $OPENPI_ROOT/packages/openpi-client
    pip install -e .
    然后,便可以使用客户端查询远程策略服务器
    # 导入图像处理工具和策略客户端模块
    from openpi_client import image_tools
    from openpi_client import websocket_client_policy
    
    # 在episode循环之外,初始化策略客户端
    # 指向策略服务器的主机和端口(默认为本地主机和8000端口)
    client = websocket_client_policy.WebsocketClientPolicy(host="localhost", port=8000)
    
    for step in range(num_steps):
        # 构建观测数据
        # 客户端侧对图像进行缩放,以最小化带宽/延迟。始终以uint8格式返回图像
        # 提供了图像缩放+uint8转换的工具,以匹配训练过程
        # 针对预训练的pi0模型的典型缩放尺寸为224
        # 注意:可以以未归一化的形式传递本体感知`状态`,归一化将在服务器端处理
        
        # 创建一个包含图像和状态的观测字典
        observation = {
            # 将图像转换为uint8格式,并调整大小为224x224
            "observation/image": image_tools.convert_to_uint8(
                image_tools.resize_with_pad(img, 224, 224)
            ),
            # 将手腕图像转换为uint8格式,并调整大小为224x224
            "observation/wrist_image": image_tools.convert_to_uint8(
                image_tools.resize_with_pad(wrist_img, 224, 224)
            ),
    
            # 包含本体感知状态
            "observation/state": state,
            # 包含任务指令
            "prompt": task_instruction,
        }
    
        # 使用当前观测调用策略服务器
        # 返回一个形状为(action_horizon, action_dim)的动作块
        # 注意:通常你只需要每隔N步调用一次策略,并在剩余步骤中以开环方式执行预测的动作块中的步骤
        action_chunk = client.infer(observation)["actions"]
    
        # 在环境中执行动作
        ...
    在此,主机和端口参数指定了远程策略服务器的 IP 地址和端口。也可以将这些参数作为命令行参数传递给你的机器人代码,或者在你的机器人代码库中直接进行硬编码
    观察结果是一个观察值字典和prompt,遵循您正在服务的策略的策略输入规范。在简单客户端示例中,有针对不同环境如何构建此字典的具体示例

总之,他们还提供了一个简单的客户端示例

而这个简单的客户端示例,即指的是无需机器人即可测试推理的脚本

  1. 使用标志指定要使用的运行时环境--env。你可以运行以下命令查看可用的选项:
    uv run examples/simple_client/main.py --help
  2. 如果使用docker
    export SERVER_ARGS="--env ALOHA_SIM"
    docker compose -f examples/simple_client/compose.yml up --build
    如果不使用docker
    终端窗口 1——客户端:
    uv run examples/simple_client/main.py --env DROID
    终端窗口 2——服务器端:
    uv run scripts/serve_policy.py --env DROID

此脚本将生成随机观察并使用模型运行推理。有关更多详细信息,请参阅此处

1.2 安装与运行

1.2.1 如何安装本openpi开源库

要运行此存储库中的模型,需要至少具有以下规格的 NVIDIA GPU。这些估算假设单个 GPU,但也可以通过fsdp_devices在训练配置中进行配置来使用具有模型并行性的多个 GPU,以减少每个 GPU 的内存要求。另请注意,当前的训练脚本尚不支持多节点训练

模式 所需内存 示例 GPU
推理 > 8 GB RTX 4090
微调(LoRA) > 22.5 GB RTX 4090
微调(完整版) > 70 GB A100(80GB)/H100

PS,他们说该 repo 已在 Ubuntu 22.04 上测试过,其他操作系统可能不支持

以下是安装过程

  1. 克隆此 repo 时,请确保更新子模块:
    git clone --recurse-submodules git@github.com:Physical-Intelligence/openpi.git
    
    # Or if you already cloned the repo:
    git submodule update --init --recursive
  2. 使用uv来管理 Python 依赖项。可参阅uv 安装说明进行设置
    安装 uv 后,运行以下命令设置环境:
    GIT_LFS_SKIP_SMUDGE=1 uv sync
    GIT_LFS_SKIP_SMUDGE=1 uv pip install -e
    注意:GIT_LFS_SKIP_SMUDGE=1需要将 LeRobot 作为依赖项
    Docker:作为 uv 安装的替代方案,他们还提供了使用 Docker 安装 openpi 的说明
    如果在系统设置中遇到问题,还可以考虑使用 Docker 来简化安装,详情请参阅Docker 设置

1.2.2 如何把该库的ALOHA sim环境跑起来

此外,该开源库还提供ALOHA SIM

  • 如使用docker
    export SERVER_ARGS="--env ALOHA_SIM"
    docker compose -f examples/aloha_sim/compose.yml up --build
  • 如没有docker,则采用C/S架构「我在上一篇文章中也解读过了这个C/S架构了,详见此文的《π0源码剖析——从π0模型架构的实现(如何基于PaLI-Gemma和扩散策略去噪生成动作),到基于C/S架构下的模型训练与部署》的第三部分 模型的训练与部署:基于客户端-服务器C/S架构
    \rightarrow  终端窗口1:建立策略客户端
    # Create virtual environment
    uv venv --python 3.10 examples/aloha_sim/.venv
    source examples/aloha_sim/.venv/bin/activate
    uv pip sync examples/aloha_sim/requirements.txt
    uv pip install -e packages/openpi-client
    
    # Run the simulation
    MUJOCO_GL=egl python examples/aloha_sim/main.py
    注意:如果看到 EGL 错误,则可能需要安装以下依赖项
    sudo apt-get install -y libegl1-mesa-dev libgles2-mesa-dev
    \rightarrow  终端窗口2:建立策略服务器
    # Run the server
    uv run scripts/serve_policy.py --env ALOHA_SIM

// 待更

1.3 基于自己的数据集微调π0基础模型

1.3.1 利用Libero数据集微调π0基础模型的三个步骤

此外,他们还提供了用于根据用户自身任务和平台微调π0的代码(code for fine-tuning the base π0 model for your own tasks and platforms),这个微调π0的代码 个人觉得很有价值且huggingface上有相应的pytorch接口

Physical Intelligence (π)认为,1 到 20 小时的数据足以微调各种任务,具体而言,如果想利用自己的数据上微调π0基础模型,只需以下三个步骤即可:

  1. 第一步,将Libero数据集转换为LeRobot数据集v2.0格式
    作者提供了一个脚本convert_libero_data_to_lerobot.py下面,我会详细分析一下这个脚本」,用于将 Libero 数据转换为 LeRobot 数据集 v2.0 格式,且可以轻松修改它以转换你自己的数据

    比如从此处下载原始 Libero 数据集,然后使用以下命令运行脚本
    uv run examples/libero/convert_libero_data_to_lerobot.py --data_dir /path/to/your/libero/data
    且作为示例,已将 BiPlay 代码库中的 aloha_pen_uncap_diverse_raw 数据集转换,并将其上传至 HuggingFace Hub,地址为 physical-intelligence/aloha_pen_uncap_diverse
  2. 第二步,定义使用自定义数据集的训练配置,并运行训练
    提供pi0_aloha_pen_uncap 配置作为示例,参考根README以了解如何使用新配置运行训练

    比如下面是 Libero 示例配置,可以根据自己的数据集进行修改:
    \rightarrow  LiberoInputs和LiberoOutputs:定义从 Libero 环境到模型的数据映射,反之亦然——将用于训练和推理
    \rightarrow  LeRobotLiberoDataConfig:定义了如何处理已经转换为LeRobot格式的Libero数据以用于训练,涉及数据配置、模型转换、数据转换
    可能马上就有同学疑问了,不是已经在上面第一步做了数据转换了么——把Libero数据转换成LeRobot格式的 咋还要转呢?
    原因很简单,这两个转换 不一样
    一者,对LeRobotLiberoDataConfig源码的分析 请见此文《π0源码剖析——从π0模型架构的实现(如何基于PaLI-Gemma和扩散策略去噪生成动作),到基于C/S架构下的模型训练与部署》的「2.1.2 数据集配置:包含ALOHA、Libero两套数据集——LeRobotLiberoDataConfig」
    二者 下文会对比下 这两个转换的不同

    \rightarrow  TrainConfig:定义微调超参数、数据配置和权重加载器

    在运行训练之前,可以计算训练数据的标准化统计数据,使用训练配置的名称运行以下脚本
    uv run scripts/compute_norm_stats.py --config-name pi0_fast_libero
    接下来,可以使用以下命令开始训练(--overwrite如果使用相同的配置重新运行微调,则该标志用于覆盖现有检查点)
    XLA_PYTHON_CLIENT_MEM_FRACTION=0.9 uv run scripts/train.py pi0_fast_libero --exp-name=my_experiment --overwrite
    该命令会将训练进度记录到控制台并将检查点保存到checkpoints目录中。还可以在 Weights & Biases 仪表板上监控训练进度。为了最大限度地利用 GPU 内存,请XLA_PYTHON_CLIENT_MEM_FRACTION=0.9在运行训练之前设置 - 这使 JAX 能够使用高达 90% 的 GPU 内存(而默认值为 75%)
  3. 第三步,启动策略服务器并运行推理
    训练完成后,可以通过启动策略服务器,然后从 Libero 评估脚本中查询它来运行推理。启动模型服务器很容易「他们在此示例中使用迭代 20,000 的检查点,但可以根据需要进行修改」
    uv run scripts/serve_policy.py policy:checkpoint
     --policy.config=pi0_fast_libero
     --policy.dir=checkpoints/pi0_fast_libero/my_experiment/20000

接下来,针对上面的前两步做两点重要的补充

一方面,针对上面第一步提到的Libero数据集转换脚本convert_libero_data_to_lerobot.py的解析

下面使用Libero数据集(存储在RLDS格式中)作为示例——将RLDS格式转换为LeRobot格式,如何修改以适应其他自定义格式的数据


首先,咱们明确下Libero数据集的层级结构

Libero数据集
├── libero_10_no_noops/
├── libero_goal_no_noops/
├── libero_object_no_noops/
└── libero_spatial_no_noops/
    └── train/
                └── episode
                            └── steps
                                      ├── observation
                                      │      ├── image (256x256x3)
                                      │      ├── wrist_image (256x256x3)
                                      │      └── state (8维向量)
                                      ├── action (7维向量)
                                      └── language_instruction (文本)

接下来,按如下步骤逐一执行

  1. 关键常量定义
    # 输出数据集名称,也用于Hugging Face Hub
    REPO_NAME = "your_hf_username/libero"  
    RAW_DATASET_NAMES = [
        "libero_10_no_noops",
        "libero_goal_no_noops",
        "libero_object_no_noops",
        "libero_spatial_no_noops",
    ]  # 将多个Libero数据集合并为一个训练数据集
  2. 定义主函数结构
    def main(data_dir: str, *, push_to_hub: bool = False):
    主函数接受两个参数:
    data_dir: 原始数据目录路径
    push_to_hub: 是否推送到HuggingFace Hub的标志
  3. 清理现有数据
        output_path = LEROBOT_HOME / REPO_NAME
        if output_path.exists():
            shutil.rmtree(output_path)
    确保输出目录干净,删除任何已存在的数据
  4. 创建LeRobot数据集:包含处理图像、状态和动作数据
        # 创建LeRobot数据集,定义要存储的特征
        # OpenPi假设本体感知数据存储在`state`中,动作存储在`action`中
        # LeRobot假设图像数据的dtype为`image`
        dataset = LeRobotDataset.create(
            repo_id=REPO_NAME,           # 数据集的仓库ID
            robot_type="panda",          # 机器人类型
            fps=10,                      # 帧率
            features={                   # 特征定义
                "image": {                  # image数据
                    "dtype": "image",                             # 数据类型
                    "shape": (256, 256, 3),                       # 数据形状
                    "names": ["height", "width", "channel"],      # 维度名称
                },
                "wrist_image": {            # 手腕image数据
                    "dtype": "image", 
                    "shape": (256, 256, 3),  
                    "names": ["height", "width", "channel"], 
                },
                "state": {                  # 状态数据
                    "dtype": "float32",  
                    "shape": (8,), 
                    "names": ["state"],  
                },
                "actions": {                # 动作数据
                    "dtype": "float32", 
                    "shape": (7,),  
                    "names": ["actions"],  
                },
            },
            image_writer_threads=10,           # 图像写入线程数
            image_writer_processes=5,          # 图像写入进程数
        )
    定义数据集结构,包括:
    - 机器人类型:panda
    - 帧率:10fps
    - 特征定义:
      - 图像:256x256x3的RGB图像
      - 手腕图像:同样的格式
      - 状态:8维浮点数向量
      - 动作:7维浮点数向量
    - 多线程/进程配置用于图像处理
  5. 数据转换循环
        # 遍历原始Libero数据集并将episode写入LeRobot数据集
        # 你可以根据自己的数据格式修改此部分
        for raw_dataset_name in RAW_DATASET_NAMES:
            raw_dataset = tfds.load(raw_dataset_name, data_dir=data_dir, split="train")  # 加载原始数据集
            for episode in raw_dataset:  # 遍历每个episode
                for step in episode["steps"].as_numpy_iterator():      # 遍历每个步骤
                    dataset.add_frame(
                        {
                            "image": step["observation"]["image"],      # 添加图像数据
                            "wrist_image": step["observation"]["wrist_image"],  # 添加手腕图像数据
                            "state": step["observation"]["state"],      # 添加状态数据
                            "actions": step["action"],                  # 添加动作数据
                        }
                    )
                dataset.save_episode(task=step["language_instruction"].decode())  # 保存episode并解码语言指令
    这部分实现了数据转换的核心逻辑:
    1. 遍历所有原始数据集
    2. 对每个数据集中的每个episode
    3. 处理episode中的每一步
    4. 保存frame数据和语言指令
  6. 数据集的整合与发布
    最后的处理步骤:
    1. 整合数据集(不计算统计信息)
    2. 可选:推送到HuggingFace Hub,包括:
       - 添加标签
       - 设置为公开
       - 包含视频
       - 指定许可证

脚本可以通过以下命令运行:

uv run examples/libero/convert_libero_data_to_lerobot.py --data_dir /path/to/your/data

如果要推送到HuggingFace Hub:

uv run examples/libero/convert_libero_data_to_lerobot.py --data_dir /path/to/your/data --push_to_hub

总之,这个脚本展示了如何构建标准化的机器人学习数据集,为训练像Pi0这样的模型提供数据支持

二方面,这个上面第一步提到的convert_libero_data_to_lerobot与上面第二步提到的LeRobotLiberoDataConfig 中的各自转换的不同

  1. 不同的处理阶段:
    - `convert_libero_data_to_lerobot` 是离线数据准备阶段的转换
    - `LeRobotLiberoDataConfig` 中的转换是在训练和推理过程中实时应用的,至于详情,参见上面提到过的此文「2.1.2 数据集配置:包含ALOHA、Libero两套数据集——LeRobotLiberoDataConfig」
  2. 键名映射的特殊性:
       - LeRobotLiberoDataConfig中的`repack_transform` 专门负责将数据集键名映射到推理环境期望的键名
       - repack_transform的注释明确说明:"重新打包转换仅应用于来自数据集的数据,不用于推理阶段",这确保了训练数据和推理时输入格式的一致性
  3. 模型特定转换
    LeRobotLiberoDataConfig中的处理超出了简单的数据格式转换范围,比如其中的`data_transforms` 和 `model_transforms` 包含了许多模型特定的处理,比如data_transforms中包含的LiberoInputs/LiberoOutputs 处理
  4. 动作表示转换
       - LeRobotLiberoDataConfig代码中有将绝对动作转换为相对动作的特殊逻辑
       - 注释解释:"pi0模型是在相对动作上训练的",这是模型训练需求,而非数据格式问题
  5. 训练推理一致性
       - LeRobotLiberoDataConfig中的`data_transforms` 在注释中明确表示:"应用于来自数据集的数据*和*推理过程中的数据"
       - 这保证了训练和推理阶段处理的一致性

简言之,convert_libero_data_to_lerobot只涉及到数据格式的简单转换,但LeRobotLiberoDataConfig转换、处理更多

1.3.2 在 UR5 数据集上微调 pi0

// 待更

第二部分 进一步实战:如何基于你自己的私有数据集微调π0——含我司的微调实践

2.1 如何在真实环境中采集数据,一步一步微调π0然后部署到机械臂上

要在真实环境中采集数据并用于微调π0模型,需要完成以下几个步骤

2.1.1 准备环境、硬件、安装依赖、采集环境

  1. 安装Git 并下载源码:
    Git
    sudo apt update
    sudo apt install git
    下载源码
    git clone https://github.com/Physical-Intelligence/openpi.git
    在源码中,新建并切换到 pi0 环境「openpi 0.1.0 明确要求 Python >= 3.11,所以在 Python 3.10 下就会报“unsatisfiable”错误」:
    conda create -n pi0 python=3.11 -y
    conda activate pi0
  2. 在新环境里安装 uv:
    pip install uv
    同步依赖并安装
    # 回到项目根目录
    GIT_LFS_SKIP_SMUDGE=1 uv sync
    GIT_LFS_SKIP_SMUDGE=1 uv pip install -e .
    如姚博士所说,如果出现draccus 拉取失败(SSL connection timeout),这一般是网络问题,多试几次或者科学上网

如姚博士所说,如果出现下面这个离谱的bug

Using Python 3.11.11 environment at: /home/yejiangchen/anaconda3/envs/pi0
    Updated https://github.com/huggingface/lerobot (6674e368249472c91382eb54bb8501c94c7f0c56)
  × No solution found when resolving dependencies:
  ╰─▶ Because there are no versions of pyav and lerobot==0.1.0 depends on pyav>=12.0.5, we can conclude that lerobot==0.1.0 cannot be used.
      And because only lerobot==0.1.0 is available and openpi==0.1.0 depends on lerobot, we can conclude that openpi==0.1.0 cannot be used.
      And because only openpi==0.1.0 is available and you require openpi, we can conclude that your requirements are unsatisfiable.
  1. 考虑到pyav 在 pip 上叫做 av,所以 pip 安装一下
    (pi0) yejiangchen@yejiangchen-System-Product-Name:~/Desktop/Codes/openpi-main$ pip install av
    Collecting av
      WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', TimeoutError('_ssl.c:989: The handshake operation timed out'))': /packages/f8/9a/8ffabfcafb42154b4b3a67d63f9b69e68fa8c34cb39ddd5cb813dd049ed4/av-14.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata
      Downloading av-14.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.6 kB)
    Downloading av-14.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (35.3 MB)
       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 35.3/35.3 MB 6.4 MB/s eta 0:00:00
    Installing collected packages: av
    Successfully installed av-14.4.0
    但是但是再次运行,依然后会报这个错:
    (pi0) yejiangchen@yejiangchen-System-Product-Name:~/Desktop/Codes/openpi-main$ GIT_LFS_SKIP_SMUDGE=1 uv pip install -e .
    Using Python 3.11.11 environment at: /home/yejiangchen/anaconda3/envs/pi0
        Updated https://github.com/huggingface/lerobot (6674e368249472c91382eb54bb8501c94c7f0c56)
      × No solution found when resolving dependencies:
      ╰─▶ Because there are no versions of pyav and lerobot==0.1.0 depends on pyav>=12.0.5, we can conclude that lerobot==0.1.0 cannot be used.
          And because only lerobot==0.1.0 is available and openpi==0.1.0 depends on lerobot, we can conclude that openpi==0.1.0 cannot be used.
          And because only openpi==0.1.0 is available and you require openpi, we can conclude that your requirements are unsatisfiable.
  2. 先看一下 pyproject.toml
    [project]
    name = "openpi"
    version = "0.1.0"
    description = "Physical Intelligence open source repo"
    readme = "README.md"
    requires-python = ">=3.11"
    license = { file = "LICENSE" }
    dependencies = [
        "augmax>=0.3.4",
        "dm-tree>=0.1.8",
        "einops>=0.8.0",
        "equinox>=0.11.8",
        "flatbuffers>=24.3.25",
        "flax==0.10.2",
        "fsspec[gcs]>=2024.6.0",
        "gym-aloha>=0.1.1",
        "imageio>=2.36.1",
        "jax[cuda12]==0.5.0",
        "jaxtyping==0.2.36",
        "lerobot",
        "ml_collections==1.0.0",
        "numpy>=1.26.4",
        "numpydantic>=1.6.6",
        "opencv-python>=4.10.0.84",
        "openpi-client",
        "orbax-checkpoint==0.11.1",
        "pillow>=11.0.0",
        "s3fs>=2024.9.0",
        "sentencepiece>=0.2.0",
        "torch>=2.5.1",
        "tqdm-loggable>=0.2",
        "typing-extensions>=4.12.2",
        "tyro>=0.9.5",
        "wandb>=0.19.1",
        "boto3>=1.35.7",
        "types-boto3[boto3,s3]>=1.35.7",
        "filelock>=3.16.1",
        "beartype>=0.19.0",
        "treescope>=0.1.7",
        "transformers==4.48.1",
    ]
     
     
    [project.urls]
    Repository = "https://github.com/Physical-Intelligence/openpi"
     
    [dependency-groups]
    dev = [
        "pytest>=8.3.4",
        "ruff>=0.8.6",
        "pre-commit>=4.0.1",
        "ipykernel>=6.29.5",
        "ipywidgets>=8.1.5",
        "matplotlib>=3.10.0",
        "pynvml>=12.0.0",
    ]
     
     
    [tool.uv.sources]
    openpi-client = { workspace = true }
    lerobot = { git = "https://github.com/huggingface/lerobot", rev = "6674e368249472c91382eb54bb8501c94c7f0c56" }
     
    [tool.uv.workspace]
    members = ["packages/*"]
     
    [tool.ruff]
    line-length = 120
    target-version = "py311"
    extend-exclude = ["docker", "third_party"]
     
    [tool.ruff.lint]
    # https://docs.astral.sh/ruff/rules/
    select = [
        "B",
        "C4",
        "DTZ",
        "E4",
        "E7",
        "E9",
        "F",
        "FBT",
        "FURB",
        "I",
        "ICN",
        "ISC",
        "LOG",
        "N",
        "PD",
        "PERF",
        "PIE",
        "PLC",
        "PLE",
        "PLR1",
        "PLR5",
        "PLW",
        "PT",
        "PTH",
        "Q",
        "RET",
        "RUF",
        "SIM",
        "SLF",
        "T10",
        "T20",
        "UP",
        "W",
    ]
    ignore = [
        "F722",   # Conflicts with array typing.
        "T201",   # We use print statements.
        "PD008",  # Lots of false positives.
        "ISC001", # Disabling to support ruff format.
    ]
    unfixable = [
        "B905", # Fix defaults to strict=False, which is not what we want.
    ]
     
    [tool.ruff.lint.isort]
    force-single-line = true
    force-sort-within-sections = true
    single-line-exclusions = ["collections.abc", "typing", "typing_extensions"]
    known-third-party = ["wandb"]
     
    [build-system]
    requires = ["hatchling"]
    build-backend = "hatchling.build"
     
    [tool.pytest.ini_options]
    markers = ["manual: should be run manually."]
    testpaths = ["src", "scripts", "packages"]
    可以看出,因为openpi 在 pyproject.toml 里把 lerobot 当成了一个普通的 PyPI 依赖来安装『因此它去 PyPI 拉的是那个旧包,元数据里依赖 pyav,导致又回到 “找不到 pyav” 的死循环

    因此解决思路为:先把本地的 lerobot 源码安装到你的环境里(editable),让 pip 先用本地版本,就不再去 PyPI 拉旧版;而本地版本的 pyproject.toml 本身依赖的是 av>=12.0.5(你已经满足),就能跳过那个 “pyav” 错误
  3. 故首先,下载最新版 lerobot,然后在 lerobot 中激活 pi0 环境并安装
     GIT_LFS_SKIP_SMUDGE=1 uv pip install -e .
    此后,修改 pyproject.toml:
    [project]
    name = "openpi"
    version = "0.1.0"
    description = "Physical Intelligence open source repo"
    readme = "README.md"
    requires-python = ">=3.11"
    license = { file = "LICENSE" }
    dependencies = [
        "augmax>=0.3.4",
        "dm-tree>=0.1.8",
        "einops>=0.8.0",
        "equinox>=0.11.8",
        "flatbuffers>=24.3.25",
        "flax==0.10.2",
        "fsspec[gcs]>=2024.6.0",
        "gym-aloha>=0.1.1",
        "imageio>=2.36.1",
        "jax[cuda12]==0.5.0",
        "jaxtyping==0.2.36",
        # 本地 lerobot 源码依赖,注意整行要放在双引号内:
        "lerobot @ file:///home/yejiangchen/Desktop/Codes/lerobot-main#egg=lerobot",
        "ml_collections==1.0.0",
        "numpy>=1.26.4",
        "numpydantic>=1.6.6",
        "opencv-python>=4.10.0.84",
        "openpi-client",
        "orbax-checkpoint==0.11.1",
        "pillow>=11.0.0",
        "s3fs>=2024.9.0",
        "sentencepiece>=0.2.0",
        "torch>=2.5.1",
        "tqdm-loggable>=0.2",
        "typing-extensions>=4.12.2",
        "tyro>=0.9.5",
        "wandb>=0.19.1",
        "boto3>=1.35.7",
        "types-boto3[boto3,s3]>=1.35.7",
        "filelock>=3.16.1",
        "beartype>=0.19.0",
        "treescope>=0.1.7",
        "transformers==4.48.1",
    ]
     
    [project.urls]
    Repository = "https://github.com/Physical-Intelligence/openpi"
     
    [dependency-groups]
    dev = [
        "pytest>=8.3.4",
        "ruff>=0.8.6",
        "pre-commit>=4.0.1",
        "ipykernel>=6.29.5",
        "ipywidgets>=8.1.5",
        "matplotlib>=3.10.0",
        "pynvml>=12.0.0",
    ]
     
    [tool.uv.sources]
    openpi-client = { workspace = true }
     
    [tool.uv.workspace]
    members = ["packages/*"]
     
    [tool.ruff]
    line-length = 120
    target-version = "py311"
    extend-exclude = ["docker", "third_party"]
     
    [tool.ruff.lint]
    select = [
        "B", "C4", "DTZ", "E4", "E7", "E9", "F", "FBT", "FURB", "I", "ICN",
        "ISC", "LOG", "N", "PD", "PERF", "PIE", "PLC", "PLE", "PLR1", "PLR5",
        "PLW", "PT", "PTH", "Q", "RET", "RUF", "SIM", "SLF", "T10", "T20",
        "UP", "W",
    ]
    ignore = [
        "F722", "T201", "PD008", "ISC001",
    ]
    unfixable = [
        "B905",
    ]
     
    [tool.ruff.lint.isort]
    force-single-line = true
    force-sort-within-sections = true
    single-line-exclusions = ["collections.abc", "typing", "typing_extensions"]
    known-third-party = ["wandb"]
     
    [build-system]
    requires = ["hatchling"]
    build-backend = "hatchling.build"
     
    # 允许在 dependencies 中使用 Git-/file-URL 直接引用
    [tool.hatch.metadata]
    allow-direct-references = true
     
    [tool.pytest.ini_options]
    markers = ["manual: should be run manually."]
    testpaths = ["src", "scripts", "packages"]
    然后在 openpi 项目的根目录里再执行一次安装:
    GIT_LFS_SKIP_SMUDGE=1 uv pip install -e .

这时候,pip 的依赖解析会:

  1. 直接使用已经安装好的、依赖 av>=12.0.5 的本地 lerobot
  2. 跳过去 PyPI 上的旧版 lerobot(也就不会再提 pyav 了)
  3. 把 openpi 的其余依赖一次性安装完毕

最后,便可运行成功

更多,可以参见姚博士所写的此文:openpi π₀ 项目部署运行逻辑(二)——环境配置与测试

2.1.2 数据的采集与转换

从`convert_aloha_data_to_lerobot.py`脚本中可以看出,Aloha机器人的数据是以HDF5格式存储的,并且需要转换成LeRobot数据集格式才能用于训练。数据包含了以下内容:

  1. 机器人关节状态(qpos)
  2. 动作(action)
  3. 可选的速度(qvel)和力矩(effort)数据
  4. 多个相机视角的图像(包括机器人基座相机和手腕相机)

采集步骤如下

  1. 设置数据采集环境
    # 在一个终端窗口启动ROS节点
    cd /Users/mac/Desktop/openpi-main
    source examples/aloha_real/.venv/bin/activate
    roslaunch aloha ros_nodes.launch
  2. 执行示范任务并记录数据
    使用Aloha机器人的现有数据收集工具(在aloha目录中)来记录示范数据。这通常涉及:
    - 设置你想要机器人执行的任务场景
    - 使用示教模式记录人类演示 
    - 将数据保存为HDF5格式的episode文件
  3. 数据转换
    使用提供的转换脚本将Aloha格式的数据转换为LeRobot格式:
    uv run examples/aloha_real/convert_aloha_data_to_lerobot.py --raw-dir /path/to/your/episodes --repo-id your-org/your-dataset-name

2.1.3 定义训练配置

下面是一个很好的示例配置 `pi0_aloha_pen_uncap`,它展示了如何为自定义的Aloha数据集创建训练配置。根据这个示例,你可以创建自己的配置:

  1. 创建自定义训练配置
    在 config.py 中添加一个新的训练配置,参考 `pi0_aloha_pen_uncap` 示例:
    TrainConfig(
        name="pi0_your_custom_task",      # 为你的任务设置一个唯一名称
        model=pi0.Pi0Config(),            # 使用标准π0模型或根据需要修改
        data=LeRobotAlohaDataConfig(
            repo_id="your-org/your-dataset-name",  # 你转换后的数据集名称
            assets=AssetsConfig(
                assets_dir="s3://openpi-assets/checkpoints/pi0_base/assets",
                asset_id="trossen",                # 根据你的机器人平台选择
            ),
    
            # 例如:"拿起杯子"
            default_prompt="你的任务指令", 
  2. 根据你的数据集结构定义重包装转换
            # 根据你的数据集结构定义重包装转换
            repack_transforms=_transforms.Group(
                inputs=[
                    _transforms.RepackTransform(
                        {
                            "images": {
                                "cam_high": "observation.images.cam_high",
                                "cam_left_wrist": "observation.images.cam_left_wrist",
                                "cam_right_wrist": "observation.images.cam_right_wrist",
                            },
                            "state": "observation.state",
                            "actions": "action",
                        }
                    )
                ]
            ),
  3. 如果是本地数据集
            base_config=DataConfig(
                # 如果是本地数据集,设为True
                local_files_only=False,  
            ),
        ),
    
        weight_loader=weight_loaders.CheckpointWeightLoader("s3://openpi-assets/checkpoints/pi0_base/params"),
         # 根据数据集大小调整
        num_train_steps=20_000, 
    )
  4. 选择合适的模型变体
      - 对于标准微调,使用 `pi0.Pi0Config()`
      - 对于低内存微调,使用 `pi0.Pi0Config(paligemma_variant="gemma_2b_lora", action_expert_variant="gemma_300m_lora")`
      - 如果要冻结VLM参数只调整动作专家的参数,记得添加 `freeze_filter` 参数

但有一些注意事项:

  1. 对于 `assets=AssetsConfig` 部分,需要确认 `asset_id="trossen"` 是否匹配你的机器人平台
  2. `repo_id` 需要确保已正确上传到HuggingFace或配置为本地数据集

2.1.4 开始训练

训练可以通过以下命令执行:

# 使用你的自定义配置名称
uv run scripts/train.py --config pi0_your_custom_task --exp_name your_experiment_name

训练参数说明:

  1. `--config`:你的配置名称
  2. `--exp_name`:实验名称,用于区分不同的训练运行
  3. 还可以添加 `--batch_size`、`--num_train_steps` 等参数覆盖配置中的默认值

对于训练进度的监控,如果你在配置中启用了wandb(`wandb_enabled=True`),可以通过Weights & Biases平台监控训练进度

2.1.5 测试和部署训练好的模型

  1. 先启动ROS节点
  2. 启动策略服务器
    # 加载训练好的模型
    uv run scripts/serve_policy.py --env ALOHA --checkpoint_path ./checkpoints/pi0_your_custom_task/your_experiment_name/latest/params --default_prompt "你的任务指令"
  3. 同时,在另一个终端运行机器人控制程序:
    # 在另一个终端运行机器人控制程序
    python -m examples.aloha_real.main

2.2 我司七月的部分实际落地实践:过程中涉及微调openpi

七月内部从24年q3开始,一直给各种工厂做场景落地和定制开发,25年q3开始,一个个过了保密期之后,可以逐一拿出部分 分享下

2.2.1 一周,完成openpi在国产臂上的部署:含训练和推理,最终自主抓零食

因为团队以前经验的积累,加上有朋友的帮助,使得

  • 我司长沙具身分部在25年7.7-7.9短短3天内,便把openpi在国产piper机械臂上部署好了,并完成数据的采集
  • 且于7.10-7.11两天完成了训练、推理

    vla openpi自主抓零食

2.2.2 openpi自主做智能分拣,即便被分拣物品被换了位置,也能分拣

  1. 昨天通过openpi抓零食,今天又训了一个任务,openpi自主做智能分拣
  2. 即便被分拣物体被交换了位置,也能成功分拣,毕竟vla还是比单纯il更智能些(视频在客户伙伴见证下拍摄,2倍速)

    vla openpi实现自主智能分拣​

// 待更

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐