← Blog

18 min read5 August 2026Written by Parv PatodiaPhysical Hardware Intelligence

SmolVLA, explained from the ground up

A 450-million-parameter robot policy that beats a 3.3-billion-parameter one, and only about 1.6 million of its weights are new. We took it apart on our own arms, starting from one red cube.


A red cube sits on the table in front of the arm, you type “pick up the red cube,” and from that moment six motors need an angle from somebody, thirty times a second, until the cube is in the gripper. Pixels and a sentence in, joint angles out.

That used to mean writing it out. Find the cube, estimate its pose, plan a path, hand it to a controller, then rewrite the chain when someone leaves a spoon on the table. A throws the chain out. One network reads the frames and the sentence and emits joint angles, and what a person used to specify is learned from recordings.

That works because the seeing half does not start from scratch. Trained on internet images and captions, it knows what “red” and “cube” mean before a robot is involved, so only the half that turns understanding into motion has to be taught. It is also why these models are big, and the SmolVLA paper calls them too costly to train and deploy while recordings from cheap arms pile up unused.

So SmolVLA sets a budget instead of a capability target. One GPU to train on, a consumer GPU or a CPU to run on, community data only, everything released. It lands at 450 million parameters and 87.3 on the , where π0 needs 3.3 billion and 10,000 hours of robot pretraining to reach 86.0. Every choice inside it is about what to leave out.

One convention. Anything marked measured is ours, from forward hooks on the released code. Everything else is the paper's, and where they disagree we say so.

WHAT GOES IN three camera frames 512 × 512 EACH pick up the red cube THE WRITTEN INSTRUCTION SmolVLA 450M parameters 1.6M OF THEM ARE NEW WHAT COMES OUT 50 time steps of joint angles ONE JOINT DRAWN · 1.7 SECONDS AT 30 Hz not one action, a whole chunk of them
The model does not emit one action but the next 50 at once, about 1.7 seconds of motion, and almost every choice below follows from that.

01Almost none of it is new

Two stacks. The left is a carrying what it learned from the internet, and it is , so none of that knowledge moves. The right is a smaller that only speaks joint angles, and it is the half that learns.

Counted layer by layer as the released config builds it, the model is 450,046,176 parameters, of which 99,880,992 train, and 47.3 million of the frozen half is an lm_head for turning hidden states back into words, on the GPU for nothing because the forward pass never calls it. Since the expert is a copy of the frozen architecture at smaller widths, the better question is how many weights are structurally new, with no counterpart in what was borrowed, and the answer is 1,635,152 across five small linear layers, 0.36% of the thing.

ALL 450,046,176 PARAMETERS, DRAWN TO SCALE vision text model lm_head action expert 86,433,024 204,626,880 47,308,800 98,245,840 loaded, never called connector · 11,796,480 new projections · 1,635,152 FROZEN · 350,165,184 · 77.8% trained · 99,880,992 THE EXPERT IS A COPY OF THE FROZEN ARCHITECTURE. WHAT HAS NO COUNTERPART IN IT state_projLinear(32 → 960)31,680 action_in_projLinear(32 → 720)23,760 action_out_projLinear(720 → 32)23,072 action_time_mlp_inLinear(1440 → 720)1,037,520 action_time_mlp_outLinear(720 → 720)519,120 1,635,152 0.36% of the model is machinery that did not already exist
Measured. 350,165,184 frozen plus 99,880,992 trained closes exactly on the released checkpoint.

02From a 4:3 camera to a square

Nothing runs until the frame is square, because the vision tower takes 512×512 and only that, while our cameras give 640 by 480. The obvious move is to squash it, and nobody does, because the frozen tower was never shown a squashed picture, so it would arrive as geometry the tower has never seen, a mug as an ellipse, a cube as a slab, with nothing downstream retrained to undo it. Better to waste pixels and keep the shapes honest. That reasoning is ours.

The code takes both shrink factors, 640/512 = 1.25 and 480/512 = 0.9375, and uses the larger for both axes. Fit-inside rather than fill, so nothing is cropped and the frame lands at 512 by 384.

That leaves 128 rows short of square, and they all go on top rather than split between the edges, holding plain zeros that img * 2.0 - 1.0 carries to −1, so they are black rather than a sentinel to be learned around. Measured. The processor the backbone ships with pads bottom and right, so the frozen tower reads padding on an edge its pretraining never used.

