Downloads · 30 days
7
29% of all-time downloads
akoniti/parol-smolvla-simulation-weights
parol-smolvla-simulation-weights is a robotics model from akoniti. Use it for the robotics task on the model card, and read the license before you ship it in a product. It is set up for lerobot. The card lists the license as apache-2.0.
A SmolVLA finetune that drives a simulated PAROL6 6-DoF arm in MuJoCo. Two cubes sit on a table, red and blue, next to a container. A plain-text instruction selects which cube to move.
Downloads · 30 days
7
29% of all-time downloads
All-time downloads
24
Public
Parameters
450M
1.2 GB on disk
Likes
1
Trending 1
Click a slice to open those files.
.safetensors1.2 GB · 100%
How the weights are stored.
BF16301M · 67%
From the Hugging Face model README
A SmolVLA finetune that drives a simulated PAROL6 6-DoF arm in MuJoCo. Two cubes sit on a table, red and blue, next to a container. A plain-text instruction selects which cube to move.
This checkpoint solves the task 32% of the time from pixels, but it does not reliably read the instruction. Read Results before using it — the honest summary is that the manipulation works and the language grounding mostly does not.
| base model | lerobot/smolvla_base |
| environment | parol6_sim/Parol6PlaceCube-v0 (MuJoCo, 128×128 RGB, two cameras) |
| action space | Cartesian tool deltas (x, y, z, grip), resolved through IK |
| training data | 491 scripted-oracle demonstrations, 124,809 frames |
| training | 40,000 steps × batch 32 = 1,280,000 samples ≈ 10.25 epochs |
| checkpoint | step 22,000, selected on a validation seed block |
| precision | float32 |
The instruction is one of ten phrasings, five per colour, e.g.
"Put the red cube in the box.", "Drop the blue block in the bin."
Every number below is on held-out seeds that were never used for checkpoint selection, except where marked.
| metric | this policy | oracle | do-nothing |
|---|---|---|---|
| success (50 held-out seeds) | 32% | 100% | 0% |
| median steps | 286 | 218 | — |
| followed the instruction | 52% | 100% | 0% |
| disturbed the other cube | 36% | 0% | 0% |
The measurement that matters. Each scene is run twice — identical cube positions, identical pixels — told "red" once and "blue" once — recording which cube actually moved.
| result | |
|---|---|
| cube changed with the sentence | 10/30 scenes = 33% |
| correct cube both ways | 9/30 = 30% |
Interpret this as weak-to-absent language conditioning. A policy that ignores the sentence and picks a cube at random would switch on roughly half of scenes by luck and be correct both ways about a quarter of the time. The measured 33% / 30% is near that chance level.
So the policy has learned the visuomotor task — approach, grasp, transport, release, at a median 286 steps against the oracle's 218 — while the language channel contributes little. It is a competent cube-placer that is not listening.
An earlier 20,000-step × batch 4 run (0.64 epochs — under one pass over the data) scored 0/20 held-out and 0/12 on the swap. That 0/12 was not evidence about language: the policy could barely move a cube at all, so the ablation conflated "does not read the instruction" with "cannot do the task". Only once success was non-zero could conditioning be measured.
Scaling to 10.25 epochs took success from 0% to 32% and then plateaued —
validation success flattened around step 14,000 and training loss around step
26,000. More training on this recipe will not help. The remaining gap is
architectural: the finetune runs with freeze_vision_encoder=true and
train_expert_only=true, so only the action expert is trained and nothing
adapts the language pathway to this task.
Requires LeRobot 0.6.1 and the
parol6-sim environment package.
from lerobot.configs.policies import PreTrainedConfig
from lerobot.policies.factory import get_policy_class, make_pre_post_processors
cfg = PreTrainedConfig.from_pretrained("akoniti/parol-smolvla-simulation-weights")
policy = get_policy_class(cfg.type).from_pretrained(
"akoniti/parol-smolvla-simulation-weights")
The normalisation statistics live in the saved preprocessor, not in the
weights. A policy invoked without policy_preprocessor / policy_postprocessor
runs happily and emits garbage. Load them.
The task string is required and must be non-empty — this is a VLA, and an empty instruction is silently accepted while destroying the result.
| file | purpose |
|---|---|
model.safetensors | the policy weights, float32 |
config.json | policy configuration |
policy_preprocessor* | normalisation statistics — required |
policy_postprocessor* | action unnormalisation — required |
train_config.json | the full training configuration this run used |
evals/*.json | per-checkpoint evaluation results, all 20 checkpoints |
The dataset is not distributed; it regenerates exactly from seeds, and has
been verified to reproduce frame-for-frame across three different machines.
The full runbook — clone, bootstrap, regenerate, sweep throughput, train,
evaluate — is SETUP.md in the project repository.
Training took ~34.5 h on an Apple M5 Max (36 GB unified) at batch 32. Batch size must be re-measured per machine: on this hardware throughput collapsed 12× at batch 64 and ran out of memory at 128.