Strands RobotsとLeRobotのストリーミングデータループをHugging Face Storage Bucketsで実現
TL;DR
Hugging Faceは、Strands Robots、LeRobotデータセットスタック、Hugging Face Storage Bucketsを接続するワークフローをリリースしました。これにより、ロボットのデモンストレーションを記録し、効率的に同期し、Hubから直接データをストリーミングして学習し、同じロボットにポリシーを再デプロイするという一連のループを実現できます。
ループの概要
このループは、1つの Robot() インスタンスを共有する4つのステージから構成されています:
- 記録 – ロボット(シミュレーションまたはハードウェア)がLeRobotDatasetを書き込みます。
- 保存 – データセットがHugging Face Storage Bucketに同期され、バイトレベルでの重複削除が行われます。
- 学習 – データセットがLeRobotの
StreamingLeRobotDatasetを使ってバケットからGPUに直接ストリーミングされ、完全なダウンロードの必要がありません。 - デプロイ – 学習済みのチェックポイントが同じ
Robot()に読み込まれ(今度はmode="real"で)、ロボットは次のデモンストレーションを記録し、ループを閉じます。
各ステージは1つの関数呼び出しまたは数行のコードで実行可能であり、ラップトップやGPUクラスタでもパイプライン全体を実行できます。
前提条件
最小限の(シミュレーション)設定
- LinuxまたはmacOS上のPython 3.12+(Apple Silicon対応)。
- Strands 互換のLLMプロバイダー(Amazon Bedrock、Anthropic、OpenAI、またはローカルのOllama)。
lerobotオプション付きのStrands Robots:
これにより、LeRobot ≥ 0.6.1、uv pip install -U "strands-robots[sim-mujoco,lerobot]>=0.5.1"datasets、av、torchcodecがインストールされます。
高度な(バケット、ハードウェア、リアルポリシー)設定
- 書き込み権限を持つHugging Faceアカウントと
hfCLI(pip install "huggingface-hub>=1.6.0,<2.0.0")。 - キャリブレーションファイルが
~/.cache/huggingface/lerobot/calibration/にある物理ロボット(例:SO‑101)。 - 学習用のNVIDIA GPU(または大規模データセット用のGPUクラスタ)。
lerobot[training]オプションでトレーナーをインストール(uv pip install "lerobot[training]")。
ステップ1 – バケットにデモンストレーションを記録
ロボットはネイティブなディスクフォーマット(状態/アクションはParquet、ビデオはMP4)でLeRobotDatasetを記録します。エピソード終了後、データセットはStorage Bucketに同期されます:
from strands import Agent
from strands_robots import Robot, sync_dataset_to_bucket
sim = Robot("so100") # default mode="sim"
agent = Agent(tools=[sim])
# プロンプトが世界の作成、記録、およびモックポリシーの実行を駆動します。
agent(
"so100ロボットで世界を作成し、赤いキューブと前面カメラを追加し、
記録を開始(repo_id='local/cube_pick', root='/tmp/cube_pick', fps=30,
overwrite=True, task='赤いキューブを掴む')、60ステップ分のモックポリシーを実行してから記録を停止。"
)
# 完了したデータセットをバケットに同期します。
sync_dataset_to_bucket("/tmp/cube_pick", "my-org/robot-fave")
# → {"status": "success", "bucket_uri": "hf://buckets/my-org/robot-fave/cube_pick"}
同期は hf://buckets/{bucket}/{run_id} に書き込まれます。run_id はデフォルトでデータセットフォルダ名になります。この呼び出しは、lerobot-record CLIで物理的なSO‑101で記録されたデータにも適用可能です。
ステップ2 – バイトレベルの重複削除で保存
Storage BucketsはXetでバックアップされており、コンテンツ定義型のチャンク分割とバイトレベルでの重複削除が行われます。LeRobotはデータを100 MBのParquetファイルと200 MBのMP4ファイルにシャーディングするため、1日の同期では新しく作成されたシャードと部分的に拡張されたシャードのみがアップロードされます。Hugging Faceが提示するベンチマークでは、単純な上書きと比較して転送バイト数が4倍削減されているとされています。
ステップ3 – Hubからストリーミングで学習
データセットをローカルディスクにコピーするのではなく、stream_dataset() はバイト範囲リクエストを使ってバケットから直接読み取ります:
reader = sim.stream_dataset(
"my-org/robot-fave/cube_pick",
repo_type="bucket",
shuffle=False,
max_num_shards=1,
buffer_size=1,
)
print(reader.num_episodes, reader.num_frames, reader.fps)
for frame in reader:
# 観測テンソルはリモートのMP4シャードからオンデマンドでデコードされます。
img = frame["observation.images.front"]
state = frame["observation.state"]
action = frame["action"]
break
ローカルにキャッシュされるのは小さな meta/ フォルダのみで、ビデオフレームは必要に応じてオンデマンドでデコードされます。学習の際は、このリーダーをPyTorchの DataLoader でラップします:
for batch in reader.dataloader(batch_size=64, num_workers=4):
loss, _ = policy(batch)
loss.backward()
LeRobotのCLIもストリーミングを直接サポートしています:
lerobot-train \
--policy.type=act \
--dataset.repo_id=my-org/robot-fave/cube_pick \
--dataset.repo_type=bucket \
--dataset.streaming=true \
--num_workers=4
1台のNVIDIA L4インスタンスが120フレームのエピソードで500回のオプティマイザステップを133秒で完了し、create_policy() でロード可能なチェックポイントを生成しました。
ステップ4 – ポリシーのデプロイとループへの戻り
新しい学習済みチェックポイントを物理ロボットにデプロイするには、Robot のモードを real に切り替えます:
robot = Robot(
"so100",
mode="real",
port="/dev/ttyACM0",
cameras={"front": {"type": "opencv", "index_or_path": "/dev/video0", "fps": 30}},
)
agent = Agent(tools=[robot])
agent("赤いキューブを掴む。")
ロボットは実行を同じLeRobotフォーマットで記録し、次の学習イテレーションのためにバケットに再度同期できます。
サンプルアプリケーション
完全なノートブックは examples/notebooks/05_streaming_data_loop.ipynb に用意されています。これはモックポリシーでシミュレーション上でループ全体を実行し、GPUやHugging Faceの認証情報は不要です。ローカルで試すには:
git clone https://github.com/strands-labs/robots.git
cd robots
uv pip install -U "strands-robots[sim-mujoco,lerobot]>=0.5.1"
jupyter notebook examples/notebooks/05_streaming_data_loop.ipynb
BUCKET = "my-org/robot-fave" と設定し、必要に応じて RUN_ID を指定してデータセットの保存先を制御できます。
セキュリティ上の考慮事項
- プロンプトインジェクション – エージェントはLLM生成のプロンプトを実行します。ツールの制限と信頼できる入力のみの供給を実施してください。
- 学習データの信頼境界 – データ収集(書き込み)と学習(読み取り)に分離した資格情報を使用し、エピソードを追跡できるように一意の
run_idを使用してください。 - バケットトークンのスコープ – ターゲット名前空間に限定されたトークンを使用し、収集データにはプライベートバケットを優先してください。
- バケットにはリビジョン履歴がない – 上書きは以前の実行を置き換えます。監査可能にするために、レビュー済みバージョンを通常のHubデータセットに公開してください。
- 信頼できるモデルの読み込み – カスタムポリシーには
trust_remote_code=Trueが必要です。信頼できる組織からのチェックポイントのみを読み込み、利用可能な場合はsafetensorsを優先してください。
クリーンアップ
ストレージ料金を回避するため、バケットの内容と一時ファイルを削除してください:
hf buckets rm my-org/robot-fave/cube_pick/ --recursive --dry-run # プレビュー
hf buckets rm my-org/robot-fave/cube_pick/ --recursive # 削除
hf buckets delete my-org/robot-fave # バケット全体を削除
rm -rf /tmp/cube_pick /tmp/cube_pick_ft /tmp/nb5_dataset /tmp/nb5_ft
push_to_hub() で作成されたバージョン付きリポジトリは変更されません。
次のステップ
- ロボットカタログ、シミュレーションバックエンド、マルチロボットメッシュについて、Strands Robots のドキュメントを確認してください。
TrainSpecのprovider文字列を変更することで、GR00T、Cosmos 3、SmolVLAなど、異なるポリシー提供者を使用できます。- フリートスケーリング:各ロボットに一意の
run_idを割り当て、同じバケットに同時に書き込ませます。 - Amazon S3などの外部ストレージと組み合わせる:LeRobotフォーマットはストレージに依存せず、バケットストリーミングによりHubネイティブなパスを追加するだけで済みます。
リソース
Strands Robots
- SDK および
Robot()ファクトリ:https://github.com/strands-labs/robots (Apache 2.0) - ドキュメント:https://strands-labs.github.io/robots/
- 記録ガイド:https://strands-labs.github.io/robots/recording/
- 本記事用のノートブック:https://github.com/strands-labs/robots/blob/main/examples/notebooks/05_streaming_data_loop.ipynb
- エージェントSDK:https://github.com/strands-agents/harness-sdk
LeRobot & Hub
- LeRobotリポジトリ:https://github.com/huggingface/lerobot
- Storage Bucketsドキュメント:https://huggingface.co/docs/hub/storage-buckets
- Xetの重複削除ブログ:https://huggingface.co/blog/from-files-to-chunks
- 例:ピックアンドプレースデータセット:https://huggingface.co/datasets/lerobot/svla_so101_pickplace
ポリシー
- SmolVLA:https://huggingface.co/lerobot/smolvla_base
- Pi0:https://huggingface.co/lerobot/pi0_base
- NVIDIA GR00T‑N1.7‑3B:https://huggingface.co/nvidia/GR00T-N1.7-3B
- NVIDIA Cosmos 3 Nano:https://huggingface.co/nvidia/Cosmos3-Nano
- SO‑100/101用のMolmoAct2:https://huggingface.co/allenai/MolmoAct2-SO100_101
背景
Sources
関連
- Dispatch
- Dispatch
- Dispatch
- Dispatch