1 · WHAT THE CAMERA GIVES 640 × 480 4:3 640 ÷ 1.25 2 · BILINEAR SHRINK 512 × 384 STILL 4:3, NOTHING CROPPED 512 pad 3 · PAD THE SHORT SIDE 512 × 512 128 rows of −1, on top WHAT THAT COSTS max(640/512, 480/512) = 1.25 The larger of the two wins, so the wide side is what binds. 128 rowsshort of square 25.0%of every frame, constant 8 of 32patch rows are padding 48 of 192image tokens carry nothing and every one is paid for at full attention cost
Measured on our SO-101 rig. All three panels share one scale, so the shrink and the padding band are true sizes.

A quarter of every frame is a constant, and nothing downstream throws it away. Those 128 rows are 8 of the 32 patch rows, so 16 of that camera's 64 tokens are blank, and across three cameras that is 48 of the 192 image tokens paying full attention cost while carrying nothing. Measured.

03One frame becomes 1024 patches

A reads one flat list, so the frame, the sentence and the arm's pose all become entries in it. One entry is a .

The square frame is cut into 16×16 patches, and 512 / 16 = 32, so there are 32 × 32 = 1024 of them. One convolution turns a patch into numbers, 16×16 kernel and stride 16, and because those are equal the windows never overlap, which makes it the same as flattening each patch and multiplying by a matrix.

768 filters, each holding 3 channels × 16 × 16 = 768 weights, so a patch arrives as 768 raw values and leaves as 768 filter responses. Across the whole frame that is 3 × 512 × 512 = 786,432 numbers in and 32 × 32 × 768 = 786,432 out, the same total to the digit. It is not a summary of the picture but the whole picture rewritten into learned features, and every reduction happens after this.

ONE PATCH GOES IN 3 × 16 × 16 = 768 raw numbers RED, GREEN, BLUE 768 FILTERS each filter is also 3 × 16 × 16 and returns one number 9 OF 768 DRAWN 768 COME OUT one response per filter 24 OF 768 DRAWN WHY THE SHAPES MATTER filter bank = 768 × 768 = 589,824 weights Stride is 16 and the kernel is 16, so the windows never overlap. This convolution is exactly “flatten each patch and multiply by a matrix.” 768 numbers in, 768 numbers out. The patch embedding compresses nothing. It is one learned change of basis, and every reduction happens later. position table = (1024, 768), one row per patch exactly 1024 rows, so 512×512 is not a setting, it is a parameter shape
512 / 16 = 32, so a square frame holds exactly 1024 patches, and the learned position table has 1024 rows. No interpolation, no room to grow.

That convolution is the only part of this model that thinks in pictures. From here to the motors, everything is a list.

Then a learned position table is added on, one row per patch, shape (1024, 768). Added, element by element, the position row landing on the patch row, so a configuration flag is frozen into the shape of a weight and the 512×512 above cannot change. Hold onto the adding, because the expert faces the same problem later and solves it the other way, at more cost than anything else new.

04Twelve layers where every patch sees every patch

Those 1024 tokens go through the vision tower proper, a plain ViT twelve layers deep, and its attention is bidirectional. No causal mask, no ordering, so patch 900 reads patch 3 as freely as patch 3 reads patch 900. The right call for a picture, which has no reading direction.

By the twelfth layer a token describes not its own 16×16 square but that square in the context of the whole frame.

Width 768 splits into 12 heads of 64, so Q, K and V each come out as (B, 12, 1024, 64), and the same shapes return in the expert at other numbers. Inside one head, Q times K transposed is a 1024 × 1024 table, one number per ordered pair of patches. Divide by √64 = 8, softmax each row, multiply by V, and each patch leaves with 64 numbers blended from the whole frame. That is 1,048,576 numbers per head per layer, so twelve layers of twelve heads is about 151 million attention scores per frame, none of them stored.

