本文將逐步介紹 Strands Robots 中的串流資料循環,這是一個代理迴圈,能錄製機器人示範、直接從 Hub 讀取資料進行訓練,並將策略部署回硬體,全程使用相同的 LeRobot 磁碟資料集格式。

假設您已經有一個能錄製示範並推送到 Hugging Face Hub 的代理。現在您希望持續運行這個循環:全天候收集情境,在不斷增長的資料集上訓練策略,部署它,然後拉回下一批資料以改進模型。

運行一次這個循環,每個環節都能正常運作。但如果每天運行,您將會重複支付相同的位元組傳輸費用。您上傳的錄影會持續增加,每次訓練運行前都會將整個資料集複製到 GPU,而且每個新的檢查點都會在下一批錄影傳回時被傳送出去。

本系列的第一篇文章介紹了 Strands Robots,這是一個來自 AWS 的開源 SDK (Apache 2.0),它將機器人抽象、模擬和 LeRobot 堆疊作為 AgentTools 暴露出來,您可以將其組合成單一的 Strands 代理。它涵蓋了 Robot() 工廠、在模擬中錄製示範、運行策略,以及將相同的代理程式碼部署到實體 SO-101 機器人。

該工廠會根據手臂、人形機器人、移動底座和機械手的註冊表解析名稱,因此本文中使用的 SO-100 只是眾多支援的實體之一。機器人目錄列出了該工廠所知的所有機器人。LeRobot 的資料集格式已被 Hub 上超過 8,000 家發布商的 90,000 多個資料集和模型使用 (LeRobot Project Pulse)。

Strands Robots 的錄影也是其中之一,因此任何為讀取 LeRobot 資料而建構的工具都可以無需轉換地讀取它。如果您是 Strands Robots 的新手,請從那裡開始;本文假設您已完成該設定。

前一篇文章是從 Hub 資料集到實體機器人,單向追蹤代理迴圈。本文則反向追蹤資料,從第一個錄製的影格回到已部署的策略,透過 Hugging Face Storage Buckets 實現,這是一種在 2026 年 3 月發布的可變動、非版本化、由 Xet 支援的物件儲存庫類型。

儲存桶與您的資料集儲存庫位於相同的 hf:// 命名空間中,並使用您已有的 hf CLI,因此它成為您從錄製資料到訓練資料之間的工作層。

總有人需要決定保留哪些情境、場景何時偏離到需要重新錄製、今天的批次是否足以進行訓練,以及哪個檢查點可以取代機械手臂上的現有檢查點。在一次收集活動中,這些決策會出現數十次,而且每次決策都需要在發出下一個指令之前查看返回的結果。這就是代理的工作。

本文將引導您了解單一代理內部的資料循環:將示範錄製到 Storage Bucket 中,儲存時每次同步只上傳變更的位元組,直接從 Hub 串流資料集進行訓練而無需下載,並透過一個關鍵字參數的變更將檢查點部署回硬體。本文的可執行配套程式碼位於 examples/notebooks/05_streaming_data_loop.ipynb。

您將建構的內容

第一篇文章是錄製資料集並推送到 Hub,而您在此處建構的代理則會從自然語言提示中錄製 LeRobotDataset,將其同步到 Storage Bucket,然後逐幀串流回相同的資料集,即時解碼攝影機影片,無需本地副本。

您在寫入它的相同過程中讀取它:錄製資料集的相同 Strands Robots Robot() 會串流它。您訓練好的檢查點隨後會透過一個關鍵字參數的變更部署到相同的 Robot(),並且它在硬體上錄製的示範會返回到相同的儲存桶。

圖 1. 四個階段共享一個後端。Robot("so100") 透過共享的 DatasetRecorder 錄製 LeRobotDataset;sync_dataset_to_bucket(...) 將其同步到 Storage Bucket;stream_dataset(...) 透過 Hub 讀取它,無需完整下載;訓練好的檢查點則以 mode="real" 部署到相同的 Robot。磁碟上的格式與 LeRobot 寫入的完全相同。

