Thủ thuật
Strands Robots: Quy trình khép kín từ ghi dữ liệu, huấn luyện đến triển khai robot với Hugging Face
(giờ Việt Nam)
Tóm tắt AI
Strands Robots (Apache 2.0) từ AWS giúp hợp nhất quy trình ghi dữ liệu, huấn luyện chiến lược và triển khai phần cứng cho robot thông qua một vòng lặp thông minh duy nhất, đảm bảo tính nhất quán của định dạng dữ liệu LeRobot.
Bản dịch AI

Quay lại các bài viết
Hướng dẫn về vòng lặp dữ liệu streaming trong Strands Robots, một vòng lặp tác nhân (agent loop) ghi lại các thao tác trình diễn của robot, huấn luyện dựa trên đó bằng cách đọc trực tiếp từ Hub, và triển khai chính sách (policy) trở lại phần cứng, với tập dữ liệu giữ nguyên định dạng LeRobot trên đĩa trong suốt quá trình.
Bạn có một tác nhân đã có thể ghi lại một bản trình diễn và đẩy nó lên Hugging Face Hub. Bây giờ bạn muốn chạy vòng lặp đó liên tục: thu thập các tập dữ liệu (episodes) trong ngày, huấn luyện một chính sách trên tập dữ liệu đang tăng dần, triển khai nó, và kéo đợt dữ liệu tiếp theo về để cải thiện. Chạy vòng lặp đó một lần thì mọi thứ đều hoạt động. Chạy nó mỗi ngày và bạn bắt đầu phải trả phí cho việc truyền tải cùng một lượng byte lặp đi lặp lại. Các bản ghi bạn tải lên ngày càng lớn, mỗi lần huấn luyện lại sao chép toàn bộ tập dữ liệu vào GPU trước khi bắt đầu, và mỗi checkpoint mới được gửi đi trong khi đợt dữ liệu tiếp theo được tải về.
Bài viết đầu tiên trong loạt bài này đã giới thiệu Strands Robots, một SDK mã nguồn mở từ AWS (Apache 2.0) cung cấp các lớp trừu tượng cho robot, mô phỏng và ngăn xếp LeRobot dưới dạng AgentTools mà bạn kết hợp thành một tác nhân Strands duy nhất. Bài viết đó đã đề cập đến factory Robot, việc ghi lại bản trình diễn trong môi trường mô phỏng, chạy một chính sách và triển khai cùng mã tác nhân đó lên một thiết bị SO-101 vật lý. Factory đó phân giải tên dựa trên một danh mục các cánh tay robot, robot hình người, đế di động và bàn tay, vì vậy SO-100 được sử dụng xuyên suốt bài viết này chỉ là một trong nhiều hiện thân được hỗ trợ. Danh mục robot liệt kê mọi robot mà factory nhận diện được. Định dạng tập dữ liệu của LeRobot hiện đã được sử dụng bởi hơn 90.000 tập dữ liệu và mô hình trên Hub từ hơn 8.000 nhà xuất bản (LeRobot Project Pulse). Một bản ghi Strands Robots cũng là một trong số đó, vì vậy bất kỳ công cụ nào được xây dựng để đọc dữ liệu LeRobot đều có thể đọc nó mà không cần chuyển đổi. Nếu bạn mới làm quen với Strands Robots, hãy bắt đầu từ đó; bài viết này giả định rằng bạn đã thiết lập xong.
Bài viết đó đã theo dõi vòng lặp tác nhân theo một chiều, từ tập dữ liệu trên Hub đến robot vật lý. Bài viết này theo dõi dữ liệu theo chiều ngược lại, từ khung hình (frame) được ghi đầu tiên trở lại chính sách đã triển khai, thông qua Hugging Face Storage Buckets - một loại kho lưu trữ đối tượng có thể thay đổi, không phiên bản, dựa trên Xet được công bố vào tháng 3 năm 2026. Một bucket nằm cạnh các kho lưu trữ tập dữ liệu của bạn trong cùng không gian tên hf:// và sử dụng hf CLI mà bạn đã có, vì vậy nó trở thành lớp làm việc lưu trữ dữ liệu của bạn giữa ngày bạn ghi lại và ngày bạn huấn luyện.
Ai đó phải quyết định xem nên giữ lại những tập dữ liệu nào, khi nào bối cảnh đã thay đổi đủ để ghi lại, liệu đợt dữ liệu hôm nay đã đủ để huấn luyện hay chưa, và checkpoint nào sẽ thay thế checkpoint trên cánh tay robot. Mỗi quyết định đó xuất hiện hàng chục lần trong một chiến dịch thu thập, và mỗi quyết định đều cần xem xét những gì đã quay trở lại trước khi lệnh tiếp theo được đưa ra. Đó là công việc dành cho một tác nhân. Bài viết này hướng dẫn bạn qua vòng lặp dữ liệu bên trong một tác nhân duy nhất: ghi lại bản trình diễn vào một Storage Bucket, lưu trữ nó sao cho mỗi lần đồng bộ chỉ tải lên những byte đã thay đổi, huấn luyện bằng cách streaming tập dữ liệu trực tiếp từ Hub thay vì tải xuống, và triển khai checkpoint trở lại phần cứng chỉ với một thay đổi đối số từ khóa. Bản chạy thử đi kèm với bài viết này nằm tại examples/notebooks/05_streaming_data_loop.ipynb.
Những gì bạn sẽ xây dựng
Trong khi bài viết đầu tiên ghi lại một tập dữ liệu và đẩy nó lên Hub, tác nhân bạn xây dựng ở đây ghi lại một LeRobotDataset từ một câu lệnh ngôn ngữ tự nhiên, đồng bộ nó vào một Storage Bucket, và stream chính tập dữ liệu đó ngược lại từng khung hình, giải mã video camera ngay lập tức (on the fly) mà không cần bản sao cục bộ. Bạn đọc nó lại trong cùng quy trình đã ghi nó: cùng một Robot của Strands Robots đã ghi lại tập dữ liệu đó sẽ stream nó. Sau đó, checkpoint đã huấn luyện của bạn sẽ triển khai lên cùng Robot đó với một thay đổi đối số từ khóa, và các bản trình diễn mà nó ghi lại trên phần cứng sẽ quay trở lại cùng bucket đó.