WHAT GOES IN + PATCHESPOSITIONS (1024, 768)(1024, 768) added element by element EVERY PATCH READS EVERY PATCH 1024 KEYS one row per patch, one column per patch no mask, so order does not exist here INSIDE ONE HEAD width 768 splits into 12 heads of 64 Q, K, V (B, 12, 1024, 64) Q @ K^T (1024×64)(64×1024) = (1024×1024) ÷ √64 = 8, then softmax across each row probs @ V (1024×1024)(1024×64) = (1024×64) merge 12 heads → (B, 1024, 768) 1,048,576 attention weights per head, per layer 12 heads × 12 layers = 151 million, one camera ONE LAYER, TWELVE TIMES in LN self-attn + LN MLP + out The two curved wires are the residuals, so a token can pass through a layer untouched if that layer has nothing to add to it, which is what lets twelve of these stack without the signal drifting away from what came in. 12 LAYERS 011 all twelve are frozen. Not one of them gets a gradient here.
Measured from the installed config.

05A thousand patches become sixty-four

SmolVLM-2 was trained with image tiling, several crops of a frame alongside the whole frame, which helps a describer see small things. SmolVLA switches it off, so the 64 tokens below are that camera's whole budget rather than 64 per crop. Detail traded for speed.

Carrying 1024 tokens per camera is not affordable. Every 4×4 block of patches is stacked end to end into one vector of 16 × 768 = 12,288 features, and a single Linear(12288 → 960) with no bias decides what survives, leaving 64 tokens per camera, each covering a 64×64 region. That matrix is 11,796,480 weights, seven times everything structurally new put together.

This is not pooling. Nothing is averaged before the projection sees it, so spatial detail folds into the channels and a learned matrix picks from it, and a thin red edge that an average over sixteen patches would wash flat can survive.

Count them. Three cameras give 192 image tokens, the arm gives 1 and the sentence up to 48, putting the prefix at 241 and the full list at 291 once the 50 actions being written are counted.

Both are ceilings, because the sentence is padded only to the longest in the batch, and “pick up the red cube” is 6 tokens, giving a 199-token prefix. We padded to the 48-token cap for every measurement below. Measured.

ONE CAMERA FRAME PADDING, ALL −1 32 × 32 = 1024 patches, swept 4 rows at a time. Our cameras are 4:3 and the model is 1:1, so the top quarter of every frame is padding carrying nothing. fold 4×4 PATCHES → 1 TOKEN TOKENS OUT 8 × 8 = 64 per camera, each covering 64×64 pixels nothing is averaged away WHAT THE MODEL ACTUALLY READS 3 cameras × 64 · 192 image tokens the sentence · 48 language tokens the arm's pose · 1 token 241 tokens describe the world what it is writing · 50 action tokens 291 in one list, every layer
Measured on our SO-101 rig. The pose is six joint angles zero-padded to 32, and those 26 empty columns are the cross-embodiment slot, for arms with more joints than ours.

06Who is allowed to look at whom

All 291 tokens sit in one sequence, but they cannot all see each other, and that rule shapes more of the architecture than anything else.

Every token gets a block number. Images and language share block 0, the pose gets 1, and each action gets its own, 2 through 51. A token may attend to another only if that other token's block number is at most its own.

ROWS LOOK · COLUMNS ARE LOOKED AT · SHADED MEANS ALLOWED IMAGES 0–191 LANG 192–239 POSE ACTIONS 241–290 IMAGES+ LANGUAGE POSE ACTIONS Read one row across and you have everything that token is allowed to use. The prefix cannot see the actions at all. That empty rectangle top right is why its keys can be computed once and cached for the whole chunk. The staircase is the actions being strictly causal among themselves. Action 0 cannot see action 1. Drawn to scale, 291 rows and 291 columns, except the single pose row and column, widened to 12 px so they are visible at all.
Measured. Block-causal, not causal end to end. The prefix is one bidirectional blob and the actions run causally after it, with the action block exactly lower-triangular.

Two things fall out, both coming back later. The prefix never looks at the actions, so its do not depend on them, which makes it legal to compute the prefix once and reuse it across all ten denoising passes. And the actions are strictly causal among themselves, so action 30 sees action 29 and not the reverse, which Table 7 prices at 74.5 against 67.5 for looking both ways, both from a self-attention-only variant.

07Two towers, sixteen floors, twenty-four attentions

The two stacks walk forward together, and what passes between them depends on the floor. This is the part described wrongly most often, including by the paper.

