Instructions to use Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego with LeRobot:
# See https://github.com/huggingface/lerobot?tab=readme-ov-file#installation for more details git clone https://github.com/huggingface/lerobot.git cd lerobot pip install -e .[smolvla]
# Launch finetuning on your dataset python lerobot/scripts/train.py \ --policy.path=Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego \ --dataset.repo_id=lerobot/svla_so101_pickplace \ --batch_size=64 \ --steps=20000 \ --output_dir=outputs/train/my_smolvla \ --job_name=my_smolvla_training \ --policy.device=cuda \ --wandb.enable=true
# Run the policy using the record function python -m lerobot.record \ --robot.type=so101_follower \ --robot.port=/dev/ttyACM0 \ # <- Use your port --robot.id=my_blue_follower_arm \ # <- Use your robot id --robot.cameras="{ front: {type: opencv, index_or_path: 8, width: 640, height: 480, fps: 30}}" \ # <- Use your cameras --dataset.single_task="Grasp a lego block and put it in the bin." \ # <- Use the same task description you used in your dataset recording --dataset.repo_id=HF_USER/dataset_name \ # <- This will be the dataset name on HF Hub --dataset.episode_time_s=50 \ --dataset.num_episodes=10 \ --policy.path=Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego - Notebooks
- Google Colab
- Kaggle
SmolVLA SO-101 β V2 Lego (single task)
SmolVLA fine-tuned on the Lego colour-sorting task only. The first model in the project that visibly worked, and the proof-of-concept that the pipeline was sound.
Part of Project-IRA β Interactive Robotic Arm. Code: https://github.com/Project-IRA/interactive-robotic-arm
| Base model | lerobot/smolvla_base |
| Robot | SO-101 follower (6-DOF) |
| Training data | Project-IRA/TPSoSe2026_Dataset_Lego_LeRobot_SO101 |
| Recommended checkpoint | 030000 |
| Inputs | camera1 (wrist) + camera2 (desk) images β renamed keys, see Usage β 6-dim joint state, English instruction |
| Outputs | 6-dim continuous action chunks |
Quality
OK-ish on Lego colour sorting. Best checkpoint 030000.
Only knows the Lego task. For a model that handles all four tasks at comparable quality, use V6 Full; for better quality, use Pi05 V7 Full V2.
Training
Single L40S GPU.
| Setting | Value |
|---|---|
| Base | lerobot/smolvla_base |
| Dataset | TPSoSe2026_Dataset_Lego_LeRobot_SO101 (460 episodes, 46 prompts) |
| Steps | 100000 (--save_freq=5000); best at 030000 |
| Batch size | 64 |
| Vision encoder | frozen (SmolVLA default) |
| Parameters | 99,880,992 trainable of 450,046,176 total |
| Camera keys | renamed β wrist_left->camera1, desk_view->camera2 |
| SLURM | --gres=gpu:L40S:1 --cpus-per-task=16 --mem=92G --time=42:00:00 |
Note the best checkpoint (030000) is far short of the 100000-step run length β this task converged early and later checkpoints did not improve on the robot.
lerobot-train \
--policy.path=lerobot/smolvla_base \
--dataset.repo_id=TPSoSe2026_Dataset_Lego_LeRobot_SO101 \
--batch_size=64 --steps=100000 --save_freq=5000 \
--num_workers=16 --tolerance_s=0.01 \
--output_dir=outputs/train/smolvla_lego \
--job_name=smolvla_lego \
--policy.device=cuda --policy.push_to_hub=false --wandb.enable=false \
--rename_map='{"observation.images.wrist_left": "observation.images.camera1", "observation.images.desk_view": "observation.images.camera2"}'
Usage
This model expects renamed camera keys. Training used
--rename_mapto remap the dataset's camera features:
Dataset feature What the policy expects Physical camera observation.images.wrist_leftobservation.images.camera1wrist observation.images.desk_viewobservation.images.camera2desk If you feed this policy
wrist_left/desk_viewit will fail or silently misbehave. Name your camerascamera1(wrist) andcamera2(desk) at inference time, or apply the same--rename_mapwhen re-training. The Pi0.5 models do not do this β they use the nativewrist_left/desk_viewnames.
Model files are nested under
outputs_V2/, sofrom_pretrainedon the repo ID will not work:outputs_V2/train/smolvla_lego/checkpoints/<step>/pretrained_model/Checkpoints present: every 5000 steps from
005000to100000, pluslast. Use030000β not the final one. Repo total ~27.7 GB.hf download Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego \ --include 'outputs_V2/train/smolvla_lego/checkpoints/030000/pretrained_model/*' \ --local-dir ./smolvla_lego
import torch
from lerobot.policies.smolvla.modeling_smolvla import SmolVLAPolicy
policy = SmolVLAPolicy.from_pretrained("Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego")
policy = policy.to("cuda").eval()
On-robot rollout:
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=$ROBOT_ID \
--robot.cameras='{
camera1: {type: opencv, index_or_path: /dev/v4l/by-path/$WRIST_PATH, width: 640, height: 480, fps: 30},
camera2: {type: opencv, index_or_path: /dev/v4l/by-path/$DESK_PATH, width: 640, height: 480, fps: 30}
}' \
--policy.path=Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego \
--dataset.repo_id=$HF_USER/eval_run \
--dataset.single_task="Sort the lego by color" \
--episodes=10
Use one of the exact training prompts (see the dataset card) as the task string. Both cameras run at 640x480 at inference time even though
desk_viewwas recorded at 800x600.
Robot setup
| Robot | SO-101 follower arm (6-DOF), robot_type: so_follower |
| Teleoperation | SO-101 leader arm |
| Control frequency | 30 fps |
| State / action space | 6-dim: shoulder_pan.pos, shoulder_lift.pos, elbow_flex.pos, wrist_flex.pos, wrist_roll.pos, gripper.pos |
Camera observation.images.desk_view |
800x600, h264 (recording) |
Camera observation.images.wrist_left |
640x480, h264 (recording) |
Inference note: both cameras are run at 640x480 during inference, not at their recording resolutions, to reduce the payload sent to the inference server.
Environment notes
All training ran on a SLURM cluster with L40S GPUs. Two environment details were required and are easy to miss when reproducing:
- ffmpeg libraries for torchcodec. A minimal conda env supplies the shared libraries
that
torchcodecdiscovers at runtime:export LD_LIBRARY_PATH=$CONDA_PREFIX/envs/ffmpeg_libs_v8/lib:<venv>/lib/python3.12/site-packages/nvidia/npp/lib:$LD_LIBRARY_PATH --tolerance_s=0.01on every run, to accommodate timestamp jitter in the recorded episodes.
Multi-GPU runs additionally set PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True.
Datasets and the virtualenv were copied to node-local /scratch before training rather
than read from shared storage.
No Weights & Biases logging was enabled for any run (--wandb.enable=false), so there are
no public training curves β the job.*.err SLURM logs are the record.
Tasks and prompts
The model is conditioned on English natural-language instructions. Prompt phrasing was varied roughly every 10 episodes during recording, giving 93 distinct prompts in the merged dataset. Use one of the training prompts verbatim for best results β the full lists are on the dataset card.
Limitations
- Behaviour cloning. The policy imitates teleoperated demonstrations and has no notion of recovery beyond what was demonstrated. It is susceptible to covariate shift and can fail to recover from states outside the demonstration distribution.
- Recovery data is incidental, not systematic. Recovery behaviour appears in the data only where the operator happened to make and correct a mistake during recording; no recovery episodes were scripted deliberately.
- Single environment. All data comes from one lab desk with one lighting setup, one camera geometry, and one set of physical objects. Expect degradation elsewhere.
- Prompt sensitivity. Language conditioning was trained on a fixed set of phrasings (listed in the dataset card). Prompts far from those phrasings may behave unpredictably.
- No formal evaluation. Quality assessments below are qualitative, from operators observing rollouts on the physical arm. There are no success-rate numbers.
- Not safety-rated. Supervise all physical execution and keep the workspace clear.
Upstream licensing & attribution
This model is a derivative work of Apache-2.0 licensed components:
| Component | Upstream | License |
|---|---|---|
| LeRobot framework | https://github.com/huggingface/lerobot | Apache-2.0 |
lerobot/smolvla_base |
https://huggingface.co/lerobot/smolvla_base | Apache-2.0 |
Apache-2.0 permits relicensing derivative works. We retain the upstream copyright notices, license text, and NOTICE files for the incorporated material, as Apache-2.0 Section 4 requires. The upstream components remain under Apache-2.0 β only this project's own contributions (the fine-tuned weights and training configuration) are offered under CC BY-SA 4.0.
CC BY-SA 4.0 was chosen because it is share-alike: derivatives must be released under the same licence, so this work cannot be taken closed-source. The project's source code lives in a separate repository under its own licence β see https://github.com/Project-IRA/interactive-robotic-arm.
Citation
@misc{project_ira_2026,
title = {Project-IRA: Interactive Robotic Arm},
author = {Baten, Cleo and Keppler, Bela and Sapper, Jonas},
year = {2026},
howpublished = {\url{https://huggingface.co/Project-IRA}},
note = {Code: \url{https://github.com/Project-IRA/interactive-robotic-arm}}
}
Model tree for Project-IRA/TPSoSe2026_SmolVLA_LeRobot_SO101_Finetuning_V2_Lego
Base model
lerobot/smolvla_base