
Training one policy on several tasks: how the LeRobot task field works, what task balance does to sampling, and the cases where a single-task ACT still beats a multi-task VLA.
What you need to know
- •A LeRobot dataset already carries a task string per episode: prompts in meta/tasks.parquet, a task_index on every data row.
- •Not every policy reads it. On lerobot main (23 August 2026) ACT has no tokenizer and no task field, so it cannot tell your tasks apart.
- •RT-1 measured the trade: cutting 25 percent of the tasks while keeping 97 percent of the data cost as much generalization as discarding 49 percent of the data.
- •SmolVLA on an SO-100 averaged 78.3 percent over three tasks trained multi-task, against 48.3 for ACT trained per task.
- •Balance is frames, not episodes. EpisodeAwareSampler shuffles one permutation over all frames, so longer episodes get more gradient updates.
- •lerobot-train still refuses a list of repo ids. Merge first with lerobot-edit-dataset.
- •Single-task still wins for one fast reactive motion: ACT runs at 20 ms per action step against SmolVLA's 245 ms.
Almost every LeRobot dataset you record is already multi-task in the format sense: it has a task field, a task index, and the trainer reads both. Whether that becomes one policy that does several things, or one policy that does the average of several things badly, comes down to which task string you write, how many frames each task contributes, and whether your model can read language at all.
This page covers all three: the file layout, the CLI flags on lerobot main and Isaac-GR00T main as of 23 August 2026, and the published numbers from BC-Z, RT-1 and SmolVLA. It also says where multi-task training makes things worse, and where ACT on one task still beats a vision-language-action model trained on five.
What a multi-task LeRobot dataset actually is
Here is the on-disk shape you are working with. Everything about tasks lives in two places: one metadata file and one column.
my_dataset/
data/
chunk-000/
file-000.parquet # one row per frame, includes task_index
file-001.parquet
meta/
info.json # fps, features, total_tasks
stats.json
tasks.parquet # the task strings, indexed by task_index
episodes/
chunk-000/file-000.parquet # per-episode metadata: tasks, length, ...
videos/
observation.images.front/chunk-000/file-000.mp4
observation.images.wrist/chunk-000/file-000.mp4The lerobot source describes that metadata in one sentence: tasks contains the prompts for each task of the dataset, which can be used for task-conditioned training. Nothing forces one task per dataset. 120 episodes over four task strings is a legal v3.0 dataset.
GR00T reads a v2 flavour of the format: meta/tasks.jsonl instead of a parquet, plus a meta/modality.json. Isaac-GR00T ships scripts/lerobot_conversion/convert_v3_to_v2.py for the conversion. On AY-Robots, GR00T N1.7 and N1.5 take LeRobot v2.0 or v2.1 while Pi0.5, SmolVLA and ACT take v3.0. See dataset rejected as v3.
Where the task string comes from
The recorder writes one task string per run. Recording a dataset with lerobot-record takes --dataset.single_task, singular, and every frame in that invocation gets it. The natural unit of collection is one task per run, so a multi-task dataset is something you assemble afterwards.
# one run, one task string, 25 episodes
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem585A0076841 \
--robot.id=my_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=my_leader_arm \
--dataset.repo_id=${HF_USER}/cubes_pick \
--dataset.num_episodes=25 \
--dataset.single_task="Pick up the red cube and put it in the box" \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2
What multi-task training actually buys you
Three papers give usable numbers, and they do not all point the same way.
BC-Z: pooling across tasks rescued a task that single-task training could not learn
BC-Z (Jang et al., CoRL 2021) collected 25,877 demonstrations across 100 tasks, 125 hours of robot time, 12 robots and 7 operators, plus 18,726 human videos. The policy is a ResNet-18 conditioned through FiLM layers on a 512-dimensional task embedding, running closed-loop at 10 Hz.
Its sharpest ablation is on place the bottle in the ceramic bowl, the task with the most data at 1000 demonstrations. A single-task policy on those 1000 demos reached 5 percent; the multi-task language-conditioned policy trained on all 25,877 reached 52. The paper's own reading: collecting over several robots and operators likely makes any one task harder to learn, and only pooling across tasks recovered it.
| BC-Z setting | Conditioning | Success |
|---|---|---|
| Table 4, single-task baseline, 1000 demos | n/a | 5% |
| Table 4, multi-task, all 25,877 demos | one-hot task id | 45% |
| Table 4, multi-task, all 25,877 demos | language embedding | 52% |
| Table 4, multi-task, no adaptive state-diff | one-hot task id | 3% |
| Table 3, 21 training tasks | one-hot task id | 42% |
| Table 3, 21 training tasks | language embedding | 40% |
| Table 3, 21 training tasks | human video embedding | 24% |
| Table 3, 28 held-out tasks | language embedding | 32% |
| Table 3, 28 held-out tasks | human video embedding | 4% |
Three things fall out. Language matches a one-hot task id on the 21 training tasks, 42 against 40, so the embedding is not the bottleneck. Language is the only conditioning that transfers to unseen tasks, 32 percent against 4 for video. And the bottom row is the warning: an unrelated processing choice, the adaptive state-diff, dropped the same multi-task policy from 45 to 3 percent.
RT-1: task diversity beat task quantity
RT-1 (Brohan et al., 2022) trained a 35M-parameter transformer at 3 Hz on roughly 130k episodes covering over 700 instructions, gathered with 13 robots over 17 months. Its data ablation is the most useful result in this area because it separates how much data from how many tasks.
| Dataset variant | % tasks | % data | Seen tasks | Generalization, all | Unseen tasks | Distractors | Backgrounds |
|---|---|---|---|---|---|---|---|
| Full dataset | 100 | 100 | 97 | 73 | 76 | 83 | 59 |
| Capped at 200 examples per task | 100 | 51 | 71 | 50 | 52 | 39 | 59 |
| Capped at 100 examples per task | 100 | 37 | 55 | 46 | 57 | 35 | 47 |
| Capped at 50 examples per task | 100 | 22 | 59 | 29 | 14 | 31 | 41 |
| Narrower: drop the tasks with the least data | 75 | 97 | 86 | 54 | 67 | 42 | 53 |
Read the columns carefully, because the summary column is easy to misquote. Generalization, all is the mean of the three columns to its right, not one of them: 14, 31 and 41 average to 29 on the 22-percent row. Seen-task success is also not monotonic in dataset size, 55 at 37 percent of the data against 59 at 22 percent.
RT-1's own sentence: removing 25 percent of the tasks while keeping 97 percent of the data achieves an equivalent generalization performance to reducing the dataset size by as much as 49 percent. More episodes of a task you already have are worth less than the same number of episodes of a task you do not.
SmolVLA: multi-task on an SO-100, with the awkward row included
SmolVLA is the closest published result to what most readers will actually run: a 450M-parameter VLA, three real tasks, an SO-100 arm. It was pretrained on 481 community datasets totalling 22.9K episodes and 10.6M frames, then fine-tuned.
| Policy and setting | Pick-Place | Stacking | Sorting | Average |
|---|---|---|---|---|
| ACT, trained per task (single-task), Table 3 | 70 | 50 | 25 | 48.3 |
| Pi0 3.5B, multi-task, Table 3 | 100 | 40 | 45 | 61.7 |
| SmolVLA 0.45B, multi-task, community pretrained, Tables 3 and 5 | 75 | 90 | 70 | 78.3 |
| SmolVLA 0.45B, single-task, no VLA pretraining, Table 5 | 55 | 45 | 20 | 40.0 |
| SmolVLA 0.45B, multi-task, no VLA pretraining, Table 5 | 80 | 40 | 35 | 51.7 |
The averages give the quotable line: pretraining on the community mixture lifts the multi-task average from 51.7 to 78.3. The per-task columns give a second one. Without pretraining, going multi-task raised Pick-Place from 55 to 80 but lowered Stacking from 45 to 40. And single-task ACT scored 50 on Stacking against multi-task Pi0's 40, Pi0 at 3.5 B parameters against ACT's roughly 80 M.
Report per task, never only the mean. In SmolVLA's own ablation one of three tasks got worse when the other two were added. If that is the task you care about, the average tells you the opposite of what you need.
Which policies can even read a task string
This is where a lot of multi-task datasets quietly become pointless. Before you spend a week writing careful instructions, check whether your model has a text encoder at all.
| Policy | Reads the task string? | Where the string goes | Latency per action step |
|---|---|---|---|
| GR00T N1.7 | Yes | meta/tasks.jsonl, into the Cosmos-Reason2-2B backbone | 152 ms |
| GR00T N1.5 | Yes | meta/tasks.jsonl, into the VLM backbone | 165 ms |
| Pi0.5 | Yes | task field, into the PaliGemma backbone | 485 ms |
| SmolVLA | Yes | task field, tokenized at tokenizer_max_length = 48 into the SmolVLM2-500M-Video-Instruct backbone | 245 ms |
| ACT | No | ignored; the config declares no tokenizer and no task input | 20 ms |
Latency figures are the ones AY-Robots publishes on the policy comparison page. The ACT row catches people: on lerobot main, configuration_act.py declares no tokenizer, no text encoder and no task field, and modeling_act.py never mentions a tokenizer. ACT is an imitation learning architecture mapping images and joint state to an action chunk, and nothing in it reads text.
Feed ACT four task strings and it trains without error, writes a healthy-looking loss curve, and produces a policy that learned the average of four behaviours conditioned only on pixels. If those tasks start from visually similar scenes, the result looks exactly like loss falls but the policy does nothing. Train ACT once per task, or move to SmolVLA.

