- Trainer key
- pi0
- GPU tier
- A100 80 GB or H100 80 GB
- Inference
- about 485 ms per action step
- Batch size
- 1, gradient accumulation 16
- Learning rate
- 5e-5
- Steps
- 30,000
- Dataset format
- LeRobot v2.1
- Typical run
- 3 to 6 hours, about 4 to 12 USD
- Servos
- Feetech STS3215 bus servos
- Servo voltage
- 7.4 V
Upload a LeRobot v2.1 dataset of at least 50 SO-100 episodes, open Training, pick Pi0.5, and start the run with the defaults: batch size 1, learning rate 5e-5, 30000 steps, gradient accumulation 16 on an A100 80 GB. The run takes 3 to 6 hours and costs about 4 to 12 USD, after which the policy runs on the arm at roughly 485 ms per action step.
What you need before you start
- A calibrated SO-100 with all six STS3215 servos responding, as covered in /learn/so-100-getting-started
- The desktop client installed and paired, so there is no Python environment to build
- At least 50 kept episodes of one task, recorded as a LeRobot v2.1 dataset and uploaded
- Two cameras that have not moved since the first episode was recorded
- A billing method on the account, because the run rents an 80 GB card by the hour
- A task that rewards precision rather than speed, which is the whole reason to pick this model
Feetech STS3215 servos are 7.4 V units. A 12 V supply, which is correct for other arms and for the LeKiwi base, destroys them in seconds and the damage is not recoverable. Read the label on the supply, not the label on the box it came in.
Why Pi0.5 earns its 485 ms on this arm
Pi0.5 is a flow-matching vision-language-action model on a PaliGemma backbone, around three billion parameters. Flow matching means the action head learns a continuous path from noise to an action chunk instead of choosing among discretized bins. The practical consequence on an SO-100 is that the commanded trajectory is smooth by construction, and small corrections stay small instead of snapping to the nearest quantized value.
That matters most when the gripper is already touching something. Seating a lid, sliding a peg into a hole, stacking a second block on a first, closing a latch: these are tasks where the correct next action differs from the current one by a fraction of a degree, and where a policy that jumps produces a nudge that ruins the alignment. The SO-100 has no force sensing and a noticeable amount of backlash, so it cannot recover from a nudge the way a stiffer arm can. Continuity in the output is the cheapest substitute for compliance in the hardware.
It does not pay everywhere. At about 485 ms per action step the arm issues just over two commands per second. On a task that is mostly free-space transit, that time is spent doing nothing useful and the model is beaten on both cost and appearance by something smaller. Pick Pi0.5 when the hard part of your task happens in contact.
Pi0.5, pi0 and pi05: three names, one model
The naming trips people up on the first API call. The model id the training backend takes is the string pi0. The policy type written into the trained checkpoint is pi05. The dropdown in the UI says Pi0.5, and the vendor writes it with a Greek letter. Search traffic arrives here as "pi zero", "pi 0.5" and "π0", all of which mean the same model. If you pass pi05 as the model id it will not resolve, so use pi0 in anything programmatic and expect pi05 back in the artifact metadata.
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "start_training",
"arguments": {
"dataset_id": "ds_7c41a9",
"policy_name": "so100-lid-seat-pi05-seed-42",
"model_id": "pi0",
"max_steps": 30000,
"confirm_spend": true
}
}
}What the dataset has to look like
The trainer reads LeRobot v2.1, which is what the client writes by default. Fifty episodes is the point where this model starts producing something you can evaluate seriously; below that you are measuring noise. Beyond the usual rules for clean demonstrations, two things matter specifically for a flow-matching policy.
- Demonstration smoothness transfers directly. The model reproduces the shape of the trajectories you recorded, so a demonstration with a hesitation in it teaches a hesitation.
- One task string, phrased identically across every episode. The language side of the backbone attends to it, and two phrasings of the same task split your data in half.
- Vary object placement, not your approach strategy. Two incompatible strategies average into a path that touches neither.
- Keep the grasp moment visible. If the wrist camera loses sight of the contact, the part of the task Pi0.5 is good at is the part it cannot see.
A demonstration recorded as fast as your hand can move it is a target the policy will chase at just over two action steps per second and miss. Deliberate, even motion during recording is not only better data, it is closer to what the deployed policy is physically able to output.
Start the run
- 1Open Training and choose the dataset
The dataset picker lists what has finished processing. Open the preview once and confirm the episode count and both camera streams before you spend anything: a dataset that uploaded with one camera missing trains perfectly well and gives you a worse policy for the same money.
- 2Select Pi0.5 in the model list
The card shows the A100 80 GB requirement and the inference figure. Selecting it swaps the parameter block to the pi0 defaults and reveals the two extra fields this trainer family exposes, seed and log frequency.
- 3Review the parameters
Batch size 1, learning rate 5e-5, 30000 steps, gradient accumulation 16. Set a seed now rather than later, and give the policy a name that contains the seed and the dataset version so the run is identifiable in three weeks.
- 4Start it and let the pool find a card
GPUs are rented on a spot market and selected by VRAM rather than by model name, so the job may sit queued for a while before an 80 GB card is available. Queued time is not billed.
- 5Watch the run page, not the loss alone
The run page plots loss, learning rate and gradient norm alongside GPU utilization, VRAM, temperature and power. Utilization tells you the job is really training; a card sitting near idle with the loss frozen means the data loader is the bottleneck, not the model.
- 6Take two or three checkpoints from the second half
The final checkpoint is the newest, not automatically the best. Keep a couple from the back half of the schedule and let the arm decide between them, because nothing on this page can.
The defaults, and when to change them
| Parameter | Default for Pi0.5 | Change this when |
|---|---|---|
| Batch size | 1 | Effectively never. The pi0 path is configured around accumulation, and raising this changes the effective batch you would be comparing your earlier runs against. |
| Learning rate | 5e-5 | The loss spikes inside the first thousand steps and never recovers, which means lower. Raising it on a 50-episode SO-100 set is rarely the fix people hope for. |
| Max steps | 30000 | You have well over a hundred episodes and the curve is still falling steeply at the end, so extend. Under fifty episodes, a shorter schedule saves GPU hours you were going to waste. |
| Gradient accumulation | 16 | Rarely. Lowering it makes each update noisier without making the run finish sooner, since the same number of samples still passes through the model. |
| Effective batch | 16 (1 x 16) | This is the number to hold constant when you compare two runs. If you change batch size or accumulation, note the product or your comparison means nothing. |
| Seed | You set it, lerobot family only | Always. It costs nothing and it is the difference between "the second run was better" and "the second run was different". |
| Log frequency | You set it, lerobot family only | Lower it on a short diagnostic run so the chart has points early. Raise it on a full 30000-step run so the curve stays readable. |
| GPU tier | A100 80 GB | Not yours to choose. The pool requests an 80 GB card for this model and takes whichever qualifying card the spot market offers. |
Cost and wall clock
An A100-tier run on this platform takes 3 to 6 hours at 1.20 to 2.00 USD per hour, so about 4 to 12 USD in total. Pi0.5 sits at the upper end of that band, and the reason is worth understanding, because it is not the reason most people assume.
Batch size 1 on an 80 GB card leaves memory to spare. The constraint is the clock: 30000 steps with 16 accumulation steps behind each of them is a lot of forward and backward passes, and they happen one small sample at a time. Nothing you can set in the form makes that materially faster, which is why the practical lever on cost is the step count and the honest question of whether this task needs this model at all.
A SmolVLA run on a 24 GB card takes 2 to 5 hours at 0.30 to 0.60 USD per hour, about 1 to 3 USD. If that run produces nothing on the arm, the fault is almost certainly in the demonstrations, and paying A100 prices to rediscover that is an expensive way to be told.
Reproducing a run exactly
Seed and log frequency are exposed for the lerobot family, which is ACT, SmolVLA and pi0. GR00T does not have this: its fine-tune entry point has no seed field at all, so two GR00T runs on the same data are simply two different runs. With Pi0.5 you fix the seed and the run is deterministic, which turns hyperparameter changes into something you can actually attribute.
Use it properly. Hold the seed constant when you change one parameter, and vary only the seed when you want to know how much of the difference between two policies was luck. Put the number in the policy name; the run page keeps the configuration, but a name you can read in a list is faster than opening six runs to find out which was which.
Deploy the checkpoint to the arm
Before you load anything, confirm the arm is in the state the dataset assumes. Cameras in their recorded positions, same lighting, same scene reset, all six servos answering on the bus.
ay-robots devices
# SERIAL PORTS
# /dev/cu.usbmodem58FA0821911 SO-100 (6 servos responding)
# CAMERAS
# 0 Scene cam 1280x720
# 1 Wrist cam 1280x720
# Only if a joint reads visibly off from where it physically sits
ay-robots calibrateThen select the checkpoint in the client and run it against the same task string you recorded with. Expect the arm to look thoughtful. At 485 ms per action step you can watch it move, settle, and move again, and on a careful insertion that reads as competence. On a fast pick-and-place the same cadence reads as hesitation: reach, pause, reach, pause. That pattern is the inference interval, not a broken policy, and no amount of retraining removes it.
A policy that has learned a contact task will press into things by design, and a policy that has learned it badly will press into the table. Clear anything you care about out of reach, stay next to the switch, and do not leave the arm running while you fetch coffee.
Evaluate it properly
Twenty attempts with the object in different starting positions, written down as you go. Then repeat the identical protocol for the second checkpoint. A four-attempt impression of a policy that takes half a second per action step is not an evaluation, it is a mood.
Separate the two failure families before you conclude anything. If the arm reaches the right place and fumbles the contact, that is a data problem and more targeted episodes will fix it. If the arm arrives too late because the object is no longer where it was half a second earlier, that is a latency problem, and the answer is a different model or a slower task, not more demonstrations.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Loss still falling steeply at step 30000 | Your dataset is larger or more varied than the default schedule assumes | Run again with more steps and the same seed, then compare both policies on the arm under one protocol rather than judging the curves. |
| Loss barely moves after the first few hundred steps | The data did not load the way you think, or the learning rate is wrong for it | Check the dataset preview for action dimensions and camera keys before touching any hyperparameter. Schema surprises look exactly like slow convergence. |
| Out of memory on a smaller card | The job is not on the 80 GB tier | Pi0.5 needs an A100 80 GB. Batch size is already 1, so there is nothing left to trim; on 24 GB hardware use SmolVLA instead of fighting this one. |
| Jittery motion between action steps | Shaky demonstrations, or a servo problem the dataset recorded faithfully | Flow matching smooths within a predicted chunk, not across bad training data. Re-record the shaky episodes, and check whether one joint jitters on its own. |
| Gripper closes late and pushes the object away | The grasp moment is under-represented, and at this cadence one step late is half a second late | Record extra episodes that dwell on approach and close, and demonstrate the close slightly earlier than feels natural during teleoperation. |
| Job sits queued for a long time | No 80 GB card available on the spot market right now | Nothing to fix locally. The pool selects by VRAM, not by GPU name, so it will start as soon as any qualifying card frees up. |
Frequently asked questions
Is Pi0.5 the same thing as π0?▾
It is the Physical Intelligence model people write as π0.5 and type as "pi zero" or "pi 0.5". On this platform the selectable model is called Pi0.5, the trainer key is pi0, and the resulting checkpoint carries policy type pi05. Three spellings, one model.
Can I train it on my own RTX 4090?▾
No. Pi0.5 is requested on the A100 80 GB tier and there is no configuration that fits it into 24 GB, since batch size is already at 1. SmolVLA and ACT are the models that run on consumer hardware.
How many episodes before Pi0.5 is worth it over ACT?▾
Fifty is the floor where the model starts producing something evaluable, the same floor as ACT. The difference is not really about episode count: ACT is faster to train, faster at inference and cheaper, while Pi0.5 buys smoother behavior in contact. Run both on the same data and compare success rates on the arm.
Why does my arm pause between movements?▾
Because each action step takes about 485 ms. Just over two commands per second is what this model produces, so visible settling between motions is expected behavior rather than a fault. It looks purposeful on careful tasks and awkward on quick ones.
Will the same seed give me the same policy?▾
With the same dataset, the same parameters and the same seed, yes, the run is deterministic. Change a single episode in the dataset and the comparison is void, so version your datasets as carefully as you version your seeds.
Does it need LeRobot v2.1 or will v3.0 work?▾
Record v2.1. It is the format the client writes by default and the format the trainers here expect, and it keeps the same dataset usable if you later want to fine-tune GR00T, which rejects v3.0 outright.
The full tutorial chain lives under /learn.