On even floors there is no separate expert attention. Each tower projects its own tokens into queries, keys and values, the two sets are concatenated on the token axis, and one attention runs over the whole thing, one matrix and one softmax, then the rows split and each tower keeps its half. In training we hooked it as a (291, 291) map. Measured.

The paper calls those the floors where “action tokens attend to each other”, which leaves out the half that matters, because in the same call the actions also attend over all 241 scene tokens. Nothing fetches the scene here, it is already in the matrix.

On odd floors they come apart. The frozen tower attends over its own 241 tokens and the expert runs a separate 50×241 attention against the frozen side. Hooking it showed the expert does not re-read the frozen hidden states, it takes the keys and values the frozen tower already computed and pushes each through its own Linear(320 → 320), so it cannot change what the frozen model saw, only how it reads it.

An action token arrives 720 wide and q_proj takes it up to 960, the frozen tower's 15 heads of 64. The keys are the frozen tower's, 5 key-value heads read by 3 query heads each, which is grouped-query attention, fifteen people asking questions of five filing cabinets. Q times K transposed gives a 50 × 241 table with no column for any action token, so actions cannot see each other here, and o_proj drops the answer back to 720. Measured.

What it saves is commonly overstated. Expanding 5 key-value heads back out to 15 costs what 15 real ones would, so the saving is a third off the attention projections but an eighth off a whole layer. The cache is what matters, 14.8 MB down to 4.9 MB in bfloat16. Measured.

Eight even floors are one call each, eight odd floors are two, because the frozen tower still does its own 241×241 pass first, so a training step is eight at (291, 291), eight at (241, 241) and eight at (50, 241), which is 24. Measured by wrapping the attention function. Sixteen floors rather than the language model's 32, because Table 8 prices the top half at 1.8 points.

FROZEN · WIDTH 960 · 16 OF ITS 32 LAYERS KEPT TRAINED · WIDTH 720 the scene241 TOKENS actions50 TOKENS DRAWN AT ITS 0.75 WIDTH floor 0 · join, attend over 291, split floor 1 · 241×241 alone, then 50×241 floor 2 · join, attend over 291, split floor 3 · the expert re-reads cached keys floor 4 · … alternating, up to floor 15 8 floors each way · 24 attentions, not 16 even floor · both towers become one list and one attention runs over all 291 odd floor · they separate, and the expert reads the frozen tower one way only expert q_proj 720 → 960 · attend in the shared 15×64 head space · o_proj 960 → 720
Measured. The width multiplier takes the expert's residual stream from 960 to 720, and its feed-forward follows at 2048 rather than the tower's 2560, leaving head count and head width alone so the even floors can concatenate.

Alternating beats either alone, 85.5 against 79.0 for cross-attention only and 74.5 for self-attention only, because they do different jobs. Cross-attention is the expert's cheap look at the scene, self-attention is how action 30 learns what action 29 committed to, and without it you hold 50 independent guesses rather than one motion.

08Why it starts from noise

Put a mug on the table between the gripper and the cube. Left around it works and right works, and if you train a model to predict the one correct trajectory under a loss that averages, what it learns from seeing both is the average of the two, straight through the mug. It learned exactly what was asked, and what was asked was wrong.

TWO GOOD DEMONSTRATIONS MUG START CUBE both reach the cube, neither touches the mug, both are correct AVERAGE THEM halfway between above and below is exactly where the mug is SAMPLE INSTEAD one whole route at a time, committed to from end to end
The average of two safe routes is an unsafe route, so being able to say “either of these, pick one” is the difference between working and broken. Swapping the averaging loss for is worth 5 points on LIBERO, 80.25 against 75.25.

So the expert never predicts the answer directly. Training mixes the true actions with noise, stands at a random point on the line between them, and asks only which direction the answer lies in.

time = Beta(1.5, 1.0).sample() * 0.999 + 0.001 x_t = time·noise + (1 - time)·actions u_t = noise - actions loss = mse(u_t, model(x_t, time))

Because the thing predicted is noise − actions, the action term never drops out. Hold that against a plain denoiser trained to predict noise alone, where at the noisy end the input very nearly is the noise, so predicting it collapses into copying the input and the loss stops measuring anything. Here the error floors at the action-prediction error instead.

And the sampling tilts towards that end. Beta(1.5, 1.0) has density proportional to √t and a mean of 0.6, with 28.5% of draws in the top fifth, so most of the training budget goes where the loss still says something.