Assembling several tasks into one dataset
Three runs, one task each. Now you need one dataset: merge, relabel, check.
- 1Record each task as its own run
Keep camera positions, arm id and fps identical across runs. Merge requires identical features, and aggregate_datasets validates fps, robot type and features before concatenating anything.
bashlerobot-record --dataset.repo_id=${HF_USER}/cubes_pick --dataset.single_task="Pick up the red cube and put it in the box" --dataset.num_episodes=25 ... lerobot-record --dataset.repo_id=${HF_USER}/cubes_stack --dataset.single_task="Stack the red cube on the blue cube" --dataset.num_episodes=25 ... lerobot-record --dataset.repo_id=${HF_USER}/cubes_sort --dataset.single_task="Sort the cubes by colour into the two bins" --dataset.num_episodes=25 ... - 2Merge them into a single repo id
Episodes are concatenated in the order you list the repo ids. The task strings survive and become separate entries in meta/tasks.parquet.
bashlerobot-edit-dataset \ --repo_id ${HF_USER}/cubes_multitask \ --operation.type merge \ --operation.repo_ids "['${HF_USER}/cubes_pick', '${HF_USER}/cubes_stack', '${HF_USER}/cubes_sort']" - 3Fix the task strings in place
modify_tasks rewrites meta/tasks.parquet, the task_index column, the episode metadata and total_tasks in info.json. It edits in place, so --new_repo_id and --new_root are ignored. Back up first.
bash# standardise wording across the merged dataset lerobot-edit-dataset \ --repo_id ${HF_USER}/cubes_multitask \ --operation.type modify_tasks \ --operation.task_replacements '{"Sort the cubes by colour into the two bins": "Sort the cubes by color into the two bins"}' # or relabel specific episodes lerobot-edit-dataset \ --repo_id ${HF_USER}/cubes_multitask \ --operation.type modify_tasks \ --operation.episode_tasks '{"0": "Pick up the red cube and put it in the box", "63": "Stack the red cube on the blue cube"}' - 4Check the task counts before you rent a GPU
Count frames per task, not episodes per task. Frames are what the sampler uses.
pythonfrom lerobot.datasets.lerobot_dataset import LeRobotDataset ds = LeRobotDataset("your-user/cubes_multitask") print(ds.meta.total_tasks) print(ds.meta.tasks) # task string -> task_index import collections frames = collections.Counter() eps = ds.meta.episodes for i in range(ds.num_episodes): task = eps["tasks"][i][0] if eps["tasks"][i] else "" frames[task] += eps["length"][i] for task, n in frames.most_common(): print(f"{n:>8} {task}")
The DatasetConfig comment above repo_id still says you may provide a list of datasets that train.py concatenates, but make_dataset in src/lerobot/datasets/factory.py raises NotImplementedError("The MultiLeRobotDataset isn't supported for now.") before it constructs one. The comment is stale. Merge into a single repo id first. Checked on main, 23 August 2026.