因為一個 Robot() 既能錄製資料集又能讀取資料集,所以資料收集和訓練是同一個物件在同一個後端上的兩種方法。代理決定運行一個情境並調用一個工具;然後部署會以機器人的控制頻率進行,直到情境結束,由訓練好的策略產生每個動作。

整個循環,只需幾行程式碼:

```python

from strands import Agent

from strands_robots import Robot

sim = Robot("so100") # mode="sim" (default - safe, no hardware)

agent = Agent(tools=[sim])

Record a demonstration and sync it to a bucket.

agent("Record a pick-the-cube demo and sync it to my-org/robot-fave.")

Stream it back from the bucket to train, without downloading it first.

for batch in sim.stream_dataset("my-org/robot-fave/cube_pick", repo_type="bucket").dataloader(batch_size=64):

...

```

接下來將逐步說明該循環中實際發生的情況。

先決條件

最低要求 (預設模擬路徑)

Python 3.12+,適用於 Linux 或 macOS (支援 Apple Silicon 的 MuJoCo 後端)。

用於代理推理的 Strands 相容模型提供者。例如:帶有 AWS 憑證的 Amazon Bedrock、Anthropic API、OpenAI 或本地運行的 Ollama。

帶有資料集附加功能的 Strands Robots:uv pip install -U "strands-robots[sim-mujoco,lerobot]>=0.5.1"。lerobot 附加功能會引入 LeRobot (>=0.6.1)、datasets、av 和 torchcodec,因此錄製和影片解碼無需額外設定即可運作。請參閱安裝指南。

就這樣。本文中的每個階段都可以在具備這三項的筆記型電腦上運行。運行的是循環,而不是一個可用的策略:預設路徑使用一個模擬策略,它會錄製一個有效的資料集,但不是一個有用的資料集。

進階要求 (儲存桶、硬體、真實策略)

一個 Hugging Face 帳戶和具有寫入權限的 token,以及用於建立儲存桶和同步資料集的 hf CLI:pip install -U "huggingface-hub>=1.6.0,<2.0.0",然後 hf auth login。

對於硬體路徑:一對 SO-101 追隨者和領導者,或任何其他 LeRobot 支援的機器人,其校準檔案位於 ~/.cache/huggingface/lerobot/calibration/ 下。

對於本地視覺語言動作 (VLA) 推理:需要 NVIDIA GPU。對於大規模訓練,則需要從 Hub 讀取的 GPU 叢集。

若要運行訓練步驟:uv pip install "lerobot[training]"。錄製和串流不需要它。如果您跳過它,trainer.train() 將返回錯誤結果而不是檢查點。故障排除指南會說明該錯誤以及修復它的安裝方式。

步驟 1 - 將示範錄製到儲存桶中

您全天候錄製新的情境,每個情境都是攝影機畫面和關節狀態-動作遙測資料的連續運行。LeRobot 將其寫入為一組少量的大檔案,這些檔案會隨著您的錄製而增長。

將它們推送到版本化資料集儲存庫中,每次追加都會成為一個提交,並且每個修訂版本都會被保留。資料收集則需要相反的功能:一個可以寫入位元組並原地覆蓋它們的地方。這就是 Storage Bucket,它位於您的 Hugging Face 工作區內,並使用您已有的權限。

無需配置身份和存取管理 (IAM) 角色、無需跨域資源共享 (CORS) 規則,也無需維護上傳服務。您的代理會以 LeRobot 在硬體上寫入的相同格式錄製 LeRobotDataset。錄製情境後,將完成的資料集同步到儲存桶中。

提示詞要求使用模擬策略,這是一個無需訓練模型即可產生關節動作的替代品,因此您可以在擁有可運行檢查點之前運行整個循環:

```python

from strands import Agent

from strands_robots import Robot, sync_dataset_to_bucket

sim = Robot("so100") # mode="sim" by default

agent = Agent(tools=[sim])

One prompt drives scene setup, cameras, policy, and recording.

agent(

"Create a world with the so100 robot, add a red cube and a front camera, "

"start recording (repo_id='local/cube_pick', root='/tmp/cube_pick', fps=30, "

"overwrite=True, task='pick up the red cube'), run the mock policy for "

"60 steps, then stop recording."

)

Sync the finished on-disk dataset into the bucket (no live recording session needed).

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 預設為資料集目錄名稱。步驟 3 中的串流讀取也會命名運行:ID 的前兩個部分是儲存桶,之後的所有內容都是其內部的路徑。

sync_dataset_to_bucket(root, bucket, run_id=...) 會驗證資料集並透過 hf CLI 同步它,與錄製生命週期解耦。如果您直接驅動一個開放的錄製器,DatasetRecorder.sync_to_bucket(bucket, run_id=...) 也提供相同的功能,而 stop_recording(bucket=...) 則會在您停止活動錄製時進行同步。

儲存桶是您全天寫入的工作層;對於版本化、已發布的成品,您仍然需要呼叫 push_to_hub()。兩者都採用相同的格式。該情境在結構上是完整的,但動作只是佔位符,因此它不是您想要的訓練資料。您可以透過 create_policy("<hf_repo>") 替換為真實策略以實現實際抓取;提示詞、格式和儲存桶同步保持不變。

在硬體上錄製

若要在實體 SO-101 上錄製,LeRobot 的 record CLI 會處理領導者-追隨者的啟動:

```bash

lerobot-record \

--robot.type=so101_follower --robot.id=my_follower \

--teleop.type=so101_leader --teleop.id=my_leader \

--dataset.repo_id=my_user/cube_picking \

--dataset.single_task='Pick up the red cube'

```

資料集會以與模擬錄製相同的格式儲存在磁碟上,因此相同的同步呼叫會將其帶到儲存桶:sync_dataset_to_bucket("./recordings", "my-org/robot-fave", run_id="run-021") (或其包裝的 hf sync ./recordings hf://buckets/my-org/robot-fave/run-021 CLI)。收集運行會追加到一個地方,而您發布的儲存庫只會獲得您選擇發布的版本。

步驟 2 - 使用位元組級重複資料刪除進行儲存

現在資料集已在儲存桶中,問題是下一次同步會花費您多少。將兩台固定攝影機對準機械手臂,讓它連續八小時清理同一張桌子,您錄製的大部分內容都是您已經擁有的像素:相同的照明、相同的底盤、相同的背景,橫跨數千個情境。

在版本化儲存庫中情況更糟,因為更改多 GB 影片分片中的一個影格會重新上傳整個檔案。儲存桶由 Xet 提供支援,它使用內容定義分塊 (content-defined chunking) 在位元組層級對您的上傳進行重複資料刪除。

分塊邊界會跟隨內容,因此插入幾個位元組只會改變它所在的塊,而不是移動其後的所有邊界。根據 Hugging Face 自己的測量 (HF Storage),內容定義分塊在整個 Hub 上每次上傳的資料傳輸量減少了約四倍,並且在企業方案中,計費是基於重複資料刪除後的佔用空間。

他們的儲存桶基準測試顯示了單一檔案的情況。從 500 MB 的上傳開始,更改 1% 的位元組並重新上傳會移動 5.5 MB,更改 5% 會移動 27.5 MB,更改 10% 會移動 55 MB。如果沒有塊級重複資料刪除,覆寫一個物件意味著再次發送其所有位元組,無論它們是否已更改。

節省多少取決於檔案佈局,而 Strands Robots 錄製器使用 LeRobot 的佈局。情境會進入 Parquet 分片 (data/chunk-000/file-000.parquet) 和每個攝影機的