09The clock the expert reads

The expert cannot point anywhere useful without knowing how far along it is, because the right direction from a nearly-clean chunk is not the right direction from pure noise. That number is the clock, and everything below is the code's time, 1 at pure noise down to 0 at the answer, the paper's τ upside down.

One number is not much to condition on, so it is widened into 720 values, 360 sines and 360 cosines, periods running 0.004 up to 4.000, each 1.0194 times the one before.

time · ONE NUMBER, 0 AT THE ANSWER TO 1 AT PURE NOISE 01 THE 10 SAMPLING STEPS period 4.0SLOWEST OF 360 a quarter of a cycle never wraps, so it reads as a coarse hand period 0.4MIDDLE 2.5 cycles period 0.04NEAR THE FAST END 25 cycles. The true fastest is 0.004, which is 250 and undrawable. 360 sines + 360 cosines = 720 · periods 0.004 → 4.000, each 1.0194× the last · ‖emb‖ = √360 = 18.9737 at every time
Measured. The slowest period, 4.0, is longer than the whole range of time, so it never wraps. The fastest, 0.004, is finer than the 0.1 spacing of the ten steps. Both ends are chosen, not inherited.

It is sharper than you would guess. Measured, the clock at 0.50 and 0.51 has cosine similarity 0.5169, falling to 0.2842 by 0.55, so neighbouring steps do not look alike. Its length is √360 at every value, so it changes direction only, never magnitude.

In section 03 the vision tower told 1024 patch tokens where they sat by adding a position row onto each patch row, free. Telling 50 action tokens what time it is goes the other way. The 720-number clock is concatenated, not added.

action_in_proj takes the noisy chunk up to (B, 50, 720), the clock arrives as (B, 720) stretched across all fifty positions, and concatenating makes (B, 50, 1440), which two layers with a SiLU between them bring back to 720. Every token then carries the same clock and its own content side by side rather than mixed.

WHAT IT DOES · CONCATENATE, THEN FUSE action · 720 clock · 720 1440 Linear(1440→720)SiLU, Linear(720→720) fused · 720 1,556,640 weights 95.2% of everything new in the whole model WHAT ADDING WOULD HAVE DONE action · 720 clock · 720 + sum · 720 0 extra weights but which step a token is and how noisy the chunk is now have to share the same 720 directions
Measured. The other three new projections come to 78,512 weights between them, next to nothing.

Adding would have been free. Concatenating costs Linear(1440 → 720) and Linear(720 → 720), 1,556,640 weights, 95.2% of everything structurally new in SmolVLA. Measured.

What the money buys is separability. Side by side, the MLP can learn any interaction between a token's place in the chunk and how noisy the chunk is. Adding folds both into the same 720 directions, where a late step in a clean chunk gets hard to tell from an early step in a noisy one. The tower gets away with adding because a patch's position never changes.

Coming back out is cheaper. action_out_proj drops each token to 32 numbers, of which only the first 6 mean anything on a six-joint SO-101. The other 26 are the cross-embodiment slot, computed on every token of every step and dropped. Measured.

10Ten steps, and why ten is exact

At generation time the expert starts from pure noise and takes ten equal Euler steps to the actions.

FLOW MATCHING · THE PATH IS STRAIGHT BY CONSTRUCTION NOISEACTIONS the direction never changes, so ten equal steps land exactly on the answer two steps would land there too, which is why the step count is close to free A CURVED PATH · WHAT DIFFUSION MODELS WALK TRUE END lands here Each step is a straight line, so on a curve it cuts the corner, and the next step starts from the wrong place. Staying on the path means taking more steps, each one smaller.
Feed the true velocity field into the sampler and measure the distance to the answer. Halfway sits at exactly half the starting distance, the end lands on zero, and two steps arrive where ten do to within 6e−06. Measured, for any starting noise.

This is what the straight path buys. Ten and two steps land in the same place, so the step count neither buys nor costs accuracy, and any error in a real run is the model pointing the wrong way, not the integrator. A curved path would cut the corner by an amount that depends on the count.

11Where the speed actually comes from

Inference is two passes that look nothing like each other.