Task balance: what the sampler is really doing
The word balance does a lot of unexamined work here, so: lerobot trains with EpisodeAwareSampler, which its docstring calls a sampler over episode frames. It keeps only the per-episode frame boundaries, then shuffles each epoch with one torch.randperm over every frame, seeded from the run seed and the epoch number. No per-task weighting anywhere in it, and no per-task argument to give it.
A task's effective weight is therefore its share of the total frames. Twenty-five episodes of a 40-second stack and twenty-five of a 12-second pick contribute frames at roughly 10:3, so the stack gets about three times the gradient updates even though the episode counts match.
| Knob | Where | What it does |
|---|---|---|
| --dataset.episodes | lerobot-train | Train on an explicit list of episode indices |
| --dataset.exclude_episodes | lerobot-train | Drop specific episodes on top of that, e.g. corrupt ones |
| --dataset.eval_split | lerobot-train | Hold out the last ceil(n * split) episodes per task |
| episode_filter | LeRobotDataset(...) | Predicate over per-episode metadata, including task_index |
| --ds-weights-alpha | Isaac-GR00T gr00t/experiment/launch_finetune.py | Sampling weight per dataset becomes len(dataset)^alpha |
| --dataset-path | Isaac-GR00T gr00t/experiment/launch_finetune.py | One dataset root, or several separated by os.pathsep |
Two deserve a note. lerobot's eval_split is stratified by task by design: make_train_eval_datasets groups episodes by task string and holds out the tail of each group, so eval_split 0.2 on five tasks gives an eval set containing all five.
GR00T's ds_weights_alpha is the only mixture control the fine-tune CLI exposes. Its docstring: each dataset's sampling weight is len(dataset)^alpha and per-dataset mix_ratio values are ignored. Alpha 1 is plain pooling by length, alpha 0 weights every dataset equally regardless of size. Either way launch_finetune.py pools every path you pass into a single entry at mix_ratio 1.0, so genuine per-dataset ratios have to come from a config file loaded by launch_train.py, not from a flag.
- A rare task with 8 percent of the frames is otherwise learned as noise around the dominant one.
- Octo's authors did a coarse version by hand: they doubled the weight of the more diverse datasets and down-weighted repetitive ones so they would not dominate the mixture.
- Per-task scores become comparable, because each task saw a similar number of updates.
- Upsampling a small task repeats the same frames, which is overfitting with extra steps, not more data.
- If one task is the product and the others exist only for transfer, proportional is correct.
- lerobot exposes no per-task weight, so forcing uniform means trimming episodes, which is destructive.
Writing task strings the model can use
SmolVLA's authors hit this at scale. Across 481 community datasets they found substantially noisy annotations: placeholders like task desc, commands as vague as Hold or Up, and datasets with no instruction at all. Their fix was to run Qwen2.5-VL-3B-Instruct over representative frames to write a short, action-oriented sentence, and to rename cameras by hand to OBS_IMAGE_1 through OBS_IMAGE_3.
- Write the instruction the way a person would say it out loud: "Pick up the red cube and put it in the box", not "pick_red_cube_v2".
- Keep it short. SmolVLA sets
tokenizer_max_length = 48, so anything past roughly 48 tokens never reaches the model. - Separate the strings by content words, not punctuation or casing. "Pick the cube" and "pick the cube." are two different task_index values.
- Name the object and the destination when they vary. If two tasks differ only in which bin, the string is the only signal the policy has.
- Use exactly one string per task across all runs, standardised afterwards with
--operation.type modify_tasks. - Do not encode the episode number, the date or the operator. Every unique string is a separate task as far as the format is concerned.
lerobot-rollout takes --task="...", and the lerobot SmolVLA guide annotates that exact line in its evaluation command: use the same task description you used in your dataset recording. A policy that scores well offline and fails on the robot is often one being asked for a string it never saw. See policy only works in one setup.
lerobot-rollout \
--strategy.type=base \
--policy.path=${HF_USER}/my_smolvla_multitask \
--robot.type=so100_follower \
--robot.port=/dev/ttyACM1 \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--task="Stack the red cube on the blue cube" \
--duration=60Two routes to the same multi-task policy
- 1Install lerobot with the SmolVLA extra
Use a fresh environment; the VLA extras pull in a lot.
bashgit clone https://github.com/huggingface/lerobot cd lerobot pip install -e ".[smolvla]" - 2Record one run per task, then merge
Same cameras, same fps, same robot id across every run.
bashlerobot-edit-dataset \ --repo_id ${HF_USER}/cubes_multitask \ --operation.type merge \ --operation.repo_ids "['${HF_USER}/cubes_pick', '${HF_USER}/cubes_stack', '${HF_USER}/cubes_sort']" - 3Fine-tune with a per-task holdout
eval_split holds out the last fraction of episodes per task, so every task appears in the eval set. The lerobot docs put a 20k-step SmolVLA run at roughly four hours on one A100.
bashlerobot-train \ --policy.path=lerobot/smolvla_base \ --dataset.repo_id=${HF_USER}/cubes_multitask \ --dataset.eval_split=0.2 \ --batch_size=64 \ --steps=20000 \ --output_dir=outputs/train/smolvla_multitask \ --job_name=smolvla_multitask \ --policy.device=cuda \ --wandb.enable=true - 4Roll out each task separately
Same checkpoint, three --task strings, three scores.
bashfor T in "Pick up the red cube and put it in the box" \ "Stack the red cube on the blue cube" \ "Sort the cubes by color into the two bins"; do lerobot-rollout --strategy.type=base \ --policy.path=outputs/train/smolvla_multitask/checkpoints/last/pretrained_model \ --robot.type=so100_follower --robot.port=/dev/ttyACM1 \ --task="$T" --duration=60 done
A 24 GB card of your own or a rented one you configure yourself. In exchange you control the sampler, the mixture and the eval split completely.
- 1Record with the desktop client
The desktop client records LeRobot-format datasets out of a teleoperation session: episodes, camera streams, joint states. One session per task.
- 2Pick the model and the dataset in the training form
The training form takes a model, a dataset and hyperparameters. Datasets come from the public directory, a Hugging Face repo id, or your own machine. The backend rents a GPU by required VRAM and writes checkpoints to object storage.
- 3Run the policy back on the arm
/api/inference/podauto-provisions a cloud GPU pod serving the policy, and the local client talks to that endpoint. Pods carry an idle watchdog and destroy themselves when idle. Same operations from the CLI and the MCP server.
There is no per-task mixture weighting in the training form: fix task balance in the dataset before uploading. The form will not warn you that you picked ACT for a five-task dataset either. And remote inference adds public-internet round trips on top of a control loop already at 20 to 485 ms per action step: fine for slow pick-and-place, not for fast reactive motion.
| Tier | Policies | Typical run | Price per hour | Cost per run |
|---|---|---|---|---|
| A100 80 GB / H100 80 GB | GR00T N1.7, GR00T N1.5, Pi0.5 | 3 to 6 hours | 1.20 to 2.00 USD | about 4 to 12 USD |
| RTX 4090 / any 24 GB card | SmolVLA, ACT | 2 to 5 hours | 0.30 to 0.60 USD | about 1 to 3 USD |

