LeRobot documentation
Quy trình Gán nhãn
Quy trình Gán nhãn
lerobot-annotate theo dõi video của từng episode bằng một mô hình thị giác-ngôn ngữ (VLM) và ghi chú thích ngôn ngữ tự nhiên trở lại vào dataset của bạn. Nó điền trực tiếp hai cột ngôn ngữ từ trang Các cột ngôn ngữ và công thức — language_persistent và language_events — vào data/chunk-*/file-*.parquet.
Tóm lại: chỉ cần trỏ nó đến một tập dữ liệu LeRobot, và nó sẽ thêm các tác vụ con, kế hoạch, bộ nhớ, các ngắt lời, giọng nói và hỏi đáp trực quan mà một chính sách có thể được huấn luyện trên đó.
Cách các phần kết hợp với nhau
your dataset lerobot-annotate
(LeRobotDataset v3.0)
│
▼
┌─────────────────────────────────────────────────────┐
│ read episodes │
└──────────────────────────┬──────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌──────────┐ ┌───────────────┐ ┌──────────┐ one shared Qwen-VL
│ plan │ │ interjections │ │ vqa │ ◀── server (vLLM, OpenAI
└────┬─────┘ └───────┬───────┘ └────┬─────┘ API) drives all three
└────────────────────┼─────────────────────┘
│ each module stages raw JSONL
▼ into .annotate_staging/
┌─────────────────┐
│ validator │ ◀── checks everything
└────────┬────────┘
▼
┌─────────────────┐
│ writer │
└────────┬────────┘
▼
data/chunk-*/file-*.parquet
(+ meta/info.json tools)Ba module (plan, interjections, vqa) đều tương tác với một VLM dùng chung. Mỗi module lưu kết quả đầu ra ra đĩa, một trình xác thực kiểm tra chúng, và một trình ghi duy nhất ghi đè các shard của tập dữ liệu tại chỗ.
Những gì pipeline tạo ra
Mỗi module phát ra một vài kiểu chú thích (“styles”), được định tuyến đến một trong hai cột ngôn ngữ:
| Phong cách / nguyên tử | Cột | Module |
|---|---|---|
subtask (kiểu Pi0.7 “cách làm, không phải làm gì”) | language_persistent | plan |
plan (ban đầu + làm mới khi có sự can thiệp) | language_persistent | plan |
memory (nén kiểu MEM) | language_persistent | plan |
task_aug (các cách diễn đạt lại của tác vụ) | language_persistent | plan |
interjection | language_events | interjections |
speech tool-call atom (style=null, say) | language_events | interjections |
vqa (cặp user / assistant) | language_events | vqa |
Cách các tác vụ con được tạo ra
Module plan không yêu cầu VLM cung cấp các tác vụ con trong một lần duy nhất. Thay vào đó, nó sử dụng luồng mô tả → phân đoạn hai bước:
- Mô tả — VLM chỉ mô tả những gì nó thực sự nhìn thấy trong camera được chọn (không suy đoán về tác vụ).
- Segment — mô tả đó được đưa trở lại, và VLM chia episode thành các subtask nguyên tử liên tiếp.
Cả hai lượt xử lý đều xem tập dữ liệu (episode) dưới dạng bảng liên hệ có mốc thời gian — các khung hình được lấy mẫu với tần số frames_per_second (mặc định là 0,5 giây) và đóng gói thành các lưới JPEG, trong đó thời gian của từng khung hình được ghi cố định vào góc, giúp VLM trích dẫn chính xác thời điểm ranh giới. Cách này tiết kiệm token thị giác hơn nhiều so với việc dùng một hình ảnh cho mỗi khung hình, nên việc lấy mẫu có thể duy trì mật độ cao; các tập dữ liệu dài hơn max_frames_per_prompt sẽ được chia thành các cửa sổ với cùng mật độ và sau đó được gộp lại. Cả hai prompt cũng đều chứa định nghĩa ranh giới sự kiện mang tính nhân quả (một sự kiện mới bắt đầu khi một vật thể được cầm / được thả / di chuyển đến một vị trí mới / nắp thay đổi trạng thái / nội dung di chuyển) để làm rõ vị trí đặt các điểm cắt.
Tùy chọn, một lượt seeded-relabel thứ ba (--plan.subtask_seeded_relabel)
xem xét lại từng span với các contact sheet của đoạn trước/lần hiện tại/sau và
chỉnh sửa nhãn một cách tối thiểu, sử dụng nhãn đầu tiên làm tiên nghiệm — nó giữ
các ranh giới cố định và chỉ làm sắc nét hơn về mặt từ ngữ, với chi phí là một
gọi bổ sung cho mỗi subtask.
Các span kết quả sau đó được ghép lại thành một lớp phủ toàn tập không có khoảng trống, đảm bảo mỗi khung hình có đúng một subtask đang hoạt động. Xem Running on Hugging Face Jobs để biết các cài đặt cho môi trường sản xuất (một camera, contact sheet có dấu thời gian, tự động tạo subtask theo cửa sổ).
Công cụ
Writer không thêm cột tools vào parquet. Danh mục công cụ nằm trong meta/info.json["tools"] (xem Tools). Sau mỗi lần chạy, pipeline đảm bảo rằng schema say chuẩn nằm trong danh sách đó, đồng thời giữ lại các công cụ bạn đã khai báo trước đó.
Muốn thêm công cụ của riêng bạn? Chỉnh sửa trực tiếp meta/info.json["tools"] — pipeline sẽ giữ nguyên những gì đã có sẵn. Điều này làm cho công cụ hiển thị với chat template, giúp mô hình có thể học cách generate lời gọi. Lớp runtime thực sự executes một lời gọi đã được generate (giao thức Tool / TOOL_REGISTRY dưới src/lerobot/tools/) hiện chưa được triển khai — tài liệu Tools đánh dấu các phần đó là chưa được triển khai.
Chạy trên Hugging Face Jobs
Việc chú thích một bộ dữ liệu thực tế đòi hỏi GPU đủ lớn để phục vụ VLM, vì vậy lerobot-annotate có thể tự triển khai lên Hugging Face Jobs — giống như lerobot-train. Thêm --job.target=<flavor> vào chính xác lệnh mà bạn sẽ chạy cục bộ và nó sẽ chạy trên phần cứng đó thay thế:
hf auth login # once
uv run lerobot-annotate \
--repo_id=user/my_dataset \
--new_repo_id=user/my_dataset_annotated \
--push_to_hub=true \
--vlm.model_id=Qwen/Qwen3.6-27B \
--vlm.num_gpus=1 \
--vlm.serve_command="vllm serve Qwen/Qwen3.6-27B --tensor-parallel-size 1 \
--max-model-len 32768 --gpu-memory-utilization 0.8 \
--uvicorn-log-level warning --port {port}" \
--vlm.serve_ready_timeout_s=1800 \
--vlm.chat_template_kwargs='{"enable_thinking": false}' \
--job.target=h200Điều này gửi một tác vụ h200 đơn GPU mà:
- bắt đầu từ ảnh
vllm/vllm-openaivà cài đặtlerobotlên trên, - khởi động một máy chủ vLLM cho mỗi GPU và điều khiển nó qua API tương thích OpenAI,
- chạy các module
plan/interjections/vqatrên bộ dữ liệu, - với
--push_to_hub=true, tải kết quả lên--new_repo_id(hoặc trở lại--repo_idtại chỗ nếu bạn để trống tham số đó).
Lệnh này sẽ phát trực tiếp nhật ký của công việc; Ctrl-C sẽ ngắt kết nối mà không hủy bỏ nó. Liệt kê các loại phần cứng khả dụng cùng bảng giá của chúng bằng hf jobs hardware.
Qwen3.6 được phát hành với chế độ suy nghĩ (thinking) bật, điều này tiêu tốn ngân sách token mà bộ chú thích cần cho câu trả lời JSON của nó —
--vlm.chat_template_kwargs='{"enable_thinking": false}'sẽ tắt chế độ này. Nếu không có--push_to_hub=true, bộ dữ liệu đã được chú thích sẽ bị loại bỏ khi pod thoát.
Các tùy chọn công việc
| Cờ | Mặc định | Nó hoạt động như thế nào |
|---|---|---|
--job.target | local | Flavor của HF Jobs để chạy (ví dụ: h200, h200x4). Bỏ qua/local chạy tại đây. |
--job.image | vllm/vllm-openai:latest | Ảnh runtime cho pod. |
--job.timeout | 2h | Giới hạn thời gian thực. Hãy tăng lên cho các bộ dữ liệu lớn. |
--job.detach | false | Gửi và thoát thay vì phát trực tiếp nhật ký. |
--job.lerobot_ref | main | Tham chiếu Git của lerobot được cài đặt trên pod — trỏ đến một nhánh để kiểm tra các thay đổi. |
--job.tags | [] | Các thẻ bổ sung trên công việc và trên bất kỳ bộ dữ liệu nào mà nó đẩy lên (lerobot luôn được thêm vào). |
Với bộ dữ liệu lớn hơn, hãy mở rộng lên h200x4 và tăng --vlm.parallel_servers / --vlm.num_gpus cho phù hợp, đồng thời dành thêm dung lượng cho công việc, ví dụ bằng --job.timeout=8h.
Chạy từ xa cần --repo_id (pod sẽ kéo dataset từ Hub; --root chỉ định một thư mục chỉ có trên máy của bạn). Dataset chỉ tồn tại trong bộ nhớ đệm cục bộ sẽ được đẩy lên một repo riêng tư trước.
Các tùy chọn chính
Đây là các cờ bạn sẽ dùng thường xuyên nhất. Chạy lerobot-annotate --help để xem các tùy chọn khác; các giá trị mặc định được điều chỉnh cho các tập hợp thao tác ngắn.
Dataset vào / ra
| Cờ | Mặc định | Nó hoạt động như thế nào |
|---|---|---|
--repo_id | — | Bộ dữ liệu Hub cần chú thích (được tải xuống nếu --root không được đặt). |
--root | — | Thay vào đó, hãy chú thích một thư mục bộ dữ liệu cục bộ. |
--new_repo_id | — | Đẩy kết quả đến một kho lưu trữ mới (không thay đổi kho lưu trữ nguồn). |
--push_to_hub | false | Tải lên sau khi chú thích (vào --new_repo_id, nếu không thì quay lại --repo_id). |
--only_episodes | tất cả | Chỉ chú thích các chỉ mục tập này (tiện lợi cho một lần chạy thử). |
--seed | 1729 | Khởi tạo các RNG chọn thời điểm xen kẽ + các loại câu hỏi VQA. |
Các module nào được chạy
Mọi module đều được bật theo mặc định và có thể được bật/tắt độc lập (đặt thành false để bỏ qua, ví dụ để lặp lại từng module một):
| Cờ | Mặc định | Tắt |
|---|---|---|
--plan.enabled | true | subtasks + plan + memory + task_aug |
--interjections.enabled | true | các từ cảm thán + các đơn vị ngôn ngữ |
--vqa.enabled | true | các cặp VQA |
VLM ( --vlm.* )
| Cờ | Mặc định | Nó hoạt động như thế nào |
|---|---|---|
--vlm.model_id | Qwen/Qwen3.6-27B | Mô hình cần triển khai và prompt. |
--vlm.camera_key | đầu tiên images.* | Camera mà mỗi prompt được dựa trên. |
--vlm.serve_command | auto | Lệnh vllm serve … chính xác (cài đặt kích thước TP, bộ nhớ GPU, --max-model-len tại đây). |
--vlm.parallel_servers | 1 | Các máy chủ độc lập cho định tuyến vòng tròn (một máy chủ cho mỗi GPU). |
--vlm.num_gpus | 0 | Số GPU trên mỗi máy chủ (0 = một GPU mỗi máy). |
--vlm.client_concurrency | 16 | Các yêu cầu đang xử lý trên tất cả các máy chủ. |
--vlm.max_new_tokens | 512 | Giới hạn sinh mỗi lần gọi. |
--vlm.temperature | 0.2 | Nhiệt độ lấy mẫu. |
--vlm.reasoning_effort | null | Gợi ý ngân sách suy nghĩ (low/medium/high) được chuyển tiếp đến các máy chủ tương thích OpenAI. |
Các tác vụ con / kế hoạch / bộ nhớ ( --plan.* )
| Cờ | Mặc định | Nó hoạt động như thế nào |
|---|---|---|
--plan.frames_per_second | 2.0 | Tốc độ lấy mẫu khung cho các bảng liên hệ (2.0 = một khung mỗi 0,5 giây). |
--plan.max_frames_per_prompt | 60 | Ngân sách khung cho mỗi lần gọi VLM. Các episode có quá trình lấy mẫu vượt quá ngưỡng này sẽ được tự động chia cửa sổ ở cùng mật độ, sau đó được ghép lại. |
--plan.contact_sheet_columns | 5 | Số cột trên lưới contact-sheet (contact_sheet_frames_per_sheet ô, hàng thời gian theo thứ tự chính). |
--plan.plan_max_steps | 8 | Giới hạn trên của số lượng tác vụ con mỗi tập. |
--plan.subtask_describe_first | true | Chạy bước grounding describe→segment (chất lượng subtask tốt nhất; +1 call/episode). |
--plan.subtask_seeded_relabel | false | Đợt hai: dán nhãn lại từng nhiệm vụ con từ các bảng liên hệ trước/hiện tại/sau của nó, khởi tạo bằng nhãn đầu tiên (+1 cuộc gọi/nhiệm vụ con). |
--plan.subtask_relabel_frames | 5 | Các khung được lấy mẫu đều trên mỗi bảng phân đoạn trong bước dán nhãn lại (chỉ được sử dụng khi subtask_seeded_relabel=true). |
--plan.emit_plan | true | Xuất các dòng plan có đánh số (false = chỉ subtasks + bộ nhớ). |
--plan.emit_memory | true | Xuất các dòng memory (false = chỉ subtasks + plan); đối xứng với emit_plan. |
--plan.n_task_rephrasings | 10 | Số lượng diễn đạt lại task_aug cần xuất ra (0 để tắt). |
--plan.derive_task_from_video | if_short | Sử dụng tác vụ của bộ dữ liệu như hiện có (off), chỉ khi nó bị thiếu/ngắn (if_short), hoặc luôn suy ra lại từ video (always). |
Từ cảm thán + VQA
| Cờ | Mặc định | Nó hoạt động như thế nào |
|---|---|---|
--interjections.max_interjections_per_episode | 3 | Giới hạn số cặp xen ngang/lời thoại mỗi tập. |
--vqa.vqa_emission_hz | 1.0 | Tần suất các cặp VQA được phát ra. |
--vqa.restrict_to_default_camera | false | Chỉ dựa vào --vlm.camera_key cho VQA (nếu không, mọi camera). |
--vqa.coordinate_scale | 1000 | Lưới bbox/keypoint của VLM, lưu dưới dạng [0, 1] (none = px). |
--executor.episode_parallelism | 16 | Số tập được xử lý đồng thời trong mỗi giai đoạn. |
Đóng góp các module mới
Pipeline được thiết kế để mở rộng, và sự đóng góp luôn được chào đón —
một module hoàn toàn mới (ví dụ, vết tích quỹ đạo hoặc affordances), một mẫu
prompt mới, một luồng grounding thông minh hơn, hoặc các bản sửa lỗi chất lượng cho các module plan / interjections / vqa hiện có.
Mọi module đều nằm dưới src/lerobot/annotations/steerable_pipeline/modules/, chia sẻ client VLM và bộ nhớ đệm keyframe, ghi kết quả thô của nó vào cây staging, và được gắn vào executor như một phase riêng. Có ý tưởng? Hãy mở một issue hoặc PR trên kho.
Cách các công thức sử dụng kết quả đầu ra
Các chú thích được thiết kế để được đọc bởi các công thức (xem Các cột ngôn ngữ và công thức). Thông thường:
- Các nhánh low-level / high-level / memory-update đọc
subtask/plan/memorytừlanguage_persistent. - một nhánh phản hồi xen ngang đọc các sự kiện
interjectioncùng với nguyên tử giọng nói ghép cặp (được hợp nhất thành một lượt trợ lý duy nhất thông quatool_calls_from) và bản cập nhậtplantương ứng tại cùng một mốc thời gian. - Một nhánh VQA đọc các cặp
(vqa, user)và(vqa, assistant)từlanguage_events.
Vì sao trạng thái và sự kiện được tách riêng
Hai ý tưởng định hình thiết kế:
- Trạng thái bền vững so với các sự kiện chính xác. Các hàng trạng thái bền vững (
subtask,plan,memory) áp dụng cho toàn bộ tập và trả lời câu hỏi “điều gì đang đúng ngay bây giờ?”. Các hàng sự kiện (interjection,vqa, giọng nói) chỉ xuất hiện trên khung duy nhất có dấu thời gian khớp. Dấu thời gian được sao chép trực tiếp từ tệp parquet nguồn — không bao giờ được tính lại bằng số dấu phẩy động. - Một lượt VLM. Cả ba module đều dùng chung một client VLM (client tương thích OpenAI giao tiếp với máy chủ vLLM của job), nên bạn chỉ phải trả chi phí nạp một mô hình cho mỗi dataset, thay vì ba lần.
Chạy lại một module duy nhất
Mỗi module lưu output thô của nó vào <root>/.annotate_staging/episode_{N:06d}/<module>.jsonl. Điều này giúp việc lặp lại prompt trở nên rẻ hơn: chạy lại một module chỉ ghi đè lên JSONL của chính nó, sau đó writer sẽ tổng hợp lại file parquet cuối cùng. Tắt các module không cần bằng --plan.enabled=false (tương tự với --interjections.enabled / --vqa.enabled) để kiểm thử từng cái một.
Những gì trình xác thực kiểm tra
Trước khi writer chạy, StagingValidator xác nhận:
- mỗi hàng sự kiện khớp chính xác với một mốc thời gian khung hình thực tế;
- không có cặp lời nói / từ cảm nào bị bỏ lại;
planđược làm mới tại mỗi mốc thời gian ngắt lời;- Các dòng
memoryrơi vào ranh giới của các subtask (một cảnh báo, không phải lỗi); - mỗi
contentcủa trợ lý VQA là JSON hợp lệ ở một trong các dạng bbox / keypoint / count / attribute / spatial; - mỗi hàng sẽ được đưa vào cột được chọn bởi
column_for_style(style).
Bất kỳ lỗi nào cũng sẽ hủy tác vụ ghi. Truyền --skip_validation=true để ghi đè khi gỡ lỗi.
Nguồn gốc của các ý tưởng trong từng module
plan— các tác vụ con. Hi Robot (Shi 2025) cho mức độ chi tiết nguyên tử (“nhặt một lá xà lách”, “đặt bát vào hộp”); Pi0.7 (Physical Intelligence 2025) cho chi tiết “cách làm, không phải làm gì”.plan— bộ nhớ. MEM (Torne 2026): chỉ giữ lại thông tin liên quan tối thiểu — bảo toàn kết quả, loại bỏ các thuộc tính cụ thể.interjections. Phân loại kịch bản của Hi Robot: tác vụ tiêu cực, sửa lỗi theo ngữ cảnh, ràng buộc cụ thể, sở thích. Lời nói là một nguyên tử chỉ gọi công cụ (tool_calls=[{type:function, function:{name:"say", arguments:{text:...}}}]).vqa. ECoT (Zawalski 2024) cho các đặc trưng có cơ sở (bounding box[x_min, y_min, x_max, y_max]và keypoints, được lưu dưới dạng phân số [0, 1] của ảnh) và Steerable VLA Policies (Zhao 2025) cho việc grounding đa mức trừu tượng. Pi0.7 cũng grounding câu trả lời xuyên suốt các mức trừu tượng.
Khi cải thiện một module, hãy điều chỉnh prompt template của nó trong src/lerobot/annotations/steerable_pipeline/prompts/ thay vì viết lại từ đầu.
Chi phí ước tính
Mỗi tập, pipeline thực hiện khoảng plan_max_steps lần gọi plan, max_interjections_per_episode lần gọi interjection và vqa_emission_hz × episode_seconds lần gọi VQA. Với các giá trị mặc định (8
subtasks, 3 interjections, 1 Hz × 3 pairs) trên một tập 30 giây, điều đó tương đương
~50 lần gọi VLM.
Bộ nhớ lưu trữ vẫn nhỏ: language_persistent chỉ tối đa vài chục KB mỗi
episode (parquet mã hóa từ điển cho một mục duy nhất lặp lại qua các
khung hình), và language_events trống trên hầu hết các khung hình — kích thước của nó tỷ lệ
với số lượng sự kiện phát ra, chứ không phải num_frames × num_emissions.