PASS 1 · RUNS ONCE PER CHUNK 241 prefix tokens → 16 layers every layer self-attends, 241×241 the vision tower runs here, exactly once key/value cache 16 layers × 2 × (241, 5, 64) = 4.9 MB bf16 this is what the white rectangle in the mask bought PASS 2 · RUNS TEN TIMES 50 action tokens → 16 layers 8 layers 50×291, 8 layers 50×241 the prefix is read from cache, never recomputed ×10 only 50 tokens ever move 50 of 291 · 17% of the sequence, ten times over ten denoising steps cost far less than ten forward passes
Measured. The vision tower and the 241-token prefix run once for the whole chunk. Only the small side runs ten times.

The prefix is 241 of the 291 tokens, and after the sixteen floors it is kept as 16 layers of two tensors of shape (241, 5, 64), 4.9 MB in bfloat16. Everything after reads it instead of recomputing, so the ten sampling passes each move 50 tokens rather than 291, and the chunk costs 16 + 10 × 16 = 176 attention calls against 24 in training. Measured.

12How long can it act blind

Predicting 50 actions is cheap. Executing all 50 before looking again is not, because the policy sees one frame with no history and no hidden state carried over, so a frame from 49 steps ago is all it has to go on. Drag the slider.

ONE PREDICTED CHUNK · 50 STEPS acted on a fresh look acted blind, on a frame this many steps old LIBERO AVERAGE, FROM THE PAPER 80.3
1 step · 80.3
Only the settings the paper measured are selectable. Going from 1 to 50 costs 28.5 points.

13So stop making it wait

If acting blind is expensive and thinking is slow, the compromise is to act, stop, think, act again, and the stopping is the waste. So SmolVLA separates the robot from the model. The arm drains a queue of actions and ships the current frame to a server when the queue runs low, then keeps moving while the server thinks, which puts the thinking underneath the motion rather than in the gaps.

SYNCHRONOUS · THE ARM WAITS thinking, arm stopped SAME TASK, AVERAGE OF 10 TRIALS 13.75 s · 9 cycles in 60 s ASYNCHRONOUS · THE ARM NEVER STOPS the server thinks while the queue keeps draining both tracks run for the same 60 seconds SAME MODEL, SAME SUCCESS RATE 9.7 s · 19 cycles in 60 s
Success rates were comparable in both modes. What changed was throughput, roughly 30% faster per task and more than twice the cycles inside a fixed minute.

14What it was trained on

481 community datasets from Hugging Face, 22,900 episodes, 10.6 million frames. The paper's own limitations put OpenVLA at around a million trajectories against this 23k, so it is roughly forty times less data.

The data was messy the way community data always is. Task descriptions were missing or wrong, so a vision-language model rewrote them, and camera names disagreed, so viewpoints had to be mapped onto a shared scheme. Neither is a research contribution and both had to happen first.

15Read the tables, not the captions

Three things in the paper do not line up with themselves, and checking beats trusting any summary, including this one.

Table 9 tests four expert widths and its caption says larger capacities do better, while its own rows say ×0.50 is smaller and scores 2.8 points higher than the ×0.75 that shipped. Table 11 says feeding the pose token to the frozen tower beats feeding it to the expert, with no qualification, when its own self-attention rows go the other way, 53.3 against 74.8.

The plainest one is not an ablation. Table 1 lists 22.9K episodes and 10.6M frames, then its own caption says the set stands “at ~10M episodes”, taking the frame count and putting the wrong noun on it.

The shipped choices might still be right, because these ablations are all trained from scratch on LIBERO with no robotics pretraining, a different setting from the released model. But anyone who reads the captions and skips the tables gets a tidier story than the numbers support.

The two ablations whose captions contradict their own rows. LIBERO average, trained from scratch with the backbone frozen. Shipped choice in red. Tables 9 and 11.
OptionAvg
Expert width
× 1.0082.3
× 0.7577.5
× 0.5080.3
× 0.2573.8
Pose token goes to
frozen tower, cross-attn80.3
action expert, cross-attn73.3
frozen tower, self-attn53.3
action expert, self-attn74.8

16The whole thing on one page

Everything above, in the order it happens.