When a single-task ACT still beats a multi-task VLA
The honest version is not "VLAs win". VLAs win on the axes a VLA is built for and lose on the one a small from-scratch model is built for. Latency is the axis nobody argues with: on this platform ACT runs at 20 ms per action step, GR00T N1.7 at 152 ms, SmolVLA at 245 ms and Pi0.5 at 485 ms.
| Situation | Pick | Why |
|---|---|---|
| One task, fast reactive motion | ACT, single-task | 20 ms per action step; language buys nothing with one task |
| Three or more tasks, one rig | SmolVLA or GR00T N1.7, multi-task | One checkpoint instead of three; SmolVLA averaged 78.3 against ACT's 48.3 |
| You want tasks you did not record | A language-conditioned VLA | BC-Z reached 32 percent on held-out tasks; a one-hot id transfers to nothing |
| Tasks look identical at the start frame | A language-conditioned VLA, or separate policies | ACT sees the same pixels and cannot disambiguate them |
| One task matters, the rest are decoration | ACT single-task on the one that matters | Multi-task can lower a per-task score while raising the mean |
Language conditioning also has a measured cost. Octo, evaluated zero-shot on the WidowX tasks, reached a 25 percent higher success rate under goal-image conditioning than under language; the authors say this is likely because a goal image carries more information about how to achieve the task. Two tasks that differ only by a fine spatial detail may not be separable by a sentence.
Nothing forces one checkpoint. With one fast task and two slow ones, a single-task ACT for the fast one plus a multi-task SmolVLA for the rest is often the highest-scoring setup, and both fit the same 24 GB tier. Head to head: ACT vs SmolVLA.
Evaluating a policy that does several things
A single average across tasks is the wrong summary statistic. Report a per-task table before and after, and hold out episodes per task rather than off the end of the dataset. The training docs cover the run mechanics this section assumes.
# per-task holdout: the last 20% of episodes of EACH task go to eval
lerobot-train \
--policy.path=lerobot/smolvla_base \
--dataset.repo_id=${HF_USER}/cubes_multitask \
--dataset.eval_split=0.2 \
--steps=20000 \
--output_dir=outputs/train/smolvla_multitask \
--policy.device=cudaCheck the noise floor before concluding a mixture change helped. NVIDIA's GR00T README notes users may observe 5-6 percent variance between runs from non-deterministic image augmentations alone, and the Isaac-GR00T fine-tune entry point exposes no seed at all, so GR00T runs are not bit-for-bit reproducible (lerobot's default seed is 1000). A 3-point per-task difference between two checkpoints tells you nothing.
How many episodes per task do I need for a multi-task dataset?▾
AY-Robots lists a minimum of 30 episodes for SmolVLA and 50 for ACT, Pi0.5, GR00T N1.5 and GR00T N1.7. Those are dataset minimums, not per-task minimums, so five tasks at the bare minimum leaves each with about ten episodes, which is not enough for any of them. Treat the published figure as the floor for one task. The lerobot SmolVLA guide recommends around 50 episodes for a single task, recorded as 10 episodes across each of 5 variations, and reports that a comparable 25-episode dataset performed badly.
Can I train ACT on a multi-task dataset?▾
It runs and it will not warn you, but ACT has no language input. On lerobot main configuration_act.py declares no tokenizer, no text encoder and no task field, so the string is ignored and you get one policy that averaged your behaviours. If the tasks start from visually distinct scenes it may still work; if they start from similar scenes it will not.
Do I have to balance the tasks equally?▾
No, and often you should not. What matters is that the balance matches your priorities, because EpisodeAwareSampler weights every task by its share of frames. If all your tasks matter equally, aim for equal frame counts, not equal episode counts. If one task is the product and the rest exist for transfer, leaving it dominant is correct.
How do I fix task strings after recording?▾
Use lerobot-edit-dataset with --operation.type modify_tasks: --operation.new_task for a blanket default, --operation.episode_tasks for a mapping from episode index to string, --operation.task_replacements for search and replace, resolved in that precedence. It edits in place, updating meta/tasks.parquet, the task_index column, the episode metadata and total_tasks, so take a copy first.
Can I train on several datasets at once instead of merging them?▾
On lerobot main, no: make_dataset raises NotImplementedError("The MultiLeRobotDataset isn't supported for now.") before constructing one, so merge into a single repo id first. Isaac-GR00T is different: gr00t/experiment/launch_finetune.py accepts several dataset roots separated by os.pathsep in --dataset-path, and --ds-weights-alpha weights them by len(dataset)^alpha.
Five policies, real numbers, no marketing
Parameter counts, GPU tier, inference latency per action step and minimum episodes for GR00T N1.7, GR00T N1.5, Pi0.5, SmolVLA and ACT, with the language-conditioning column that decides whether a multi-task dataset is worth recording.
Compare the policiesWhat to do next
One fast task: train an ACT and skip everything above. Three tasks on the same rig: record separately, merge, count frames per task rather than episodes, and fine-tune SmolVLA with eval_split set so the holdout contains all three. Then score each task on its own against the single-task baselines you already have. That comparison is cheap on the 24 GB tier and it is the only thing that tells you whether multi-task is better for your tasks.
Related reading: the BC-Z breakdown, how to collect high-quality VLA training data on the recording side, and the VLA overview. Benchmark data for 85 models sits in the arena, and the format details this page skipped are in the dataset docs.
Sources
- BC-Z: Zero-Shot Task Generalization with Robotic Imitation Learning, Jang et al., CoRL 2021 (arXiv 2202.02005). Tables 3 and 4.
- RT-1: Robotics Transformer for Real-World Control at Scale, Brohan et al., 2022 (arXiv 2212.06817). Table 7, data quantity and diversity ablation.
- SmolVLA: A Vision-Language-Action Model for Affordable and Efficient Robotics, Shukor et al., 2025 (arXiv 2506.01844). Tables 1, 3 and 5.
- Octo: An Open-Source Generalist Robot Policy, Octo Model Team, 2024 (arXiv 2405.12213). Goal-image against language conditioning on WidowX; manual dataset mixture weighting.
- lerobot LeRobotDataset: the v3.0 on-disk layout and the tasks metadata docstring, main branch, read 23 Aug 2026
- lerobot EpisodeAwareSampler: per-episode frame boundaries, seeded per-epoch permutation, no per-task weighting, main branch
- lerobot datasets/factory.py: make_dataset raises NotImplementedError for MultiLeRobotDataset; make_train_eval_datasets holds out the last ceil(n * eval_split) episodes per task, main branch
- lerobot DatasetConfig: eval_split, exclude_episodes, episodes, and the stale list-of-datasets comment above repo_id, main branch
- lerobot ACTConfig, main branch: no language, task or tokenizer fields; chunk_size and n_action_steps default to 100
- lerobot SmolVLAConfig, main branch: tokenizer_max_length = 48, vlm_model_name HuggingFaceTB/SmolVLM2-500M-Video-Instruct
- lerobot, Using Dataset Tools: merge, split and modify_tasks with lerobot-edit-dataset, main branch, read 23 Aug 2026
- lerobot, Imitation Learning on Real-World Robots: the lerobot-record and lerobot-rollout command lines
- lerobot SmolVLA guide: fine-tuning command, ~50 episodes over 5 variations, 20k steps at roughly 4 hours on one A100, and the same-task-description note on --task
- Isaac-GR00T FinetuneConfig: dataset_path as an os.pathsep-separated list, ds_weights_alpha dataset soup weighting, no seed field, main branch
- NVIDIA Isaac-GR00T README: GR00T LeRobot v2 data format with tasks.jsonl and modality.json, Cosmos-Reason2-2B backbone for N1.7, convert_v3_to_v2.py, 5-6% run-to-run variance
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started