1321 字
7 分钟
模型训练环境配置问题

LeRobot PI0 模型训练环境配置问题与解决方案#

环境信息#

  • 系统: Linux
  • Python: 3.11
  • LeRobot 版本: 0.4.3
  • huggingface_hub 版本: 0.35.3
  • 训练模型: PI0 (Physical Intelligence pi0_base)
  • 目标: 在 HuggingFace 离线模式 (HF_HUB_OFFLINE=1) 下完成微调训练

问题一:HuggingFace 模型缓存目录结构不正确#

问题描述#

用户通过 cp -r 命令将预训练模型文件直接拷贝到 HuggingFace Hub 缓存目录:

Terminal window
cp -r "/model/pi0"/* ~/.cache/huggingface/hub/models--lerobot--pi0_base/
cp -r "/model/paligemma"/* ~/.cache/huggingface/hub/models--google--paligemma-3b-pt-224/
cp -r "/model/fast"/* ~/.cache/huggingface/hub/models--physical-intelligence--fast/

这种方式只是把文件平铺放进了缓存目录,但 HuggingFace Hub 的缓存系统要求特定的目录结构。导致 huggingface_hub.scan_cache_dir() 扫描到 0个缓存仓库,离线模式下完全无法使用。

错误表现#

执行 snapshot_download('lerobot/pi0_base') 时报错:

LocalEntryNotFoundError: Cannot find an appropriate cached snapshot folder for the
specified revision on the local disk and outgoing traffic has been disabled.

根本原因#

HuggingFace Hub 缓存格式要求以下结构:

~/.cache/huggingface/hub/models--lerobot--pi0_base/
├── blobs/ ← 存放实际文件内容(以SHA256哈希命名)
│ ├── cd7cb479bb...config.json的内容
│ ├── 8229fd9a7c...model.safetensors的内容
│ └── ...
├── refs/
│ └── main ← 内容为 commit hash(如 "00000000")
└── snapshots/
└── <commit_hash>/ ← 目录名必须与 refs/main 中的值一致
├── config.json ← 符号链接 → ../../blobs/<sha256>
├── model.safetensors ← 符号链接 → ../../blobs/<sha256>
└── ...

关键点:

  1. blobs/ 目录存放文件的实际内容,文件名为内容的 SHA256 哈希值
  2. refs/main 文件内容是一个 commit hash(可以是自定义字符串如 “00000000”)
  3. snapshots/<commit_hash>/ 目录下的文件是符号链接,指向 blobs/ 中对应的文件
  4. snapshots/ 的目录名必须与 refs/main 中的 commit hash 完全一致

解决方法#

使用 Python 脚本为每个模型仓库重建正确的缓存结构:

import os, hashlib, shutil
def setup_hf_cache(model_dir, repo_name, snapshot_id="00000000"):
cache_dir = os.path.expanduser(f"~/.cache/huggingface/hub/{repo_name}")
blobs_dir = os.path.join(cache_dir, "blobs")
refs_dir = os.path.join(cache_dir, "refs")
snap_dir = os.path.join(cache_dir, "snapshots", snapshot_id)
os.makedirs(blobs_dir, exist_ok=True)
os.makedirs(refs_dir, exist_ok=True)
os.makedirs(snap_dir, exist_ok=True)
with open(os.path.join(refs_dir, "main"), "w") as f:
f.write(snapshot_id)
for fname in os.listdir(model_dir):
src_path = os.path.join(model_dir, fname)
if not os.path.isfile(src_path):
continue
sha = hashlib.sha256()
with open(src_path, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha.update(chunk)
blob_hash = sha.hexdigest()
blob_path = os.path.join(blobs_dir, blob_hash)
if not os.path.exists(blob_path):
shutil.copy2(src_path, blob_path)
snap_file = os.path.join(snap_dir, fname)
rel = os.path.relpath(blob_path, snap_dir)
if os.path.exists(snap_file) or os.path.islink(snap_file):
os.remove(snap_file)
os.symlink(rel, snap_file)
# 对三个模型分别执行
setup_hf_cache("/model/pi0", "models--lerobot--pi0_base")
setup_hf_cache("/model/paligemma/paligemma-3b-pt-224", "models--google--paligemma-3b-pt-224")
setup_hf_cache("/model/fast/fast", "models--physical-intelligence--fast")

验证#

Terminal window
python3 -c "
from huggingface_hub import snapshot_download
path = snapshot_download('lerobot/pi0_base')
print('OK:', path)
"
# 输出: OK: /root/.cache/huggingface/hub/models--lerobot--pi0_base/snapshots/00000000

问题二:Processor Step 注册表缺失#

问题描述#

PI0 模型的预处理器和后处理器配置文件(policy_preprocessor.json 和 policy_postprocessor.json)中引用了两个在当前版本 lerobot (0.4.3) 中未注册的 processor step。

错误表现#

训练启动时在 “Creating policy” 阶段报错:

KeyError: "Processor step 'relative_actions_processor' not found in registry.
Available steps: ['to_batch_processor_action', 'to_batch_processor_observation',
'to_batch_processor_complementary_data', 'to_batch_processor', ...]"

根本原因#

配置文件缺失的 Step配置状态说明
policy_preprocessor.jsonrelative_actions_processor"enabled": false预处理器中引用了此 step,但 registry 中未注册
policy_postprocessor.jsonabsolute_actions_processor"enabled": false后处理器中引用了此 step,但 registry 中未注册

这两个 step 在配置中虽然 enabled 设为 false(即不会实际执行),但 lerobot 的 pipeline 加载机制会在初始化时尝试从 registry 中查找并实例化所有配置的 step,不管其是否启用。因此即使 enabled: false,找不到也会报错。

解决方法#

从两个配置文件中移除这两个不支持的 step。由于它们本来就是禁用状态,移除不影响任何功能。

policy_preprocessor.json — 移除 relative_actions_processor:

// 修改前的 steps 列表:
{
"registry_name": "relative_actions_processor",
"config": {
"enabled": false,
"exclude_joints": ["gripper"],
"action_names": null
}
}
// → 直接从 steps 数组中删除此条目

policy_postprocessor.json — 移除 absolute_actions_processor:

// 修改前的 steps 列表:
{
"registry_name": "absolute_actions_processor",
"config": {
"enabled": false
}
}
// → 直接从 steps 数组中删除此条目

验证#

修改后训练命令成功通过 “Creating policy” 阶段,模型权重加载成功。


LeRobot PI0 模型加载链路分析#

理解整个加载链路有助于快速定位问题:

lerobot-train 命令
↓
lerobot_train.py:233 Creating policy
↓
factory.py:491-492 policy_cls.from_pretrained(pretrained_name_or_path="lerobot/pi0_base")
↓
pretrained.py:96-106 PreTrainedConfig.from_pretrained("lerobot/pi0_base")
│ → 加载 config.json 等配置文件(走 HF Hub)
↓
pretrained.py:109-112 os.path.isdir("lerobot/pi0_base")?
│ ├─ YES → 直接加载本地 model.safetensors
│ └─ NO → 调用 hf_hub_download() 从缓存获取 model.safetensors
↓
pretrained.py:126 加载 safetensors 权重到模型
↓
factory.py:267-284 make_pre_post_processors()
│ → 加载 policy_preprocessor.json
│ → 加载 policy_postprocessor.json
│ → 逐个实例化 registry 中的 processor step
↓
processor_pi0.py:135 TokenizerProcessorStep(tokenizer_name="google/paligemma-3b-pt-224")
│ → AutoTokenizer.from_pretrained()(走 HF Hub 缓存)
↓
训练开始

关键点:

  • PI0 模型权重(包括 PaliGemma 视觉编码器和语言模型的权重)都包含在 pi0_base/model.safetensors 中,不需要单独下载 PaliGemma 模型
  • PaliGemma 的模型架构在 modeling_pi0.py 中随机初始化,权重从 PI0 checkpoint 中加载
  • PaliGemma 的 tokenizer 通过 AutoTokenizer.from_pretrained("google/paligemma-3b-pt-224") 单独加载,因此 paligemma 的 HF 缓存也必须正确配置

修改的文件清单#

文件路径操作说明
~/.cache/huggingface/hub/models--lerobot--pi0_base/重建重建 blobs/refs/snapshots 结构
~/.cache/huggingface/hub/models--google--paligemma-3b-pt-224/重建重建 blobs/refs/snapshots 结构
~/.cache/huggingface/hub/models--physical-intelligence--fast/重建重建 blobs/refs/snapshots 结构
snapshots/.../policy_preprocessor.json编辑移除 relative_actions_processor
snapshots/.../policy_postprocessor.json编辑移除 absolute_actions_processor

训练命令参考#

Terminal window
export HF_HUB_OFFLINE=1
export TRANSFORMERS_OFFLINE=1
lerobot-train \
--dataset.repo_id=local/6-09-orange \
--dataset.root=/root/ws/local/6-09-orange \
--dataset.video_backend=pyav \
--policy.type=pi0 \
--policy.pretrained_path=lerobot/pi0_base \
--policy.dtype=bfloat16 \
--policy.gradient_checkpointing=false \
--policy.push_to_hub=false \
--output_dir=outputs/pi0_orange \
--batch_size=8 \
--steps=50000 \
--wandb.enable=false \
--log_freq=100 \
--save_freq=5000

注意事项#

  1. 如果将来重新拷贝模型文件(cp -r),需要重新执行问题一中的缓存修复脚本
  2. 如果升级 lerobot 版本,policy_preprocessor.json 和 policy_postprocessor.json 可能需要重新调整(检查新版本是否注册了 relative_actions_processor 和 absolute_actions_processor)
  3. /model/fast 目录包含 FAST tokenizer 相关文件,用于 PI0.5 等变体。基础 PI0 训练不直接依赖它,但建议也保持缓存正确
  4. 所有模型文件在 /model/ 目录下有原始副本,可随时重新部署
模型训练环境配置问题
https://fuwari.vercel.app/posts/模型训练环境配置问题/
作者
Jack min
发布于
2026-06-25
许可协议
CC BY-NC-SA 4.0