Робототехника
LeRobot открыл слой датасетов для новых форматов: первым стал Lance
24 сентября 2026 года в блоге Hugging Face вышла статья об интеграции LeRobot и LanceDB: LeRobotDataset читает датасеты, которые хранятся как таблицы Lance, напрямую, обучение идёт прямо из объектного хранилища без скачивания, а глобальный шаффл охватывает все кадры датасета.

Что именно открылось
Данные для обучения роботов раньше приходили в стольких форматах, сколько было лабораторий: у каждой группы свой формат записи, своя раскладка эпизодов, свой способ связывать видео с камер с положениями суставов и действиями. Повторно использовать чужой датасет означало сначала написать конвертер, а повторно использовать чужой код обучения — ещё один. LeRobot привёл эту экосистему к общему формату датасета и общему стеку обучения, а теперь открывает свой слой датасетов для поддержки новых форматов хранения: Lance стал первым из них.
На практике это значит, что LeRobotDataset читает датасеты Lance напрямую и сохраняет те же API и инструменты обучения: нужный загрузчик выбирается по исходному датасету, а код записи и обучения не меняется.
Что это меняет для команд
Обучаться можно там, где лежат данные. LanceDB читает случайные кадры прямо из Hugging Face Hub или любого популярного объектного хранилища, включая Hugging Face Storage Buckets, забирая только те байты, которые нужны текущему батчу: шага скачивания нет, а каждый батч может быть настоящим глобальным шаффлом по всему датасету.
Конвертация стоит примерно как копирование файлов: видео лежит блобами без перекодирования, поэтому элементы остаются бит-в-бит такими же, как в источнике. Новый признак — это объявление колонки и последующее заполнение задним числом, старые данные при этом не копируются. Просмотр эпизодов тоже не требует выгрузки: просмотрщик датасетов LeRobot отдаёт эпизоды в Foxglove прямо из таблицы.
Обучение прямо из Storage Buckets
Адресация внутри бакета — hf://buckets/<namespace>/<bucket>/<path>, управление — знакомым CLI hf. Запуск обучения указывает на бакет через --dataset.repo_type=bucket, а в альтернативном варианте путь задаётся прямо в --dataset.root. Датасеты, которые не объявляют storage_format: "lance", продолжают работать через стандартный читатель LeRobot, поэтому остальной конвейер не меняется.
Первый замер авторов — датасет lerobot/koch_pick_place_5_lego: 37 972 кадра с двух камер, политика SmolVLA, две H100, 1 500 шагов при одинаковых модели, seed и порядке выборки. Удалённая таблица LanceDB в бакете и локальная копия на NVMe дали одну и ту же устойчивую скорость 212 сэмплов в секунду и одинаковое время шага 0,30 секунды; по настенным часам получилось 503 секунды против 484, а функция потерь прошла путь 0,324 → 0,107 в обоих случаях. Авторы объясняют разрыв временем на подготовку локальной копии, а не скоростью чтения: GPU были заняты чтением из бакета ровно так же, как чтением локальной копии.
Таблица обучения — она же поисковый индекс
Parquet хорошо хранит колонки, но вторичных индексов у него нет: ни векторного, ни полнотекстового, поэтому кадры приходится искать сканом, а эмбеддинги, оценки и метрики — держать в отдельных системах с отдельными файлами-манифестами. В таблице Lance векторный индекс живёт на колонке эмбеддингов, полнотекстовый — на колонке инструкций, производные оценки — обычные колонки на тех же строках, а связь с кадрами даёт сама строка: вместо четырёх систем, которые нужно синхронизировать, остаётся одна.
Авторы приводят и числа этого слоя: 610 403 кадра были заэмбеддированы моделью SigLIP2 со скоростью 712 кадров в секунду на двух GPU, без локальной копии и без специального класса датасета. Добавление колонки с оценкой резкости движения jerk_score увеличило таблицу на 7% вместо копирования, а читатели, зафиксированные на старой версии таблицы, продолжили работать. Один запрос может соединить векторный поиск по эмбеддингу кадра с SQL-фильтром по другим колонкам той же таблицы — например, найти кадры с захватом предмета среди самых резких по движению.
Просмотр эпизода из такого хранилища тоже не требует выгрузки: эпизод 7 датасета DROID авторы открыли прямо из объектного хранилища и получили три потока камер вместе с собственным состоянием и траекториями действий; 54 секунды воспроизведения вытянули 132,7 МБ, то есть 0,036% от 369 ГБ датасета.
Крупный прогон: DROID на восьми H100
Основной эксперимент — обучение SmolVLA на всём датасете lerobot/droid_1.0.1: 27 630 375 кадров в 95 658 эпизодах и 369 ГБ видео, прочитанных напрямую из удалённого объектного хранилища с глобальным шаффлом по каждому кадру. Один и тот же запуск на 10 000 шагов выполнили дважды на восьми H100, меняя только --dataset.root: одна половина читала локальную копию, скачанную заранее (384 ГБ), вторая — таблицу LanceDB в объектном хранилище без скачивания.
Таблица LanceDB прошла задание за 1 час 27 минут 29 секунд против 2 часов 22 секунд у локальной копии на NVMe, то есть разница составила 33 минуты, или 1,38×. Устойчивая скорость — 495 сэмплов в секунду против 361, доля времени ожидания данных — 1,7% против 37,4%, а итоговая функция потерь совпала: 0,2380. Кривые потерь сходились до четырёх знаков после запятой, поэтому авторы объясняют разрыв именно простоем GPU в ожидании данных, а не качеством обучения. На 48 отложенных эпизодах улучшились все 48, а средняя абсолютная ошибка следующего действия упала с 0,3259 до 0,1004.
Отдельно авторы измерили сам читатель на шести публичных датасетах при восьми воркерах, батче 64 и окне шаффла в 0,05% датасета, но не меньше 5 000 кадров. На DROID чтение через LanceDB оказалось в 1,7 раза быстрее потокового читателя, на остальных датасетах — до 11,6 раза, а глобальный шаффл без скачивания — в 1,1–1,7 раза быстрее, чем чтение локальной копии. В статье есть и оговорка: потоковый читатель тестировался в PR #4342, то есть в версии, которая ещё находится в разработке, поэтому сравнение относится именно к протестированному состоянию.
Что показал полный проход по 27,6 млн строк
Авторы один раз просканировали все 27 630 375 строк и описали три находки. «Idle-фильтр» OpenPI, переписанный по опубликованному исходному коду, отбрасывает 11,66% DROID, причём исходник жёстко зашивает длину датасета после фильтра вместо того, чтобы её вычислять.
Стандартное разбиение 80/20 на обучение и валидацию протекает: простое деление помещает все 72 здания и всех 78 операторов сразу в оба набора. Обычный фильтр «гладкости» указывает в обратную сторону: на 95 603 эпизодах успешные эпизоды оказались резче неуспешных (AUROC 0,402), так что отбрасывание «дёрганых» эпизодов удаляло бы хорошие данные.
Отбор данных действительно помогает
Проверяли это на LIBERO — 1 693 успешных демонстраций в 40 задачах. Тридцать процентов эпизодов испортили намеренно, тремя реалистичными ошибками логирования, не трогая кадры камер: подменяли инструкцию на задачу из того же набора (оценка goal_dist), добавляли шум в действия — всплеск на 4% кадров и переворот гриппера на 2% (jerk_score), сдвигали действия на 0,6 секунды вперёд относительно наблюдений (act_lag). Оценки — это колонки таблицы эпизодов, объявленные и заполненные тем же способом, что и jerk_score; эпизод, не прошедший любую проверку, получает непустой quality_flag, а обучение читает остальное одним фильтром, который вернул 1 199 идентификаторов эпизодов для --dataset.episodes.
Четыре прогона SmolVLA по 40 000 шагов и 400 проверок в симуляторе показали: на чистых данных 86,0% успеха, на испорченных — 62,7%, после фильтрации — 77,0% при потолке 80,2%, который достигается идеальным удалением известных испорченных эпизодов. На наборе Goal результат восстановился с 48% до 85%. Проверки сработали с точностью 96% и полнотой 93%, а основная часть промахов — неверные метки в задачах, чьи финальные кадры выглядят почти одинаково.
Как это попробовать
Интеграция ставится как pip install "lerobot[lancedb]" "lerobot-lancedb>=0.3.1": отдельный пакет отвечает за нативный читатель и конвертер, команда lerobot-lance-convert переводит датасет LeRobot v3.0 в слой Lance, после чего его можно выложить в бакет через hf buckets sync и обучать с --dataset.repo_type=bucket. Датасеты без storage_format: "lance" продолжают идти через стандартный читатель — этот путь авторы оставили без изменений.
Документация интеграции описывает два слоя хранения, и оба являются подклассами LeRobotDataset: покадровые байты JPEG (LeRobotLanceDataset) и файлы mp4 блобами Lance (LeRobotLanceVideoDataset). Свой замер авторы документации сделали на lerobot/aloha_static_cups_open: бит-точный видеослой показал 2,44× по скорости чтения относительно исходного parquet+mp4. Готовые датасеты лежат в организации lance-format на Hugging Face, отобранный стол DROID доступен в живом демо, а скрипты бенчмарка, записанные порядки батчей и полный журнал измерений — в сопровождающем репозитории, на который ссылается статья.
Первоисточники
- Hugging Face Blog — «How to Train Your Robot: The LanceDB Edition» (24 сентября 2026)
- lerobot-lancedb — документация интеграции (слои Frames и Video, замеры)
- Hugging Face — документация Storage Buckets
- GitHub huggingface/lerobot — PR #4342 «feat(streaming dataset): improving streaming dataset consistency and robustness»
- Hugging Face — датасет lerobot/droid_1.0.1 (DROID)