1 SEE WHAT THE ARM IS GIVEN three cameras 640 × 480 AT 30 Hz pick up the red cube the instruction 6 TOKENS FOR THIS ONE the arm's own pose 6 JOINT ANGLES 25.0% of every frame is padding once 4:3 is made square 2 TOKENISE ONE FLAT LIST OF TOKENS 512 × 512 THE SQUARED FRAME 1024 PATCHES, ONE 16×16 CONV 1024 AFTER 12 ViT LAYERS 64 FOLDED 4×4, PER CAMERA × 3 = 192 IMAGE TOKENS 192 image + up to 48 language + 1 pose IMAGES AND LANGUAGE ARE BOTH SCALED BY √960, THE POSE IS NOT 241 tokens at most in the prefix, and 291 once the 50 being written are added 3 THINK SIXTEEN SHARED FLOORS frozen VLM 960 WIDE · 16 OF ITS 32 LAYERS 350,165,184 WEIGHTS, 0 TRAINED action expert 720 WIDE · 16 LAYERS 99,880,992 TRAINED 8 even floors · one attention, both towers in one matrix frozen · 241 × 241 expert · 50 × 241 8 ODD FLOORS · THE EXPERT READS THE FROZEN CACHE VIA Linear(320 → 320) 24 attention calls on a training step, and 176 across a whole chunk at inference 4 DENOISE NOISE TO ACTIONS IN TEN clock · 720 numbers concatenated onto every action token NOISE ACTIONS ten equal steps, and two steps land where ten do PREFIX BUILT ONCE AND CACHED AT 4.9 MB, ONLY THESE 50 TOKENS REPEAT 10 Euler steps, and only the small half of the model walks them 5 ACT DRAIN, THEN REFILL 50 × 6 joint angles, 1.7 seconds of motion at 30 Hz THE ARM REFILLS THE QUEUE BEFORE IT EMPTIES, SO IT NEVER STOPS TO THINK 50 × 6 numbers, then it looks at the world again
Read top to bottom. Bands one to three run once per observation, band four ten times.

Taking it apart mostly taught us how little of it is new. Flow matching and the action expert come from π0, the frozen backbone is SmolVLM-2 off the shelf, and action chunking goes back to ACT in 2023. What SmolVLA adds is decisions about what to leave out, and they cover most of the distance from 3.3 billion parameters to 450 million.

Sources

  1. Shukor, Aubakirova, Capuano et al., SmolVLA: A vision-language-action model for affordable and efficient robotics, arXiv:2506.01844v1, June 2025the paper's own figures, including 450M parameters with ~100M in the action expert, the first 16 of the language model's layers, 64 visual tokens per frame, chunk size 50, 10 flow-matching steps, expert width 0.75×d, Tables 6 to 13, and the async timings of 9.7 s against 13.75 s with 19 pick-and-place cycles against 9 in a 60-second window
  2. Phi, SmolVLA: a frozen VLM with an action expert bolted onevery number marked measured: the ledger closing at 450,046,176 with 99,880,992 trainable and 1,635,152 structurally new; the 47.3M dead lm_head; the 480×640 resize landing at 512×384 with 128 padded rows and 25.0% dead pixels; the (768, 3, 16, 16) patch convolution at 589,824 weights; the (1024, 768) position table; the 241-token prefix and 291-token sequence at the 48-token language cap, and the 199-token prefix our own instruction really gives; the block-causal mask; the 720-number clock with periods 0.004 to 4.000 and norm √360; the 1,556,640-weight time-fusion MLP at 95.2% of all new weights; 24 attention calls across 16 layers; the expert re-projecting cached keys through Linear(320→320); the 4.9 MB bf16 cache; and Euler integration landing at 0.0000
  3. Black et al., π0: A Vision-Language-Action Flow Model for General Robot Control, 2024the 3.3B model SmolVLA is measured against, pretrained on 10,000 hours of robot data; origin of the flow-matching action expert and the Beta-distributed noise level
  4. Zhao et al., Learning Fine-Grained Bimanual Manipulation with Low-Cost Hardware (ACT), RSS 2023action chunking, and the single-task baseline in the paper's real-world tables
  5. Marafioti et al., SmolVLM2, Hugging Face, 2025the frozen backbone, a SigLIP vision encoder feeding a SmolLM2 decoder
  6. Cadene et al., LeRobotthe implementation everything was measured against, lerobot/policies/smolvla/ at version 0.6.0