Hình 1. Bốn giai đoạn chia sẻ chung một backend. Robot("so100") ghi lại một LeRobotDataset thông qua DatasetRecorder dùng chung; sync_dataset_to_bucket(...) đồng bộ nó vào một Storage Bucket; stream_dataset(...) đọc nó ngược lại qua Hub mà không cần tải xuống toàn bộ; và checkpoint đã huấn luyện triển khai lên cùng Robot đó với chế độ mode="real". Định dạng trên đĩa vẫn giữ nguyên như cách LeRobot đã ghi.
Vì một Robot vừa ghi lại tập dữ liệu vừa đọc lại nó, việc thu thập dữ liệu và huấn luyện trên đó là hai phương thức trên một đối tượng thông qua một backend. Tác nhân quyết định chạy một tập dữ liệu và gọi một công cụ; quá trình thực thi sau đó tiếp tục ở tần suất điều khiển của robot cho đến khi tập dữ liệu kết thúc, với chính sách đã huấn luyện tạo ra mọi hành động. Toàn bộ vòng lặp chỉ gói gọn trong vài dòng:
Những gì tiếp theo là những gì thực sự đang diễn ra bên trong vòng lặp đó, từng bước một.
Điều kiện tiên quyết
Tối thiểu (đường dẫn mô phỏng mặc định)
Chỉ vậy thôi. Mọi giai đoạn trong bài viết này đều chạy trên một chiếc laptop với ba thứ này. Những gì chạy là vòng lặp, không phải một chính sách hoạt động: đường dẫn mặc định sử dụng một chính sách giả (mock policy), ghi lại một tập dữ liệu hợp lệ nhưng không hữu ích.
Nâng cao (buckets, phần cứng, chính sách thực tế)
Bước 1 - Ghi lại bản trình diễn vào một bucket
Bạn ghi lại các tập dữ liệu mới trong ngày, mỗi tập là một chuỗi liên tục các khung hình camera và dữ liệu đo từ xa trạng thái-hành động của khớp. LeRobot ghi lại điều đó dưới dạng một tập hợp nhỏ các tệp lớn tăng dần khi bạn ghi. Đẩy chúng vào một kho lưu trữ tập dữ liệu có phiên bản và mỗi lần thêm vào (append) sẽ trở thành một commit, và mỗi bản sửa đổi đều được giữ lại. Việc thu thập dữ liệu cần điều ngược lại: một nơi để ghi byte và ghi đè lên chúng tại chỗ. Đó là Storage Bucket, nằm trong không gian làm việc Hugging Face của bạn và sử dụng các quyền mà bạn đã có. Không có vai trò quản lý danh tính và truy cập (IAM) nào để cấu hình, không có quy tắc chia sẻ tài nguyên chéo nguồn (CORS), và không có dịch vụ tải lên nào để duy trì.
Tác nhân của bạn ghi lại một LeRobotDataset ở cùng định dạng mà LeRobot ghi trên phần cứng. Ghi lại tập dữ liệu, sau đó đồng bộ tập dữ liệu đã hoàn thành vào một bucket. Câu lệnh yêu cầu chính sách giả, một phương án thay thế tạo ra các hành động khớp mà không cần mô hình đã huấn luyện, để bạn có thể chạy toàn bộ vòng lặp trước khi có checkpoint để chạy:
Quá trình đồng bộ ghi vào hf://buckets/{bucket}/{run_id}, trong đó run_id mặc định là tên thư mục tập dữ liệu. Việc đọc streaming ở Bước 3 cũng đặt tên cho lần chạy: hai phân đoạn đầu tiên của id là bucket, và mọi thứ sau đó là đường dẫn bên trong nó.
sync_dataset_to_bucket(root, bucket, run_id=...) xác thực tập dữ liệu và đồng bộ nó thông qua hf CLI, tách biệt khỏi vòng đời ghi. Khả năng tương tự cũng có trên DatasetRecorder.sync_to_bucket(bucket, run_id=...) nếu bạn điều khiển trực tiếp một trình ghi mở, và stop_recording(bucket=...) đồng bộ tại thời điểm bạn dừng một bản ghi đang hoạt động. Bucket là lớp làm việc bạn ghi vào trong ngày; đối với các artifact đã xuất bản và có phiên bản, bạn vẫn gọi push_to_hub. Cả hai đều giữ cùng một định dạng.
Tập dữ liệu đã hoàn chỉnh về cấu trúc, nhưng các hành động chỉ là phần giữ chỗ, vì vậy đó không phải là dữ liệu huấn luyện mà bạn mong muốn. Hãy thay thế bằng một chính sách thực tế với create_policy("<hf_repo>") để thực hiện việc gắp vật thể; câu lệnh, định dạng và việc đồng bộ bucket vẫn giữ nguyên.
Ghi lại trên phần cứng
Để ghi lại trên một SO-101 vật lý, CLI ghi của LeRobot xử lý việc khởi tạo leader-follower:
Tập dữ liệu nằm trên đĩa ở cùng định dạng với bản ghi mô phỏng, vì vậy cùng một lệnh đồng bộ sẽ đưa nó vào bucket: sync_dataset_to_bucket("./recordings", "my-org/robot-fave", run_id="run-021") (hoặc CLI hf sync./recordings hf://buckets/my-org/robot-fave/run-021 mà nó bao bọc). Việc thu thập dữ liệu chạy thêm vào một nơi, và các kho lưu trữ đã xuất bản của bạn chỉ nhận được các phiên bản mà bạn chọn xuất bản.
Bước 2 - Lưu trữ với tính năng khử trùng lặp ở cấp độ byte
Bây giờ tập dữ liệu đã nằm trong bucket, câu hỏi là lần đồng bộ tiếp theo sẽ tốn kém bao nhiêu. Hướng hai camera cố định vào một cánh tay robot đang dọn cùng một chiếc bàn trong tám giờ và phần lớn những gì bạn ghi lại là các pixel bạn đã có: cùng ánh sáng, cùng khung gầm, cùng nền, qua hàng ngàn tập dữ liệu. Trên một kho lưu trữ có phiên bản, tình hình còn tệ hơn, vì việc thay đổi một khung hình trong một shard video nhiều gigabyte sẽ tải lên lại toàn bộ tệp.
Các bucket được hỗ trợ bởi Xet, giúp khử trùng lặp các tệp tải lên của bạn ở cấp độ byte bằng cách sử dụng phân đoạn dựa trên nội dung (content-defined chunking). Các ranh giới phân đoạn tuân theo nội dung, vì vậy việc chèn một vài byte chỉ thay đổi phân đoạn mà nó nằm trong đó thay vì dịch chuyển mọi ranh giới sau nó. Theo các phép đo của chính Hugging Face (HF Storage), phân đoạn dựa trên nội dung giúp giảm dữ liệu truyền tải mỗi lần tải lên khoảng bốn lần trên Hub, và trên các gói Enterprise, việc thanh toán dựa trên dung lượng đã khử trùng lặp. Các điểm chuẩn bucket của họ cho thấy điều đó trông như thế nào trên một tệp duy nhất. Bắt đầu từ một tệp tải lên 500 MB, thay đổi 1% số byte và tải lên lại chỉ tốn 5,5 MB, thay đổi 5% tốn 27,5 MB, và thay đổi 10% tốn 55 MB. Nếu không có khử trùng lặp cấp độ phân đoạn, việc ghi đè một đối tượng có nghĩa là gửi lại tất cả các byte của nó, bất kể chúng có thay đổi hay không.
Mức độ tiết kiệm phụ thuộc vào bố cục tệp, và trình ghi Strands Robots sử dụng định dạng của LeRobot. Các tập dữ liệu đi vào các shard Parquet (data/chunk-000/file-000.parquet) và các shard MP4 theo từng camera (videos/observation.images.front/chunk-000/file-000.mp4), chỉ chuyển sang tệp mới khi tệp hiện tại đầy, với mặc định của LeRobot là 100 MB cho Parquet dữ liệu và 200 MB cho MP4 video. Vì vậy, một lần đồng bộ sau một ngày ghi sẽ tải lên các shard mới ở cuối cộng với một shard bị đầy một phần, thay vì toàn bộ tập dữ liệu. Đồng bộ lại cùng bucket đó vào ngày mai và Xet sẽ xử lý việc khử trùng lặp.

Hình 2. Một lần đồng bộ chỉ tải lên những gì đã thay đổi. Lần đồng bộ đầu tiên của một tập dữ liệu mới tải lên mọi phân đoạn; sau khi ghi thêm các tập dữ liệu, phân đoạn dựa trên nội dung của Xet có nghĩa là lần đồng bộ tiếp theo chỉ tải lên các phân đoạn mới và bỏ qua những phân đoạn đã được lưu trữ.
Bước 3 - Huấn luyện bằng cách streaming từ Hub
Để huấn luyện, bạn hướng GPU vào tập dữ liệu của mình. Tải xuống trước và các GPU đó sẽ nhàn rỗi cho đến khi hàng trăm gigabyte sao chép xong. Streaming trực tiếp từ Hub hoạt động ở đây nhờ bố cục shard từ Bước 2: một lô (batch) trở thành một vài lần đọc phạm vi byte trên các shard lớn thay vì hàng ngàn lần tìm nạp nhỏ. StreamingLeRobotDataset của LeRobot biến điều đó thành một torch iterable có thể cắm vào, và Strands Robots hiển thị nó thông qua stream_dataset:

Hình 3. Stream, đừng tải xuống. Đường dẫn tải xuống sao chép toàn bộ tập dữ liệu vào đĩa cục bộ trước, vì vậy GPU phải chờ; stream_dataset đọc các lô trực tiếp từ bucket mà không có gì trên đĩa cục bộ, vì vậy GPU huấn luyện từ lô đầu tiên.
Không có gì nằm trên đĩa cục bộ ngoại trừ thư mục meta/ nhỏ chứa lược đồ, số liệu thống kê và chỉ mục tập dữ liệu. Các khung hình camera được giải mã từ các shard MP4 từ xa khi bạn lặp; trạng thái và hành động đến từ các shard Parquet. Vòng lặp đó đọc từng khung hình một, phù hợp để kiểm tra một tập dữ liệu. Để huấn luyện, hãy chuyển trình đọc vào DataLoader và lặp qua các lô thay thế. Tập dữ liệu streaming tự xáo trộn bên trong thông qua một bộ đệm reservoir có giới hạn, vì vậy việc giải mã video được song song hóa trên các tiến trình worker, và bước huấn luyện chính là bước PyTorch thông thường:
Nếu bạn không muốn viết vòng lặp, trình huấn luyện của LeRobot đọc qua cùng một công cụ, vì vậy tập dữ liệu mà tác nhân của bạn thu thập sẽ huấn luyện mà không cần thêm một dòng mã mới nào. Nó nhận một bucket thông qua cùng đối số từ khóa mà trình đọc trong tiến trình sử dụng:
Các bucket chỉ dành cho streaming, vì vậy --dataset.repo_type=bucket yêu cầu --dataset.streaming=true và cấu hình sẽ từ chối kết hợp nếu không có điều kiện này. Hãy sử dụng stream_dataset khi bạn muốn vòng lặp trong tiến trình của riêng mình: xác thực một tập dữ liệu, phát lại trong mô phỏng, hoặc cung cấp cho một vòng lặp đánh giá tùy chỉnh. Đối với streaming chỉ cảm thụ bản thân (proprioceptive-only), drop_videos=True sẽ bỏ qua hoàn toàn việc giải mã video, điều này giúp nó hoạt động trên thiết bị biên không có torchcodec. Hướng dẫn về ghi và tập dữ liệu ghi lại đối số đó cùng với bản đồ delta_timestamps mà nó yêu cầu.
Tên nhà cung cấp được chia sẻ giữa việc chạy một chính sách và huấn luyện một chính sách. create_trainer("lerobot_local") trả về một Trainer hoạt động giống như create_policy, và một TrainSpec mô tả quá trình chạy; vòng lặp ghi-huấn luyện-triển khai sau đó kết thúc trong vài dòng:
Bài viết được AI dịch và tổng hợp tự động từ Hugging Face: Blog. Liên kết bài gốc ở phía trên. Dữ liệu đồng bộ qua API công khai được ghi nguồn tại AI HOT (canonical) ↗. AIHOT.vn luôn dẫn nguồn đầy đủ — nếu bạn thấy điểm cần chỉnh sửa, hãy gửi ý kiến tại trang phản hồi.