Views
No views yet
transformers dependency.pc_success, % of episodes solved), 10 tasks ×
10 episodes per suite (400 rollouts), n_action_steps=10, --seed 1:| Suite | pc_success |
|---|---|
| libero_object | 97.0 |
| libero_goal | 88.0 |
| libero_spatial | 82.0 |
| libero_10 (long-horizon) | 60.0 |
| Average | 81.8 |
eval_libero.py --seed 1, to
within run-to-run noise (see Caveat 1 — fixed seed is approximately, not
bit-exactly, reproducible on GPU). Please read
Caveats before comparing to any other paper or
checkpoint — the eval protocol and settings matter a lot here.| File | What it is |
|---|---|
model.safetensors | the weights (557.6M; frozen SmolVLM2 backbone + trained expert/projections) |
config.json | architecture config (rebuilds the model exactly) |
norm_stats.safetensors | state/action normalization stats the model was trained with — load-bearing for replication |
tokenizer.json | the SmolVLM2-500M-Instruct tokenizer (bundled; Apache-2.0) |
smolvla/ | minimal, transformers-free inference + eval code (pure PyTorch) |
predict_example.py | minimal load + single forward pass (no simulator) |
eval_libero.py | standalone eval that reproduces the table above (needs the LIBERO sim) |
requirements.txt | pinned dependency versions |
1pip install -r requirements.txt # torch, numpy, safetensors, tokenizers
2python predict_example.py1import torch
2from safetensors.torch import load_file
3from smolvla import SmolVLA, SmolVLAProcessor, Tokenizer, load_lerobot_norm_stats, load_smolvla_config
4from smolvla.types import Obs
5
6cfg = load_smolvla_config("config.json")
7model = SmolVLA(cfg).float().eval()
8model.load_state_dict(load_file("model.safetensors"))
9stats = load_lerobot_norm_stats("norm_stats.safetensors")
10proc = SmolVLAProcessor(cfg, Tokenizer("tokenizer.json", max_length=cfg.tokenizer_max_length), stats, device="cpu")
11
12obs = Obs(images={"image": torch.rand(1,3,512,512), "image2": torch.rand(1,3,512,512)},
13 state=torch.zeros(1,8), task=["pick up the black bowl and place it on the plate"])
14chunk = model.predict_action_chunk(proc.to_model_input(obs)) # (1, 50, 32) normalized
15actions = proc.postprocess_action(chunk) # (1, 50, 7) rawpredict_action_chunk returns a chunk of chunk_size=50 actions; at eval you
execute the first n_action_steps (we use 10) before re-planning.1# 1. get the HF CLI, then download this repo (it contains requirements.txt + the code)
2pip install -U "huggingface_hub[cli]"
3hf download verapulse/pulsevla-libero-0.5b --local-dir ./pulsevla-libero
4cd ./pulsevla-libero
5
6# 2. deps: inference (requirements.txt) + the public LIBERO sim. NOTE: lerobot 0.5.2
7# is a main-branch dev version NOT on PyPI (latest PyPI is 0.5.1); install the exact
8# commit we used (pulls robosuite + mujoco + bddl):
9pip install -r requirements.txt
10pip install "lerobot[libero] @ git+https://github.com/huggingface/lerobot.git@d1b1c5c8cff5e1f637495e1667a1d6c7c5258f3b"
11
12# 3. run the canonical eval, once per suite (headless rendering => MUJOCO_GL=egl)
13MUJOCO_GL=egl python eval_libero.py --task libero_object --seed 1
14MUJOCO_GL=egl python eval_libero.py --task libero_goal --seed 1
15MUJOCO_GL=egl python eval_libero.py --task libero_spatial --seed 1
16MUJOCO_GL=egl python eval_libero.py --task libero_10 --seed 1pc_success. With --seed 1 and the defaults
(--n_action_steps 10 --n_envs 1) you should get the table above.eval_libero.py's
defaults):n_action_steps = 10, n_envs = 1, 10 tasks × 10 episodes per suite;norm_stats.safetensors (these are the
HuggingFaceVLA/libero dataset-metadata stats the model trained with — no dataset
download needed for eval);--seed 1 reseeds the policy's flow-matching noise per episode (see below).--seed 1 is only approximately reproducible
on GPU. It samples flow-matching noise from the global RNG on every re-plan.
Unseeded, pc_success varies ±5–10 pts per suite at 100 episodes. --seed 1
fixes that noise and gets you the table within a few points — but it is
not bit-exact on GPU: residual CUDA / MuJoCo nondeterminism can flip a few
near-boundary episodes from run to run. In our own clean-room checks, object,
spatial and libero_10 reproduced exactly across runs, while goal moved
between 84% and 88% (one task flipping 4 episodes). So expect to land within a
couple of points of each number, sometimes exactly. (Full bit-determinism would
additionally need torch.use_deterministic_algorithms(True),
CUBLAS_WORKSPACE_CONFIG=:4096:8, and a fixed-seed simulator — we do not enforce
these.) A different seed, or unseeded, will likewise land a few points off — all
expected, not a bug.--n_envs 1. Batched rollouts (--n_envs > 1,
or --vec async for speed) draw the noise in a different shape, so they produce a
different but equally valid sample — not the seed-1 table. Use --n_envs 1 to
match us; use --vec async only when you want a faster estimate and don't need
exact reproduction.lerobot at commit d1b1c5c8 (its dev version string is 0.5.2, which is
not on PyPI — the latest PyPI release is 0.5.1). Install the pinned commit
shown in step 1; other versions may change env construction or eval batching and
shift numbers.[eef_pos(3), quat→axis-angle(3), gripper_qpos(2)]), language instruction →
chunk of 7-DoF actions. State/action normalized with the bundled stats; images are
flipped 180° and mapped to SigLIP range (handled inside smolvla/).tokenizer.json:
Apache-2.0, © Hugging Face — see the
base model card.