Huggingface.js documentation
@huggingface/lerobot
@huggingface/lerobot
Парсер для наборов данных робототехники LeRobot, размещённых на Hugging Face Hub.
Все данные читаются через HTTP-запросы с диапазоном, поэтому код работает без изменений как в браузере, так и в Node, и при этом никогда не загружает весь датасет, чтобы ответить на вопрос о нём.
Почему
Наборы данных LeRobot существуют в двух форматах. В v2.0 / v2.1 у каждого эпизода есть собственный видеофайл и файл parquet, а индекс эпизодов — это файл JSON Lines. В v3.0 эпизоды объединяются в общие файлы, а индекс — это parquet, поэтому эпизод представляет собой диапазон байтов и диапазон времени внутри более крупного файла.
Этот пакет скрывает это различие за единой формой LeRobotEpisode.
Установка
npm install @huggingface/lerobot
hyparquet поставляется вместе с ним и используется для чтения индекса эпизодов v3.0 и данных кадров. fzstd добавляет ZSTD в дополнение к встроенному в hyparquet SNAPPY. Оба импортируются по требованию, поэтому вызывающие стороны, которым нужны только info() или список эпизодов v2, никогда не загружают их.
Использование
import { LeRobotDataset } from "@huggingface/lerobot";
const dataset = new LeRobotDataset("lerobot/svla_so101_pickplace");
const info = await dataset.info();
// {
// codebaseVersion: "v3.0",
// robotType: "so100_follower",
// fps: 30,
// totalEpisodes: 50,
// totalFrames: 11939,
// cameras: [{ key: "observation.images.up", width: 640, height: 480, codec: "av1" }, ...],
// joints: { "observation.state": ["shoulder_pan.pos", "shoulder_lift.pos", ...] },
// ...
// }
const episodes = await dataset.episodes({ limit: 10 });
// [
// {
// index: 0,
// length: 303,
// durationSec: 10.1,
// tasks: ["pink lego brick into the transparent box"],
// videos: [{ cameraKey: "observation.images.up", url: "https://...", fromSec: 0, toSec: 10.1 }, ...],
// data: { url: "https://.../data/chunk-000/file-000.parquet", fromRow: 0, toRow: 303 },
// },
// ...
// ]
const episode = await dataset.episode(42);
// The episode whose `index` is 42, or undefined when there is noneoffset считает позиции в индексе, которые совпадают с индексами эпизодов только в том случае, если датасет нумерует свои эпизоды как 0, 1, 2, … Некоторые датасеты начинают с 10 или пропускают удалённые эпизоды, поэтому для открытия конкретного эпизода используйте episode(index). Для датасета с нумерацией 0, 1, 2, … это стоит столько же, сколько episodes({ offset: index, limit: 1 }).
videos[].fromSec / toSec — это смещения эпизода внутри url. В v3.0 несколько эпизодов размещены в одном файле, поэтому нужно перейти к fromSec и остановиться на toSec; в v2.x у каждого эпизода свой файл, и диапазон просто охватывает его.
data указывает на строки кадров для данного эпизода, для вызывающих сторон, которые хотят самостоятельно построить график observation.state или action. fromRow включительно, а toRow исключительно;
оба являются смещениями строк внутри data.url, а не индексами по всему набору данных. Для v3, когда страница начинается
в середине файла данных, при перечислении эпизодов также читается футер parquet этого файла, чтобы определить,
с чего он начинается. data отсутствует, если этот файл не может быть прочитан или не соответствует метаданным эпизода.
Держите один LeRobotDataset при листании эпизодов: как и info(), он запоминает файлы индекса v3.0, которые уже обработал, поэтому последующее обращение к странице или episode() сразу находит нужный файл.
Фиксация ревизии
Передавайте commit sha каждый раз, когда результат сохраняется или кэшируется где-либо, чтобы последующий push не мог изменить то, что вы проанализировали:
const dataset = new LeRobotDataset("lerobot/svla_so101_pickplace", {
revision: "f641879e22172be7e8161d5e6c1503c2d2feb657",
});Частные и закрытые наборы данных
Передайте собственный fetch, чтобы добавить учётные данные:
const dataset = new LeRobotDataset("my-org/private-dataset", {
additionalFetchHeaders: { Authorization: `Bearer ${accessToken}` },
});В браузере на huggingface.co достаточно сессионных cookie:
const dataset = new LeRobotDataset(repoId, {
fetch: (url, init) => fetch(url, { ...init, credentials: "same-origin" }),
});Разбор без загрузки
parseInfo является чистой функцией для вызывающих сторон, у которых уже есть байты:
import { parseInfo } from "@huggingface/lerobot";
const info = parseInfo(await readFile("meta/info.json", "utf8"));Он вызывает исключение для любого файла, который не является пригодным для использования файлом информации, включая указатель LFS, усечённое чтение или codebase_version, не поддерживаемый этим пакетом.