# `@huggingface/lerobot`

Trình phân tích cho các bộ dữ liệu robot [LeRobot](https://github.com/huggingface/lerobot) được lưu trữ trên Hugging Face Hub.

Mọi thứ đều được đọc qua các yêu cầu HTTP có phạm vi, nên hoạt động không đổi cả trong trình duyệt lẫn Node, và không bao giờ tải toàn bộ bộ dữ liệu để trả lời một câu hỏi về nó.

## Tại sao

Bộ dữ liệu LeRobot tồn tại ở hai bố cục. Trong `v2.0` / `v2.1`, mỗi episode có tệp video và tệp parquet riêng, và chỉ mục episode là tệp JSON Lines. Trong `v3.0`, các episode được nối vào các tệp dùng chung và chỉ mục là parquet, do đó một episode là một khoảng byte và một khoảng thời gian bên trong một tệp lớn hơn.

Gói này che giấu sự khác biệt đó phía sau một hình dạng `LeRobotEpisode` duy nhất.

## Cài đặt

```bash
npm install @huggingface/lerobot
```

[hyparquet](https://github.com/hyparam/hyparquet) được đi kèm và được dùng để đọc chỉ mục tập `v3.0` và dữ liệu khung hình. [fzstd](https://github.com/101arrowz/fzstd) bổ sung ZSTD bên cạnh SNAPPY có sẵn trong hyparquet. Cả hai đều được nhập theo yêu cầu, nên các trình gọi chỉ cần `info()` hoặc danh sách tập `v2` sẽ không bao giờ nạp chúng.

## Cách sử dụng

```ts
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 none
```

`offset` đếm các vị trí trong chỉ mục, chỉ trùng khớp với chỉ mục tập khi bộ dữ liệu đánh số các tập của nó là 0, 1, 2, ... Một số bắt đầu từ 10 hoặc bỏ qua các tập đã bị xóa, vì vậy hãy dùng `episode(index)` để mở một tập cụ thể. Trên một bộ dữ liệu được đánh số 0, 1, 2, ..., chi phí bằng với `episodes({ offset: index, limit: 1 })`.

`videos[].fromSec` / `toSec` là các offset của tập phim bên trong `url`. Trên `v3.0`, nhiều tập phim chia sẻ chung một tệp, vì vậy hãy seek đến `fromSec` và dừng lại tại `toSec`; trên `v2.x`, mỗi tập phim có tệp riêng và khoảng này đơn giản bao trùm toàn bộ tệp đó.

`data` trỏ đến các hàng khung hình của tập đó, dành cho các trình gọi muốn tự vẽ biểu đồ `observation.state` hoặc `action`. `fromRow` là bao gồm và `toRow` là không bao gồm; cả hai đều là độ lệch hàng bên trong `data.url`, không phải chỉ mục xuyên suốt bộ dữ liệu. Đối với v3, khi một trang bắt đầu ở giữa tệp dữ liệu, việc liệt kê các tập cũng đọc phần chân parquet của tệp đó để tìm nơi bắt đầu. `data` vắng mặt khi tệp đó không thể đọc được hoặc không khớp với siêu dữ liệu của tập.

Giữ một `LeRobotDataset` trong khi duyệt qua các episode: giống như `info()`, nó ghi nhớ các tệp chỉ mục `v3.0` đã được duyệt, nên việc truy vấn trang sau hoặc `episode()` sẽ đi thẳng đến tệp chứa thông tin cần thiết.

### Cố định một bản sửa

Truyền commit sha bất cứ khi nào kết quả được lưu trữ hoặc cache ở đâu đó, để một lần push sau đó không thể thay đổi những gì bạn đã phân tích:

```ts
const dataset = new LeRobotDataset("lerobot/svla_so101_pickplace", {
	revision: "f641879e22172be7e8161d5e6c1503c2d2feb657",
});
```

### Bộ dữ liệu riêng tư và có kiểm soát

Truyền `fetch` của riêng bạn để thêm thông tin xác thực:

```ts
const dataset = new LeRobotDataset("my-org/private-dataset", {
	additionalFetchHeaders: { Authorization: `Bearer ${accessToken}` },
});
```

Trình duyệt trên `huggingface.co`, các cookie phiên là đủ:

```ts
const dataset = new LeRobotDataset(repoId, {
	fetch: (url, init) => fetch(url, { ...init, credentials: "same-origin" }),
});
```

## Phân tích mà không cần tải

`parseInfo` là thuần túy, dành cho các bên gọi đã có sẵn các byte:

```ts
import { parseInfo } from "@huggingface/lerobot";

const info = parseInfo(await readFile("meta/info.json", "utf8"));
```

Nó sẽ gây lỗi với bất kỳ thứ gì không phải là tệp thông tin có thể sử dụng, bao gồm một con trỏ LFS, một lần đọc bị cắt cụt, hoặc một `codebase_version` mà gói này không hỗ trợ.

