Skip to the walkthrough
FixTheRobot Home / VLA / Paper guides / AsyncVLA

VLA · Paper guide

AsyncVLA: Asynchronous Flow Matching for Vision-Language-Action Models

A robot policy that checks its own action plan and redoes only the shaky parts, explained through the questions an engineer would ask.

  • Jiang, Cheng, Ding, Gao, Qi
  • arXiv:2511.14148 (v2)
  • Overview: about 4 minutes
  • Full guide: about 45 minutes

This is a guide to the AsyncVLA paper, not a sentence-by-sentence paraphrase. Part A is a 4-minute overview. Parts B to D explain the architecture, the training and the experiments one idea at a time. Equations and code are folded away in Part E, and Part F is a critical review of the paper’s numbers and claims. It builds on the flow-matching generation described in the π0 guide.

Start with the overview Jump to the critical review

How to use this page

  1. In a hurry: read Part A (about 4 minutes).
  2. To understand the method: add Parts B to D. Each idea follows the same pattern: intuition, the problem it solves, how it works, an example, then technical details and where to find them in the paper.
  3. To check or rebuild it: open the folded sections (equations, shapes, hyperparameters, timings, runnable examples) and read Part F.

Open the paper (arXiv:2511.14148) beside this page; section, figure, table and equation references are to it. We paraphrase and never reproduce its text. Statements are labelled so you can tell them apart: Reported by the paper, Our calculation from the paper’s numbers, and Our interpretation. Runnable examples are marked Toy illustration when they are our own code and never present results from the paper.

Part A · about 4 minutes

Start here: the paper at a glance

The problem

Many recent robot models (vision-language-action, or VLA, models: they take images and an instruction and output robot actions) produce a short plan of motor commands, an action chunk, by flow matching: start from random noise and clean it up in a fixed number of equal steps. The authors call this synchronous flow matching because every action in the chunk is cleaned up together, on the same schedule, with no way to go back. Their argument is that one badly generated action can then spoil a long task, because nothing checks the plan before the robot acts.

The main contribution

  1. A second, selective pass. After the usual first draft, a small network scores how trustworthy each action in the chunk is. The doubtful ones are regenerated while the trustworthy ones are held fixed as context. This is asynchronous flow matching: during the second pass different actions are at different stages of cleaning.[1]
  2. A confidence rater, the small network that does the scoring, trained with labels made from the draft’s own errors.
  3. One model for both passes. A training procedure that teaches a single network to do the full draft and the partial regeneration.

How the model works, in one paragraph

The model reads camera images, the robot’s state and the instruction, and writes a draft chunk in ten denoising steps. The confidence rater gives every action in the draft a score between 0 and 1. Actions scoring below 0.5 are thrown back to noise; the rest are kept. Ten more denoising steps then rewrite only the thrown-back actions, looking at the kept ones as context, and the result is sent to the robot.

What it learns from

The backbone is Qwen2.5-VL-3B-Instruct, a pretrained vision-language model. The whole system, with the action head and the rater, has 4.08 billion parameters. It is pre-trained on a subset of the Open X-Embodiment robot datasets (eight datasets, Table 8) and then fine-tuned for each benchmark and for a real AgileX PiPER robot arm.

What the paper reports

Success rates as printed in the paper:

Headline results as printed.
TestAsyncVLABest comparison in the same table
LIBERO, 4 suites, 500 trials each (Table 1)97.4%dVLA 96.4%, π0.5 96.9%
WidowX benchmark in SimplerEnv (Table 2)70.8%UD-VLA 62.5%, π0.5 57.1%
Google Robot, visual matching / variant aggregation (Table 3)75.3% / 64.3%π0 71.4% / 54.7%
Real robot, four tasks, 50 trials each (Table 5)87.0%π0.5 77.0%, π0 65.0%
WidowX ablation: same model without the second pass (Table 4)47.9% against 70.8%no second pass

What to keep in mind

  • Several gaps are small. On LIBERO the margin over the next model is about one point, and on the simulated WidowX tasks the percentages imply only 24 episodes per task, so the intervals are wide (Part F).
  • The evidence that the model really “self-corrects” is one hand-picked example plus the ablations; the paper does not report how many actions get flagged or how often the second pass fixes a failure.
  • The paper does not state the action-chunk length or the real-world training protocol.
  • The authors name their own limits: the confidence labels are relative within each chunk, and the idea is only tested on robot actions.

If you read nothing else: AsyncVLA adds a draft-rate-redo loop to a flow-matching robot policy: write the whole action chunk, find the shaky actions, and regenerate only those with the solid ones as context. Its ablations suggest the second pass helps a lot, but the experiments are small enough that the size of the gain, and how much comes from the confidence rater itself, is uncertain.

Check your understanding: Why does the second pass keep the confident actions fixed instead of regenerating the whole chunk again?

The confident actions are the context that makes the regenerated ones better: the model can see what comes before and after the shaky action. Regenerating everything would throw that context away and risk changing actions that were already fine.

Part B

Understand the architecture

Follow one action chunk through the system: a robot arm is told “pour water into the bowl”. Plain words first, technical names second; equations wait until Part E. It helps to have read the π0 guide, whose flow-matching generation this paper builds on.

AsyncVLA data flow Camera images, robot state and an instruction go to a pretrained vision-language backbone. Stage 1 writes a draft action chunk from noise in ten steps. A confidence rater scores every action in the draft, and actions scoring below 0.5 are flagged. Stage 2 regenerates only the flagged actions from noise in ten more steps, keeping the others fixed as context and reusing the cached image and text computation. The result is sent to the robot. Images + robot statewhat the robot sees and feels Instruction“pour water into the bowl” Vision-language backbone (Qwen2.5-VL, 3 billion)reads the images, the instruction and the action tokenstogether, with full attention among the action tokens Stage 1 · Draftevery action token starts as noise; 10 denoising stepsgive a complete draft chunk Confidence ratera small 4-layer transformer scores everyaction token in the draft from 0 to 1 Flag the doubtful tokensscore below 0.5: regenerate; otherwise keep Stage 2 · Refineflagged tokens restart from noise, kept tokens stay fixed10 steps; reuses the cached image and text computation Final action chunksent to the robot
The data flow. Blue is the pretrained backbone, orange the second (refine) pass that gives the method its name, dashed grey the draft and the rating steps. Redrawn by us from the paper’s Figure 1 and Section 3.
  1. Inputs and tokens
  2. Draft
  3. Confidence rater
  4. Refine

1. What goes in, and what an “action token” is

Intuition
The robot looks, feels its own joints and reads the instruction, then plans a short stretch of movement made of many small steps.
How it works
The observation is the camera images (several views) plus the robot’s state at the current time; the instruction is text. The backbone is Qwen2.5-VL-3B-Instruct, a pretrained vision-language model (VLM), to which the authors add a flow-matching head for continuous actions. The model outputs an action chunk of L consecutive actions. Each action in the chunk is treated as one token, a slot in the sequence: the sequence contains text tokens, image-patch tokens, a robot-state token and partially cleaned action tokens.
Example
Illustration, not from the paper A single arm with a front camera and a wrist camera is told “pour water into the bowl”. The chunk is a short sequence of arm and gripper commands.
Technical details
The paper never states the value of L. The action tokens are projected to the backbone’s width and appended to the vision-language hidden states, and attention among the action tokens is full (each action sees all the others), following CoT-VLA.
Evidence in the paper
§3.1 · §4.1 · Figure 1
Check your understanding: The chunk length L is not given in the paper. Does that stop you following the method?

No: the method works for any chunk length. It does mean a reader cannot reproduce the exact setting from the paper alone (the released code would say).

2. Stage 1: the draft (synchronous flow matching)

Intuition
A first sketch of the whole movement, drawn in one go.
The problem it solves
The model needs a complete first plan before it can judge which parts of the plan are shaky.
How it works
All L action tokens start as random noise and are cleaned up together over 10 steps on one shared schedule, from noise (time τ = 1) to clean actions (τ = 0). This is the usual flow-matching generation used by π0 and similar models, called synchronous flow matching (SFM) in this paper because every token is at the same stage at every step. The pass also builds the key-value (KV) cache: the stored computation for the image and text tokens.
Example
Illustration, not from the paper The draft for the pouring chunk might tilt the cup correctly, but release the cup too early near the end.
Why the authors chose it
It is the baseline that earlier models stop at. Here it only provides the first draft; the authors’ claim is that checking and redoing parts of it improves success.
Technical details
Time runs from 1 to 0 in this paper, the opposite of the π0 and GR00T N1 papers (where 0 is noise). The notation is consistent in this paper (checked in Parts C and E). The draft costs most of the time: 83.2 of 95.9 ms.
Evidence in the paper
§3.1 · Figure 1(a) · Appendix B and E.2
Check your understanding: Why is the first stage called “synchronous”?

Every action token has the same noise level at every step, and all are updated at every step. The second stage is “asynchronous” because different tokens then have different noise levels in the same pass.

3. The confidence rater: which actions look shaky?

Intuition
A proofreader who reads the draft next to the original scene and puts a mark beside the actions that look wrong.
The problem it solves
Flow-matching actions are continuous numbers, so there is no table of word probabilities to read confidence from, as a language model has.
How it works
A separate small network takes the backbone’s final hidden states for the image and text tokens together with the draft actions (projected into the same space) and runs them through four transformer layers with full attention, so it can look at actions both before and after the one being rated. A final linear layer and a sigmoid give each action token a score between 0 and 1. Every token scoring below a threshold T = 0.5 is flagged for regeneration.
Example
Illustration, not from the paper In the pouring chunk, the rater gives the early “release” action a score of 0.37 and the neighbouring actions about 0.9, so only the release is flagged.
Why the authors chose it
A fixed threshold flags as many or as few tokens as seem doubtful, which the authors prefer to choosing a fixed number (top-K). The paper’s Figure 2 shows such a case on a LIBERO-Long task with a score of 0.37.
Technical details
The rater has 308 million parameters, 7.56% of the 4.08 billion in the whole model. Its feed-forward width is 6,144 and it has 32 attention heads. How it is trained is in Part C.
Evidence in the paper
§3.2 · Appendix E.3 · Figure 2
Check your understanding: Why not just use the model’s own probabilities as confidence?

The model outputs continuous velocities, not a probability for each token, so there are no logits to read. That is why a separate rater is trained.

4. Stage 2: asynchronous refinement

Intuition
Rewrite only the doubtful sentences, while reading the sentences you decided to keep.
The problem it solves
A flagged action should be regenerated using the trustworthy neighbouring actions as context, not from nothing.
How it works
This pass is called asynchronous flow matching (AFM). Flagged tokens go back to pure noise (τ = 1); unflagged tokens keep their draft values. For ten steps the model predicts a velocity for the whole chunk but only the flagged tokens are moved. Because the unflagged tokens stay fixed, the model sees the plan around the gap. Each token has its own time: kept tokens count as already clean (time 0), flagged ones run from 1 to 0. The first stage is just the special case where every token is flagged, so one model does both.
Example
Illustration, not from the paper The flagged “release” action is regenerated while the neighbouring “keep holding the cup” actions stay fixed, so the new action is consistent with them.
Why the authors chose it
The authors argue that reusing the draft’s context lets the model correct large errors without disturbing actions that were fine. The cached image and text computation from stage 1 is reused, so stage 2 takes only 10.1 ms.
Technical details
An “asynchronous time embedding” gives each token its own time value: the model turns each token’s time into a vector and mixes it with the token’s action. In the toy below the model is replaced by a simple stand-in so that the loop is visible; it is not the paper’s network.
Run the example: one asynchronous refinement, step by step
Toy illustration

What each part does

  1. Make a smooth plan of 8 actions and a draft with one wrong token.
  2. Flag that token, keep the others, and start the flagged one from noise (the paper’s Algorithm 1).
  3. Use a stand-in denoiser that predicts a token from its neighbours, and run ten steps that move only the flagged token.
import numpy as np
rng = np.random.default_rng(0)

# A toy plan: 8 actions that rise smoothly (one number per action, for simplicity).
truth = 0.1 * np.arange(1, 9)
draft = truth.copy()
draft[3] += 0.5                                   # the first-round (SFM) draft has one bad token

m = np.array([0, 0, 0, 1, 0, 0, 0, 0])           # the rater flagged token 3 (1 = regenerate)

def toy_target(a, i):
    # Stand-in for the trained model: it "knows" a smooth plan, so it predicts the average of the neighbours.
    # (The real model is a neural network; this stand-in only shows how the loop uses the context.)
    return 0.5 * (a[i - 1] + a[i + 1])

def toy_velocity(a_hat, tau):
    # For a straight noise-to-data path, the exact velocity is (x - target) / tau, with tau running 1 -> 0.
    v = np.zeros_like(a_hat)
    for i in np.flatnonzero(m):
        v[i] = (a_hat[i] - toy_target(a_hat, i)) / tau
    return v

# Algorithm 1: unmasked tokens keep their draft values; masked tokens start from noise (tau = 1).
a_hat = np.where(m == 0, draft, rng.normal(size=8))
delta, tau = 0.1, 1.0
while tau > 1e-9:
    v = toy_velocity(a_hat, tau)
    a_hat = a_hat - delta * v * m                 # Equation 1: only masked tokens move
    tau = max(0.0, tau - delta)

print("truth :", np.round(truth, 2).tolist())
print("draft :", np.round(draft, 2).tolist())
print("refined:", np.round(a_hat, 2).tolist())
print("draft error at the flagged token:  ", round(abs(draft[3] - truth[3]), 3))
print("refined error at the flagged token:", round(abs(a_hat[3] - truth[3]), 3))
print("unflagged tokens unchanged:", bool(np.array_equal(a_hat[m == 0], draft[m == 0])))

Output:

truth : [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]
draft : [0.1, 0.2, 0.3, 0.9, 0.5, 0.6, 0.7, 0.8]
refined: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]
draft error at the flagged token:   0.5
refined error at the flagged token: 0.0
unflagged tokens unchanged: True

The stand-in knows the plan is smooth, which the real network learns from data. The example shows only how the loop uses the context and leaves the other tokens alone.

Evidence in the paper
§3.1 · Figure 1(b,c) · Algorithm 1 (Appendix C) · Equations 1 and 2
Check your understanding: What changes between the draft pass and the refine pass for a token that was not flagged?

Nothing: its value is held fixed at the draft, and it only acts as context. Only the flagged tokens are re-noised and updated.

Part C

Understand the training

Three things have to be learned: how to draft and refine with one model, how to rate confidence, and the general robot skills the model starts from.

Unified training: one model for both passes

Intuition
Practise both writing a whole page from scratch and filling in a few blanks on a page that is already mostly written.
The problem it solves
The refine pass gives the model a sequence where some actions are already clean and others are noisy, which is a situation a model trained only for the draft pass has never seen.
How it works
For each training example the authors choose how much to mask: a probability y between 0 and 1 is drawn, then each action token is masked independently with that probability. Masked tokens follow the usual noise path with a time τ drawn from a Beta(1.5, 1) distribution, which favours noisier times (near 1). Unmasked tokens are the context: they get a small amount of Gaussian noise (standard deviation 0.05) so that they resemble the imperfect drafts seen at test time. The loss is the velocity error on the masked tokens only. When every token is masked this is the ordinary draft training.
Example
Illustration, not from the paper One training chunk keeps 6 of 8 actions as slightly noisy context and trains the model to rebuild the other 2; another masks all 8.
Why the authors chose it
This lets a single network serve both passes and, the authors argue, acts as data augmentation because each chunk is seen with many different masks. Without it, the ablation collapses (7.3% on WidowX).
Technical details
The context noise addresses a mismatch: in training the context would otherwise be clean ground truth, while at test time it is the model’s own imperfect draft.
Run the example: time runs backwards: is the sign convention consistent?
Toy illustration

What each part does

  1. Build the noisy action at time τ as the paper writes it (τ = 1 is noise, τ = 0 is clean).
  2. Check that the path’s slope equals the target velocity n − a, and that ten Euler steps with the exact velocity return the clean chunk.
  3. Sample τ from Beta(1.5, 1) to see which noise levels training favours.
import numpy as np
rng = np.random.default_rng(0)

# AsyncVLA runs time backwards: tau = 1 is noise, tau = 0 is the clean action (Figure 1).
# Equation 6:  a_hat(tau) = a - tau * (a - n)      and the target velocity u = n - a  (Equation 4).
# Equation 1:  a_hat(tau - delta) = a_hat(tau) - delta * V.
a = rng.normal(size=5)                # a clean action chunk (toy numbers)
n = rng.normal(size=5)                # noise

def path(tau):
    return a - tau * (a - n)

print("tau = 1 gives the noise:      ", bool(np.allclose(path(1.0), n)))
print("tau = 0 gives the clean chunk:", bool(np.allclose(path(0.0), a)))

# Slope of the path as tau grows, compared with the target velocity u = n - a.
d = 1e-6
slope = (path(0.5 + d) - path(0.5)) / d
print("path slope equals u = n - a:", bool(np.allclose(slope, n - a, atol=1e-4)))

# Walk with the exact velocity u from tau = 1 to 0 in 10 Euler steps (Equation 1 with V = u).
x, delta = n.copy(), 0.1
for _ in range(10):
    x = x - delta * (n - a)
print("10 Euler steps with the exact velocity reach the clean chunk:", bool(np.allclose(x, a)))

# The time distribution: tau ~ Beta(1.5, 1) puts more weight near 1 (the noisy end).
tau = rng.beta(1.5, 1.0, 200000)
print("mean tau:", round(float(tau.mean()), 3), "(exact 0.6); share of samples above 0.5:", round(float(np.mean(tau > 0.5)), 3), "(exact", round(1 - 0.5 ** 1.5, 3), ")")

Output:

tau = 1 gives the noise:       True
tau = 0 gives the clean chunk: True
path slope equals u = n - a: True
10 Euler steps with the exact velocity reach the clean chunk: True
mean tau: 0.6 (exact 0.6); share of samples above 0.5: 0.647 (exact 0.646 )

A check of the mathematics only. Unlike the π0 and GR00T N1 papers, the signs here agree with each other.

Evidence in the paper
§3.3 · Equations 4 to 6 · Algorithm 2 (Appendix C) · Table 4 (“w/o unified training”)
Check your understanding: Why add noise to the context tokens during training?

At test time the context is the model’s own draft, which has errors. Training on slightly perturbed context makes the model robust to that, instead of expecting perfectly clean neighbours.

Training the confidence rater

Intuition
Teach the proofreader by showing it many drafts together with how wrong each action turned out to be.
The problem it solves
There is no label that says “this action is shaky”. Only the actions’ errors against the demonstrations are known.
How it works
After the main model is trained, it is frozen. For each training chunk the model writes a draft and the error (mean squared error) of every draft action against the demonstration is measured. These errors are turned into soft labels between 0.01 and 0.99 by min-max scaling within the chunk (the lowest error gets about 0.99, the highest about 0.01), and the rater is trained to predict them with a squared-error loss.
Example
Illustration, not from the paper If the draft’s errors are tiny for seven actions and large for the eighth, the labels are about 0.97 to 0.99 for the seven and about 0.01 for the eighth.
Why the authors chose it
The authors compare with simply labelling every action in a successful trajectory 1 and in a failed one 0 (“task success indicator”, TSI) and report that their error-based labels work better (70.8% against 64.6% on WidowX), because TSI gives the same coarse label to every action.
Technical details
The scaling is relative to the chunk: the score says which actions are worse than their neighbours, not how bad they are in absolute terms. The authors point out the consequence themselves as a limitation (Appendix A.1), and the example shows a second one.
Run the example: confidence labels and the mask
Toy illustration

What each part does

  1. Write Equation 7 with the paper’s α = 0.01 and β = 0.98, and the mask rule with threshold T.
  2. Try three made-up chunks: one clear outlier, all tokens accurate, all tokens inaccurate.
  3. Print labels and the mask for T = 0.25, 0.5 and 0.75.
import numpy as np

alpha, beta, eps = 0.01, 0.98, 1e-6        # values from Section 4.1

def labels(errors):
    # Equation 7: the token with the smallest error gets about 0.99, the largest about 0.01.
    e = np.asarray(errors, dtype=float)
    return 1 - alpha - beta * (e - e.min()) / (e.max() - e.min() + eps)

def mask(p, threshold):
    # Equation 3: mask (regenerate) every token whose confidence is below the threshold.
    return (p < threshold).astype(int)

chunks = {
    "one clear outlier":     [0.002, 0.003, 0.002, 0.060, 0.003, 0.002, 0.003, 0.002],
    "all tokens accurate":   [0.0020, 0.0021, 0.0022, 0.0023, 0.0020, 0.0024, 0.0022, 0.0021],
    "all tokens inaccurate": [0.50, 0.52, 0.55, 0.51, 0.53, 0.56, 0.52, 0.54],
}

for name, errors in chunks.items():
    p = labels(errors)
    print(name)
    print("   token errors:", errors)
    print("   labels      :", np.round(p, 2).tolist())
    for T in (0.25, 0.5, 0.75):
        m = mask(p, T)
        print(f"   T = {T:<4} mask {m.tolist()}  ({m.sum()} of {len(m)} regenerated)")
    print()
print("The labels only say which tokens are worse than the others in the SAME chunk.")

Output:

one clear outlier
   token errors: [0.002, 0.003, 0.002, 0.06, 0.003, 0.002, 0.003, 0.002]
   labels      : [0.99, 0.97, 0.99, 0.01, 0.97, 0.99, 0.97, 0.99]
   T = 0.25 mask [0, 0, 0, 1, 0, 0, 0, 0]  (1 of 8 regenerated)
   T = 0.5  mask [0, 0, 0, 1, 0, 0, 0, 0]  (1 of 8 regenerated)
   T = 0.75 mask [0, 0, 0, 1, 0, 0, 0, 0]  (1 of 8 regenerated)

all tokens accurate
   token errors: [0.002, 0.0021, 0.0022, 0.0023, 0.002, 0.0024, 0.0022, 0.0021]
   labels      : [0.99, 0.75, 0.5, 0.26, 0.99, 0.01, 0.5, 0.75]
   T = 0.25 mask [0, 0, 0, 0, 0, 1, 0, 0]  (1 of 8 regenerated)
   T = 0.5  mask [0, 0, 0, 1, 0, 1, 0, 0]  (2 of 8 regenerated)
   T = 0.75 mask [0, 1, 1, 1, 0, 1, 1, 1]  (6 of 8 regenerated)

all tokens inaccurate
   token errors: [0.5, 0.52, 0.55, 0.51, 0.53, 0.56, 0.52, 0.54]
   labels      : [0.99, 0.66, 0.17, 0.83, 0.5, 0.01, 0.66, 0.34]
   T = 0.25 mask [0, 0, 1, 0, 0, 1, 0, 0]  (2 of 8 regenerated)
   T = 0.5  mask [0, 0, 1, 0, 0, 1, 0, 1]  (3 of 8 regenerated)
   T = 0.75 mask [0, 1, 1, 0, 1, 1, 1, 1]  (6 of 8 regenerated)

The labels only say which tokens are worse than the others in the SAME chunk.

Made-up errors. The point is what the relative labels can and cannot express.

Evidence in the paper
§3.3 “Training confidence rater” · Equation 7 · Table 4 (“w/ TSI labeling”) · Appendix A.1, D.1 and Table 9
Check your understanding: If the draft is bad everywhere, what does the relative labelling do?

It still gives the least-bad action a high score, so it would be kept as context even though its absolute error is large. The authors list this as a limitation and propose absolute calibration as future work.

Pre-training and fine-tuning

Intuition
Learn general manipulation from many robots first, then specialise on the benchmark or robot at hand.
The problem it solves
Starting from only a vision-language model, the system has never seen robot actions; each benchmark has limited data.
How it works
The system is pre-trained on a subset of Open X-Embodiment (OXE) made of eight datasets (Bridge-V2 24.14% of the mixture, RT-1 13.80%, and six others at 10.34% each) on 32 H200 GPUs for about 2.5 days with a global batch size of 2,048. It is then fine-tuned for each target (LIBERO, Bridge-V2, Fractal) on one node of 8 GPUs for 15 to 32 hours. Pauses in the trajectories are excluded from the loss.
Why the authors chose it
Pre-training provides general skills; the fine-tuning datasets match the benchmarks. The paper does not run a model without pre-training.
Technical details
Learning rate 1e-4 for the language backbone and the flow-matching head and 2e-5 for the vision encoder; AdamW with weight decay 0; bf16 precision, flash-attention-2 and ZeRO-2 sharding. The arithmetic (about 1,920 GPU-hours, weights that add to 99.98%) is in the example in Part E.
Evidence in the paper
§4.1 · Appendix E.1 · Table 8
Check your understanding: The paper tests on Bridge-V2 and Fractal. Bridge-V2 is in the pre-training mixture and Fractal is, to our knowledge, the RT-1 dataset, which is also in it. Why does that matter?

The benchmarks are built from data the model has already seen in pre-training, so the results measure fine-tuning on familiar data, not transfer to unseen robots. Every model compared has its own pre-training mixture, which differs.

Part D

Understand the experiments

Four sets of tests: LIBERO (simulated tabletop tasks), the WidowX and Google Robot benchmarks (simulated copies of real robots), an ablation study, and a real robot arm. Numbers are as printed in the paper unless marked as ours.

The set-up: benchmarks, baselines and the score

Intuition
Several different exams, each against a different set of rivals.
How it works

LIBERO has four task suites (Spatial, Object, Goal, Long), each with 10 tasks of 50 episodes, so 500 trials per suite. All models are fine-tuned on the four suites combined.

SimplerEnv simulates two real setups: the WidowX robot (fine-tuned on Bridge-V2; four tasks) and the Google Robot (fine-tuned on Fractal; four tasks under two settings, visual matching M and variant aggregation A).

Real robot: an AgileX PiPER arm with a fixed front camera and a wrist camera, four tasks (carrot into a bowl, pen out of a holder, pour water, spoon onto a plate), 50 trials per task and method.

Baselines differ by table: for example π0, π0.5, π0-FAST, OpenVLA-OFT, GR00T-N1, UD-VLA, Discrete-Diffusion VLA and dVLA on LIBERO; Magma, Octo, RoboVLM, ThinkAct and others on SimplerEnv; OpenVLA-OFT, π0 and π0.5 on the real robot. The paper does not say whether baseline numbers were re-run or taken from the cited papers.

Score: success rate.

Evidence in the paper
§4.1 · §4.2 · §5 · Tables 1 to 3 and 5
Check your understanding: Why does it matter whether baseline numbers were re-run or copied?

Copied numbers come from other papers’ training and evaluation settings (different data, seeds, trial counts), so the comparison may mix protocols. Part F finds hints of that.

LIBERO

Technical details
Table 1, selected rows. Bold marks the best value in each column.
Success rate (%)SpatialObjectGoalLongAverage
π096.898.895.885.294.2
π0.598.898.298.092.496.9
OpenVLA-OFT (continuous)96.998.195.591.195.4
GR00T-N194.497.693.090.693.9
Discrete-Diffusion VLA97.298.697.492.096.3
dVLA97.497.998.292.296.4
AsyncVLA98.499.298.693.497.4

AsyncVLA has the best average, 97.4%, a margin of about one point over dVLA and about half a point over π0.5. The paper says it achieves the highest success rate on all four suites; in the table π0.5 has the higher Spatial score (98.8 against 98.4). Our calculation Each suite has 500 trials, which puts a 95% interval of roughly ±1 point on a single value near 98%, so these margins are small.

Run the example: who is best on each LIBERO suite?
Our calculation

What each part does

  1. Type in every row of Table 1.
  2. Check that each printed average is the mean of the four suites.
  3. Find the best entry on each suite and the gap on the average.
# Table 1 (LIBERO success rates, %): Spatial, Object, Goal, Long, printed average
rows = {
    "WorldVLA":             ([87.6, 96.2, 83.4, 60.0], 81.8),
    "TraceVLA":             ([84.6, 85.2, 75.1, 54.1], 74.8),
    "SpatialVLA":           ([88.2, 89.9, 78.6, 55.5], 78.1),
    "pi0-FAST":             ([96.4, 96.8, 88.6, 60.2], 85.5),
    "pi0":                  ([96.8, 98.8, 95.8, 85.2], 94.2),
    "pi0.5":                ([98.8, 98.2, 98.0, 92.4], 96.9),
    "OpenVLA-OFT (con.)":   ([96.9, 98.1, 95.5, 91.1], 95.4),
    "OpenVLA-OFT (dis.)":   ([96.2, 98.2, 95.6, 92.0], 95.5),
    "GR00T-N1":             ([94.4, 97.6, 93.0, 90.6], 93.9),
    "UD-VLA":               ([94.1, 95.7, 91.2, 89.6], 92.7),
    "Discrete-Diffusion":   ([97.2, 98.6, 97.4, 92.0], 96.3),
    "dVLA":                 ([97.4, 97.9, 98.2, 92.2], 96.4),
    "AsyncVLA":             ([98.4, 99.2, 98.6, 93.4], 97.4),
}
suites = ["Spatial", "Object", "Goal", "Long"]

print("do the printed averages match the plain mean of the four suites?")
for name, (scores, printed) in rows.items():
    mean = sum(scores) / 4
    flag = "" if abs(mean - printed) < 0.06 else "   <- differs"
    print(f"  {name:<20} mean {mean:6.3f}  printed {printed}{flag}")

print()
print("best entry on each suite:")
for i, suite in enumerate(suites):
    best = max(rows, key=lambda r: rows[r][0][i])
    ours = rows["AsyncVLA"][0][i]
    print(f"  {suite:<8} best = {best} ({rows[best][0][i]}); AsyncVLA {ours}")

best_average = max(rows, key=lambda r: rows[r][1])
print()
print("best printed average:", best_average, rows[best_average][1])
print("gap to the runner-up on the average:", round(rows["AsyncVLA"][1] - rows["dVLA"][1], 1), "points (dVLA)")

Output:

do the printed averages match the plain mean of the four suites?
  WorldVLA             mean 81.800  printed 81.8
  TraceVLA             mean 74.750  printed 74.8
  SpatialVLA           mean 78.050  printed 78.1
  pi0-FAST             mean 85.500  printed 85.5
  pi0                  mean 94.150  printed 94.2
  pi0.5                mean 96.850  printed 96.9
  OpenVLA-OFT (con.)   mean 95.400  printed 95.4
  OpenVLA-OFT (dis.)   mean 95.500  printed 95.5
  GR00T-N1             mean 93.900  printed 93.9
  UD-VLA               mean 92.650  printed 92.7
  Discrete-Diffusion   mean 96.300  printed 96.3
  dVLA                 mean 96.425  printed 96.4
  AsyncVLA             mean 97.400  printed 97.4

best entry on each suite:
  Spatial  best = pi0.5 (98.8); AsyncVLA 98.4
  Object   best = AsyncVLA (99.2); AsyncVLA 99.2
  Goal     best = AsyncVLA (98.6); AsyncVLA 98.6
  Long     best = AsyncVLA (93.4); AsyncVLA 93.4

best printed average: AsyncVLA 97.4
gap to the runner-up on the average: 1.0 points (dVLA)
Evidence in the paper
§4.2 “LIBERO Benchmark” · Table 1
Check your understanding: What does a margin of 0.5 points on 2,000 trials tell you?

Very little by itself: with 2,000 trials the 95% interval on a rate near 97% is about ±0.8 points, wider than the margin.

SimplerEnv: WidowX and Google Robot

Technical details
Table 2, selected rows.
WidowX, success rate (%)Spoon on towelCarrot on plateStack cubesEggplant in basketAverage
π0.549.364.744.769.757.1
UD-VLA58.362.554.175.062.5
ThinkAct58.337.58.770.843.8
Magma37.529.220.891.744.8
AsyncVLA70.866.758.387.570.8
Table 3, averages over the four tasks (selected rows). Bold marks AsyncVLA.
Google Robot averageVisual matching (M)Variant aggregation (A)
π071.454.7
RT-2-X47.354.4
Magma48.857.5
RoboVLM51.736.6
AsyncVLA75.364.3

AsyncVLA has the highest average in both settings and the best score on three of four WidowX tasks (Magma is higher on eggplant). Our calculation Every AsyncVLA and UD-VLA percentage in Table 2 is a multiple of 100/24, consistent with 24 episodes per task, so the interval on a single task is wide (for example 70.8% = 17/24 runs from about 51% to 85%) and on the four-task average about 61% to 79%. Some baselines’ entries (for instance all four π0.5 entries) are not multiples of 1/24, which suggests they were produced by a different protocol.

Run the example: how many trials are behind these percentages?
Our calculation

What each part does

  1. Check that the WidowX percentages are multiples of 100/24.
  2. Compute 95% (Wilson) intervals for task, average, real-robot and LIBERO results.
  3. List the Table 2 baseline entries that are not multiples of 100/24.
import math

def wilson(successes, n, z=1.96):
    # 95% interval for a success rate measured over n trials
    p = successes / n
    centre = (p + z * z / (2 * n)) / (1 + z * z / n)
    half = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / (1 + z * z / n)
    return 100 * (centre - half), 100 * (centre + half)

# The WidowX percentages in Tables 2 and 4 are all multiples of 100/24 = 4.1667:
widowx = [4.2, 8.3, 0.0, 16.7, 58.3, 54.2, 33.3, 45.8, 37.5, 66.7, 70.8, 87.5, 75.0, 79.2, 50.0]
counts = [round(p * 24 / 100) for p in widowx]
print("each WidowX percentage times 24 / 100 is close to a whole number:",
      all(abs(p * 24 / 100 - k) < 0.05 for p, k in zip(widowx, counts)))
print("-> consistent with 24 episodes per task (the paper does not state the number)")

print()
print("95% intervals if each task has 24 episodes:")
for label, k in (("AsyncVLA, put spoon on towel: 70.8% = 17/24", 17), ("UD-VLA, put spoon on towel: 58.3% = 14/24", 14)):
    lo, hi = wilson(k, 24)
    print(f"  {label}: {lo:.0f}% to {hi:.0f}%")

print()
print("averages over the four tasks (96 episodes):")
for label, pct in (("AsyncVLA", 70.8), ("w/o confidence rater", 62.5), ("w/o AFM, 10 steps", 47.9), ("UD-VLA", 62.5)):
    k = round(pct * 96 / 100)
    lo, hi = wilson(k, 96)
    print(f"  {label:<22} {pct:5.1f}%  ->  {lo:.0f}% to {hi:.0f}%")

print()
print("real robot, 50 trials per task (200 per method):")
for label, pct in (("AsyncVLA", 87.0), ("pi0.5", 77.0), ("pi0", 65.0)):
    k = round(pct * 200 / 100)
    lo, hi = wilson(k, 200)
    print(f"  {label:<10} {pct:5.1f}%  ->  {lo:.0f}% to {hi:.0f}%")

print()
print("LIBERO, 500 trials per suite (2000 for the average):")
for label, pct in (("AsyncVLA avg 97.4", 97.4), ("pi0.5 avg 96.9", 96.9)):
    k = round(pct * 2000 / 100)
    lo, hi = wilson(k, 2000)
    print(f"  {label}: {lo:.1f}% to {hi:.1f}%")
lo, hi = wilson(round(98.4 * 5), 500)
print(f"  one suite, 98.4% over 500 trials: {lo:.1f}% to {hi:.1f}%")

# Are the baselines' Table 2 entries also multiples of 1/24? (a tolerance of 0.1 allows for truncated decimals)
table2 = {
    "OpenVLA": [0, 0, 0, 4.1], "SpatialVLA": [20.8, 20.8, 25.0, 70.8], "Magma": [37.5, 29.2, 20.8, 91.7],
    "pi0-FAST": [29.1, 21.9, 10.8, 66.6], "Octo-Base": [12.5, 8.3, 0, 43.1], "Octo-Small": [47.2, 9.7, 4.2, 56.9],
    "RoboVLM": [45.8, 20.8, 4.2, 79.2], "pi0.5": [49.3, 64.7, 44.7, 69.7], "ThinkAct": [58.3, 37.5, 8.7, 70.8],
    "UD-VLA": [58.3, 62.5, 54.1, 75.0], "AsyncVLA": [70.8, 66.7, 58.3, 87.5],
}
print()
print("Table 2 entries that are NOT within 0.1 of a multiple of 100/24:")
for name, scores in table2.items():
    off = [p for p in scores if abs(p * 24 / 100 - round(p * 24 / 100)) > 0.1 * 24 / 100]
    print(f"  {name:<12} {len(off)} of 4" + (f"  {off}" if off else ""))

Output:

each WidowX percentage times 24 / 100 is close to a whole number: True
-> consistent with 24 episodes per task (the paper does not state the number)

95% intervals if each task has 24 episodes:
  AsyncVLA, put spoon on towel: 70.8% = 17/24: 51% to 85%
  UD-VLA, put spoon on towel: 58.3% = 14/24: 39% to 76%

averages over the four tasks (96 episodes):
  AsyncVLA                70.8%  ->  61% to 79%
  w/o confidence rater    62.5%  ->  53% to 72%
  w/o AFM, 10 steps       47.9%  ->  38% to 58%
  UD-VLA                  62.5%  ->  53% to 72%

real robot, 50 trials per task (200 per method):
  AsyncVLA    87.0%  ->  82% to 91%
  pi0.5       77.0%  ->  71% to 82%
  pi0         65.0%  ->  58% to 71%

LIBERO, 500 trials per suite (2000 for the average):
  AsyncVLA avg 97.4: 96.6% to 98.0%
  pi0.5 avg 96.9: 96.0% to 97.6%
  one suite, 98.4% over 500 trials: 96.9% to 99.2%

Table 2 entries that are NOT within 0.1 of a multiple of 100/24:
  OpenVLA      0 of 4
  SpatialVLA   0 of 4
  Magma        0 of 4
  pi0-FAST     2 of 4  [21.9, 10.8]
  Octo-Base    1 of 4  [43.1]
  Octo-Small   3 of 4  [47.2, 9.7, 56.9]
  RoboVLM      0 of 4
  pi0.5        4 of 4  [49.3, 64.7, 44.7, 69.7]
  ThinkAct     1 of 4  [8.7]
  UD-VLA       0 of 4
  AsyncVLA     0 of 4

The number of episodes is inferred from the percentages; the paper does not state it for SimplerEnv.

Evidence in the paper
§4.2 “WidowX” and “Google Robot” · Tables 2 and 3
Check your understanding: Why is a 12-point lead on four tasks less certain than it looks?

Each task has only about 24 episodes, so each percentage is uncertain by about ±15 to 20 points, and the four-task average by about ±9. A lead of 8 points over a close competitor can disappear within that noise.

The ablation: which part does the work?

How it works
Seven variants are compared with the full method on the four WidowX tasks (Table 4): without unified training; without the second pass (with 10 or 20 first-pass steps); with the second pass but without the rater (random masks at probability 0.5); with the rater trained from task-success labels; and with a separate refinement network (predicting changes, or the refined actions directly) in place of the second pass.
Technical details
Table 4 averages.
WidowX average (%)AsyncVLA variant
7.3without unified training
47.9no second pass, 10 draft steps
51.1no second pass, 20 draft steps
62.5second pass with random masks (no rater)
61.5 / 62.5separate refinement network (changes / direct)
64.6rater trained from task-success labels
70.8full method

Reading the table: unified training is essential (7.3% without it); a second pass helps even with random masks (+14.6 points over 47.9%); a rater adds a further 8.3 points; extra draft steps help little (51.1% with 20). The 20-step control has about the same number of steps as the full method (10 + 10) though the second pass touches fewer tokens, so it is not an easy comparison for the baseline. Our interpretation Two cautions: with 24 episodes per task the intervals of the 62.5% and 70.8% averages overlap, and the table has no row for a vanilla model trained and run without any of the new ideas (Part F).

Run the example: the ablation arithmetic
Our calculation

What each part does

  1. Type in the per-task scores of Table 4 and Table 5.
  2. Recompute every printed average.
  3. Compute the gains the text quotes (14.6 points) and the one it does not (rater against random masks).
# Re-add the averages the paper prints, from the per-task numbers in its tables.
def mean(xs):
    return sum(xs) / len(xs)

# Table 4 (ablation on the WidowX benchmark): spoon, carrot, stack cubes, eggplant, printed average
table4 = {
    "w/o unified training": ([4.2, 8.3, 0.0, 16.7], 7.3),
    "w/o AFM (10 steps)":   ([58.3, 54.2, 33.3, 45.8], 47.9),
    "w/o AFM (20 steps)":   ([58.3, 54.2, 37.5, 54.2], 51.1),
    "w/o confidence rater": ([66.7, 54.2, 54.2, 75.0], 62.5),
    "w/ TSI labeling":      ([66.7, 58.3, 54.2, 79.2], 64.6),
    "w/ delta refinement":  ([66.7, 58.3, 45.8, 75.0], 61.5),
    "w/ direct refinement": ([66.7, 54.2, 50.0, 79.2], 62.5),
    "AsyncVLA":             ([70.8, 66.7, 58.3, 87.5], 70.8),
}
print("Table 4: recomputed average vs printed")
for name, (scores, printed) in table4.items():
    print(f"  {name:<22} {mean(scores):6.2f}  printed {printed}")

full = mean(table4["AsyncVLA"][0])
print()
print("gain of AFM without a rater over SFM-only (10 steps):", round(62.5 - 47.9, 1), "points (paper says 14.6)")
print("gain of the confidence rater over random masking:     ", round(70.8 - 62.5, 1), "points")
print("gain of the full method over 20-step SFM-only:        ", round(70.8 - 51.1, 1), "points")

# Table 5 (real robot, 50 trials per task): carrot, pen, pour water, spoon, printed average
table5 = {"OpenVLA-OFT": ([82, 68, 46, 66], 65.5), "pi0": ([72, 76, 48, 64], 65.0),
          "pi0.5": ([86, 78, 68, 76], 77.0), "AsyncVLA": ([94, 86, 82, 86], 87.0)}
print()
print("Table 5: recomputed average vs printed")
for name, (scores, printed) in table5.items():
    print(f"  {name:<12} {mean(scores):5.1f}  printed {printed}")

Output:

Table 4: recomputed average vs printed
  w/o unified training     7.30  printed 7.3
  w/o AFM (10 steps)      47.90  printed 47.9
  w/o AFM (20 steps)      51.05  printed 51.1
  w/o confidence rater    62.53  printed 62.5
  w/ TSI labeling         64.60  printed 64.6
  w/ delta refinement     61.45  printed 61.5
  w/ direct refinement    62.53  printed 62.5
  AsyncVLA                70.83  printed 70.8

gain of AFM without a rater over SFM-only (10 steps): 14.6 points (paper says 14.6)
gain of the confidence rater over random masking:      8.3 points
gain of the full method over 20-step SFM-only:         19.7 points

Table 5: recomputed average vs printed
  OpenVLA-OFT   65.5  printed 65.5
  pi0           65.0  printed 65.0
  pi0.5         77.0  printed 77.0
  AsyncVLA      87.0  printed 87.0
Evidence in the paper
§4.3 · Table 4
Check your understanding: What does the “random mask” row tell you about the confidence rater?

A second pass with randomly chosen tokens already gets most of the benefit (62.5% against 47.9%). The rater’s own contribution is the remaining 8 points, which is promising but within the noise of 24-episode tasks.

Training data efficiency

How it works
Using a quarter of the LIBERO-Spatial training set for 200 epochs, the unified training method is compared with ordinary synchronous training. The authors report that the ordinary method’s training loss stops improving at about 0.0076 after 150 epochs and its success rate plateaus around 86.2% after 140 epochs, while AsyncVLA’s loss reaches 0.0042 and its success rate keeps rising to 95.8%.
Technical details

The authors attribute this to the random masks acting like data augmentation. Our interpretation The loss curves are not a like-for-like comparison: the unified method’s loss is computed on the masked tokens of a randomly masked chunk, a different (often easier) task than the full draft. The success-rate curve is the comparison that counts.

Evidence in the paper
§4.4 · Figure 3
Check your understanding: Why is a lower training loss alone weak evidence of better data efficiency?

The two losses measure different tasks (partial regeneration with context against full generation), so they are not comparable. The success rate on held-out episodes is the real signal.

Real robot

How it works
Four tasks on the AgileX PiPER arm, 50 trials each, under mild variation in object poses and initial states: carrot into bowl, pen extraction, pouring water, spoon onto plate.
Technical details
Table 5.
Success rate (%)Carrot → bowlPen extractionPour waterSpoon → plateAverage
OpenVLA-OFT82.068.046.066.065.5
π072.076.048.064.065.0
π0.586.078.068.076.077.0
AsyncVLA94.086.082.086.087.0

AsyncVLA is best on all four tasks and by 10 points on average over π0.5. Our calculation With 200 trials per method the 95% intervals are about 82 to 91% (AsyncVLA) and 71 to 82% (π0.5), which barely overlap, so this is the paper’s strongest evidence. The authors say the gains are largest on the error-sensitive tasks (pouring, pen extraction). The paper does not describe how the baselines were fine-tuned or how many demonstrations were used for any model.

Evidence in the paper
§5 · Table 5 · Figure 4
Check your understanding: Why is the real-robot result stronger evidence than the SimplerEnv ones?

It uses 50 trials per task on a physical robot, so the intervals are narrower, and the margin is larger (10 points). It still comes from one robot, one lab and an undescribed fine-tuning protocol for the baselines.

What the results show

  • Adding a second, selective pass to the same model improves success in the paper’s ablation by a large amount (47.9% to 70.8% on WidowX).
  • Unified training is needed for the second pass to work at all.
  • AsyncVLA has the highest averages in every table, with the strongest margin on the real robot.
  • The method keeps the cost modest: about 15% more time than the draft alone.

What they do not show

  • That the model corrects its own mistakes in general: there is one selected example and no count of how often a flagged action is repaired.
  • That the confidence rater itself matters more than any second pass: the gap to random masks is about 8 points on 24-episode tasks.
  • That the margins on LIBERO and SimplerEnv are larger than the noise.
  • That the gains transfer beyond robot actions, which the authors say they have not tested.

Part E · optional

Engineering deep dive

Equations, shapes, hyperparameters, timings, sizes and sensitivity tables, for readers who want to rebuild or audit the method. Everything is collapsed; Parts A to D do not depend on it.

The equations (Equations 1 to 7)

Symbols: ot is the observation (images and state), ℓ the instruction, a the true action chunk of length L, âτ the partially cleaned chunk at time τ (τ = 1 is noise, τ = 0 is clean), n noise, Vθ the network, m the mask (1 = regenerate), ⊙ a per-token product.

Reported by the paper Refinement update (Equation 1), moving only masked tokens:

a^τ−δ=a^τ−δ⋅Vθ(ot, ℓ, a^τ)⊙m\hat{a}^{\tau -\delta }=\hat{a}^{\tau }-\delta \cdot V_{\theta }(o_{t},\,\ell ,\,\hat{a}^{\tau })\odot m

Reported by the paper Starting point (Equation 2): kept tokens begin at the draft, masked tokens at noise:

a~l=a^lSFM if ml=0;\tilde{a}_{l}=\hat{a}^{\text{SFM}}_{l}\,\text{if}\,m_{l}=0;
nl∼N(0, I) if ml=1n_{l}\sim N(0,\,I)\,\text{if}\,m_{l}=1

Reported by the paper Mask from the rater’s scores (Equation 3) with threshold T = 0.5:

ml=1{pl<T}m_{l}=1\{p_{l}<T\}

Reported by the paper Training loss on masked tokens (Equation 4), target velocity u = n − a, context noise (Equation 5) and the intermediate noisy chunk (Equation 6):

L=Eτ ∥(Vθ(ot, ℓ, a^τ)−u)⊙m ∥2L=E_{\tau }\,\lVert (V_{\theta }(o_{t},\,\ell ,\,\hat{a}^{\tau })-u)\odot m\,\rVert ^{2}
a~=a+ε⊙(1−m),\tilde{a}=a+\varepsilon \odot (1-m),
ε∼N(0, σc2 I),\varepsilon \sim N(0,\,\sigma _{c}^{2}\,I),
a^τ=a~−τ(a~−n)⊙m\hat{a}^{\tau }=\tilde{a}-\tau (\tilde{a}-n)\odot m

Reported by the paper Rater labels (Equation 7), with α = 0.01, β = 0.98 and a small ε:

q=1−α−β⋅(e−min⁡ e)max⁡ e−min⁡ e+εq=1-\alpha -\frac{\beta \cdot (e-\min \,e)}{\max \,e-\min \,e+\varepsilon }

Our calculation With âτ = a − τ(a − n), the slope with respect to τ is n − a, which is the target u, and stepping from τ to τ − δ with −δ·u moves toward the clean chunk. The conventions agree (unlike the printed equations of the π0 and GR00T N1 papers); the example in Part C checks it. See also the π0 guide’s finding.

Token embeddings and shapes (asynchronous time embedding)

Reported by the paper For an action chunk of L tokens and the backbone’s hidden size d: the time of each token (τ for masked tokens, 0 for kept ones) is encoded with a sinusoidal function into a matrix S ∈ RL×d; the partially cleaned actions are projected linearly into P ∈ RL×d; the two are concatenated to L×2d and an MLP (multi-layer perceptron) brings them back to L×d, the same width as the backbone, and the result joins the vision-language hidden states. L and d for the released model are not stated in the paper.

Run the example: asynchronous time embedding shapes
Toy illustration

What each part does

  1. Choose toy sizes L = 8 and d = 16 and mark one token as masked.
  2. Encode each token’s time (τ for the masked token, 0 for the rest) and project the noisy actions.
  3. Concatenate, apply a small MLP, and print the shapes.
import numpy as np
rng = np.random.default_rng(0)

L, d = 8, 16                 # L action tokens (the paper does not give L) and hidden width d (toy sizes)

def sinusoidal(values, width):
    # Encode each time value as `width` numbers, like a transformer position code.
    freqs = 1000.0 ** (-np.arange(width // 2) / (width // 2))
    angles = values[:, None] * freqs[None, :]
    return np.concatenate([np.sin(angles), np.cos(angles)], axis=1)

m = np.array([0, 0, 0, 1, 0, 0, 0, 0])      # which tokens are being regenerated (1 = masked)
tau = 0.6                                    # current flow-matching time
per_token_time = tau * m                     # "tau m": the masked tokens have time tau, the others time 0

S = sinusoidal(per_token_time, d)            # asynchronous time embedding, shape (L, d)
noisy_actions = rng.normal(size=(L, 7))      # partially denoised actions, 7 numbers each (toy)
P = noisy_actions @ rng.normal(size=(7, d)) * 0.1     # linear projection of the actions, shape (L, d)

h = np.concatenate([S, P], axis=1)           # shape (L, 2d)
W1 = rng.normal(size=(2 * d, 2 * d)) * 0.1   # a small MLP (two layers) back to width d
W2 = rng.normal(size=(2 * d, d)) * 0.1
x = np.maximum(h @ W1, 0) @ W2               # shape (L, d), same width as the VLM's hidden states

print("time embedding S:", S.shape, "| projected actions P:", P.shape)
print("concatenated:", h.shape, "-> after the MLP:", x.shape)
print("time embeddings of the unmasked tokens are identical:", bool(np.allclose(S[0], S[1]) and np.allclose(S[0], S[7])))
print("the masked token's time embedding differs:", not np.allclose(S[3], S[0]))

Output:

time embedding S: (8, 16) | projected actions P: (8, 16)
concatenated: (8, 32) -> after the MLP: (8, 16)
time embeddings of the unmasked tokens are identical: True
the masked token's time embedding differs: True

Random weights and toy sizes; only the shapes and the identical time embeddings of the kept tokens matter here.

Hyperparameters and training details
As printed in Section 4.1 and Appendix E.
SettingValue
BackboneQwen2.5-VL-3B-Instruct (total model 4.08 billion parameters including the action head and the rater)
Denoising steps10 for the draft and 10 for the refine pass (uniform step size)
Learning rate1e-4 (language backbone and flow-matching head), 2e-5 (vision encoder); cosine decay, peak 1e-4 in pre-training
OptimiserAdamW, weight decay 0, β₁ 0.9, β₂ 0.999
Context noise σc0.05
Rater labels and thresholdα 0.01, β 0.98, ε 1e-6; threshold T 0.5
Pre-training32 H200 GPUs (4 nodes), bf16, gradient checkpointing, flash-attention-2, ZeRO-2; global batch 2,048; about 2.5 days
Fine-tuningone node of 8 H200 GPUs, 15 to 32 hours per dataset
PromptThe chat template starts with “You are a helpful physical assistant.”
Data handlingPause intervals in trajectories are marked and excluded from the loss
Inference time (Table 6)
On an NVIDIA RTX 4090 with 2 camera images and 10 denoising steps.
ComponentTimeShare
Draft (SFM)83.2 ± 1.4 ms86.8%
Confidence rater2.6 ± 0.1 ms2.7%
Refine (AFM)10.1 ± 0.3 ms10.5%
Overall95.9 ± 1.6 ms100%

Reported by the paper The draft builds the image-and-text key-value (KV) cache from scratch and runs all tokens. The refine pass reuses that cache and updates only the flagged action tokens; the rater runs once per chunk.

Run the example: inference time, parameter share and training cost
Our calculation

What each part does

  1. Add the three components and recompute each share.
  2. Work out the extra time over the draft alone.
  3. Check the rater’s parameter share, the pre-training GPU-hours and the dataset weights.
# Table 6: wall-clock time on an RTX 4090 with 2 camera images, in milliseconds
sfm, rater, afm = 83.2, 2.6, 10.1
total = sfm + rater + afm
print("total:", round(total, 1), "ms (paper: 95.9)")
for name, t in (("SFM", sfm), ("confidence rater", rater), ("AFM", afm)):
    print(f"  {name:<17} {t:5.1f} ms = {100 * t / total:.1f}%")

print()
print("extra time over running SFM alone:", round(rater + afm, 1), "ms =", round(100 * (rater + afm) / sfm), "% more")
print("AFM compared with SFM, stage by stage:", round(afm / sfm, 2), "of the time (SFM builds the cache and runs all tokens)")
print("but the full pipeline is slower than SFM alone:", round(total / sfm, 2), "times")

# Parameter share of the confidence rater (Section 4.1)
print()
print("rater share of the model:", round(100 * 308 / 4080, 2), "% (paper: 7.56%)")

# Pre-training cost (Appendix E.1): 32 GPUs for about 2.5 days
print("pre-training GPU-hours:", 32 * 24 * 2.5, "(32 GPUs x 24 h x 2.5 days)")

# Pre-training dataset weights (Table 8)
weights = [24.14, 13.80] + [10.34] * 6
print("dataset weights add up to", round(sum(weights), 2), "%")

Output:

total: 95.9 ms (paper: 95.9)
  SFM                83.2 ms = 86.8%
  confidence rater    2.6 ms = 2.7%
  AFM                10.1 ms = 10.5%

extra time over running SFM alone: 12.7 ms = 15 % more
AFM compared with SFM, stage by stage: 0.12 of the time (SFM builds the cache and runs all tokens)
but the full pipeline is slower than SFM alone: 1.15 times

rater share of the model: 7.55 % (paper: 7.56%)
pre-training GPU-hours: 1920.0 (32 GPUs x 24 h x 2.5 days)
dataset weights add up to 99.98 %

Arithmetic on the paper’s numbers; the 15% extra-time figure is ours.

Pre-training dataset weights (Table 8)
These weights add up to 99.98% (rounding).
DatasetWeight
Bridge-V224.14%
RT-113.80%
TOTO, VIOLA, RoboTurk, Jaco Play, Berkeley Autolab UR5, Berkeley Fanuc Manipulation10.34% each
Sensitivity to the rater settings (Table 9)
All four suites change by at most a few tenths of a point.
LIBERO average (%)Setting
97.4default (α 0.01, β 0.98, T 0.5)
97.2α = 0.05
97.3β = 0.95
97.2T = 0.25
97.3T = 0.75

Our interpretation With 2,000 trials the noise is about ±0.7 points, so changes of 0.1 to 0.2 cannot be distinguished from none; the table shows the method is not very sensitive, not that the settings are optimal.

Comparison with discrete-diffusion VLAs (Table 7)
As printed in Appendix D.
AspectDiscrete-diffusion VLAAsyncVLA
Actionsdiscrete tokenscontinuous
What the network predictsthe clean target (x-prediction)the velocity (v-prediction)
Re-maskinga mask tokenGaussian noise
Confidencetaken from the logitsa separate rater

Part F

Critical paper review

Everything above reports what the paper says. This part is our independent reading: where a claim is stronger than its table, where the numbers cannot carry the weight put on them, where the method has gaps, and what the authors list as limits. We looked for these in good faith; none overturns the paper’s main idea, and each links back to the concept it affects. Calculations are reproducible in the examples. Interval statements assume the trial counts we inferred from the percentages, which the paper does not state.

Claims against the tables and the numbers

  1. F1. “Highest success rate in all four LIBERO suites” Numerical inconsistency

    What the paper says. AsyncVLA is said to achieve the highest success rates in all four tasks (suites) of Table 1.

    What we found. In Table 1, π0.5 has 98.8 on LIBERO-Spatial, higher than AsyncVLA’s 98.4. AsyncVLA is best on Object, Goal and Long and on the average. Every printed average matches the mean of its four suites.

    Why it matters. A small overstatement: the model is best on three of four suites and the average. The gaps are also within the noise of 500 trials per suite. Concept: LIBERO · example

  2. F2. How much the simulated margins can carry Method caveat

    What the paper says. AsyncVLA achieves the best results across simulation, with an average of 70.8% on WidowX and a gain of 8.3 points from the rater in the ablation.

    What we found. The WidowX percentages are all multiples of 100/24, consistent with 24 episodes per task. On that basis the four-task averages have 95% intervals of roughly ±9 points: 61 to 79% for 70.8%, 53 to 72% for 62.5% and 38 to 58% for 47.9%. The interval for the full method overlaps that of the variant without the rater, and with UD-VLA’s 62.5%.

    Why it matters. The ranking is plausible but the 8-point differences are not established by these numbers; the paper reports no repeated runs or intervals. Concept: SimplerEnv · Ablation · example

  3. F3. The baselines may come from different protocols Method caveat

    What the paper says. Tables 1 to 3 compare AsyncVLA with many models fine-tuned on the combined LIBERO suites or on the simulated benchmarks.

    What we found. The paper does not say whether baseline numbers were re-run or copied. Some entries are not multiples of 1/24 (all four π0.5 entries, and several for π0-FAST and Octo), while AsyncVLA’s and UD-VLA’s all are, which suggests the baselines were evaluated differently or taken from other papers. Backbones (Qwen2.5-VL, PaliGemma, others), pre-training data and fine-tuning budgets also differ between models.

    Why it matters. The tables show AsyncVLA as a system next to published numbers; they do not isolate the second pass. The paper’s own ablation is the cleaner evidence for that. Concept: The set-up

  4. F4. Which row is the plain baseline? Attribution in the ablation Method caveat

    What the paper says. Removing the second pass drops WidowX to 47.9%; removing unified training drops it to 7.3%; separate refinement networks reach about 62%.

    What we found. The table has no row for a plain synchronous model trained and run without any of the new ideas, so the gain of the whole method over a normal flow-matching model on WidowX cannot be read off it. It is also not stated whether “without AFM” uses the unified training. “Without unified training” (7.3%) mixes two changes: the model never practised partial regeneration and is then asked to do it. The rater’s 8-point gain over random masks is within the noise in F2.

    Why it matters. The ablation shows that the second pass matters and that unified training is needed for it; it does not give a clean “plain synchronous versus AsyncVLA” number, and the rater’s contribution is less certain than the headline. Concept: Ablation · Unified training

  5. F5. The training-loss comparison is not like for like Ambiguity

    What the paper says. The training loss of AsyncVLA decreases faster and is consistently lower than that of synchronous training; the loss is normalised “per unmasked token”.

    What we found. Equation 4 computes the loss on masked tokens, with unmasked context given, and with random masks that sometimes leave most tokens as context. That is easier than the all-masked draft task, so the lower loss can partly reflect the easier objective. The phrase “unmasked token” also reads oddly since the loss is on masked tokens.

    Why it matters. The success-rate curves in the same figure are the real evidence; the loss curves do not show better data efficiency by themselves. Concept: Data efficiency

  6. F6. Relative confidence labels Ambiguity

    What the paper says. The rater’s labels are min-max normalised errors within each chunk; the authors note a corner case where a globally bad draft keeps its “best” token as context.

    What we found. Beyond the authors’ case, a chunk whose actions are all accurate still gets labels spread from 0.01 to 0.99, so about half of its tokens fall below 0.5 at a loose threshold (in our example 6 of 8 at T = 0.75, 2 of 8 at T = 0.5) and would be regenerated needlessly. The labels carry no absolute information.

    Why it matters. The method may regenerate good tokens or trust bad ones. The paper does not report the typical fraction of tokens flagged, so the size of this effect is unknown. Concept: The rater’s training · example

  7. F7. Evidence for “self-correction” Method caveat

    What the paper says. AsyncVLA exhibits self-correction ability: in Figure 2 a low-confidence “drop now” action is regenerated as “keep grasping” and the task succeeds.

    What we found. The evidence is one illustrated case chosen from rollouts (the verbs in the figure are descriptions of continuous actions), plus the ablations. The paper does not report how many tokens are flagged on average, how often a flagged action changes the outcome, or how often a failure is repaired and a success broken.

    Why it matters. The ablations show the second pass helps on average; they do not show that the mechanism works by repairing detected errors, as opposed to a second refinement of any kind (random masks also help). Concept: The rater · Refine

  8. F8. How far the data-efficiency claim goes Method caveat

    What the paper says. AsyncVLA is data-efficient: with a quarter of LIBERO-Spatial, synchronous training plateaus near 86.2% while AsyncVLA reaches 95.8%, always ahead by at least 7.8%.

    What we found. The evidence is one suite, one data fraction, one comparison against the authors’ own synchronous variant, and no repeated runs; “at least 7.8%” does not say whether it means points. The final gap (95.8 − 86.2) is 9.6 points.

    Why it matters. A suggestive result about training with random masks as augmentation; it does not compare with other models’ data efficiency. Concept: Data efficiency

  9. F9. “AFM is significantly faster than SFM” Ambiguity

    What the paper says. Appendix B says AFM inference is significantly faster than SFM, because it reuses the key-value cache and updates only some tokens.

    What we found. Stage by stage that is true: 10.1 ms against 83.2 ms. But AFM is an extra stage after SFM, so the whole pipeline takes 95.9 ms against 83.2 ms for the draft alone, about 15% more. No latency comparison with other models is given, and the timing is for 2 camera images on an RTX 4090.

    Why it matters. The cost is modest, but the claim should be read as “cheap relative to the draft”, not “faster overall”. Concept: Refine · example

  10. F10. The rater’s 308 million parameters Ambiguity

    What the paper says. The rater is a 4-layer transformer with 32 heads and a feed-forward width of 6,144, totalling 308 million parameters (7.56% of 4.08 billion).

    What we found. The hidden width is not stated. If it were 2,048, which we assume is the backbone’s width (from memory, not from the paper), four layers with those sizes come to about 168 million (two-matrix feed-forward) or 218 million (gated), not 308 million; a width of about 2,650 would fit. The 7.56% share itself matches 308 million of 4.08 billion within rounding.

    Why it matters. Minor, but the rater’s size cannot be rebuilt from the appendix; the code would settle it. Concept: The rater

    Run the example: can the rater have 308 million parameters?
    Our calculation

    What each part does

    1. Write the parameter count of one layer from its pieces (attention matrices and the feed-forward).
    2. Try the width 2,048 with a two-matrix and a gated feed-forward.
    3. Solve for the width that would give 308 million.
    # Can the confidence rater really be 308 million parameters? The paper gives: 4 transformer layers,
    # 32 attention heads, feed-forward width 6144, plus a linear layer to bring in the actions and a rate head.
    # It does not give the hidden width d. We try d = 2048, which we assume is the VLM's hidden size.
    d, ffn, layers = 2048, 6144, 4
    
    attention = 4 * d * d                 # query, key, value and output matrices
    for name, mats in (("two-matrix feed-forward", 2), ("gated feed-forward (three matrices)", 3)):
        per_layer = attention + mats * d * ffn
        total = layers * per_layer
        print(f"{name}: {per_layer / 1e6:.0f} million per layer, {total / 1e6:.0f} million for {layers} layers")
    
    print("the paper says 308 million in total")
    
    # Which hidden width would be needed for 308 million with a gated feed-forward?
    import math
    target = 308e6 / layers                # per layer
    a, b, c = 4, 3 * ffn, -target          # 4 d^2 + 3 * ffn * d = target
    width = (-b + math.sqrt(b * b - 4 * a * c)) / (2 * a)
    print("hidden width that would give 308 million (gated):", round(width))

    Output:

    two-matrix feed-forward: 42 million per layer, 168 million for 4 layers
    gated feed-forward (three matrices): 55 million per layer, 218 million for 4 layers
    the paper says 308 million in total
    hidden width that would give 308 million (gated): 2652

    Rests on the assumed width and on ignoring the small input and output layers.

  11. F11. Details the paper does not give Ambiguity

    What the paper says. The paper describes the method, benchmarks and settings in Section 4 and Appendix E.

    What we found. We found no statement of the action-chunk length L, the number of episodes per task on SimplerEnv, the number of demonstrations or the fine-tuning protocol for any real-world model (including the baselines), the number of random seeds, or the fraction of tokens the rater flags.

    Why it matters. These limit reproduction from the paper alone and the weight the intervals in F2 can carry; the released code may answer them. Concept: Inputs · Real robot

Limitations the authors state

  1. F12. The authors’ own list Limitation

    What the paper says. The relative confidence labels may fail when the first draft is globally wrong, and the authors plan absolute error-aware calibration. The method is validated only on robotic action generation, not on image generation or other multimodal generation.

    What we found. We agree; the first is illustrated in F6, and F2 and F7 explain why the second matters: the evidence is one domain and small simulated samples.

    Why it matters. They bound where the reported gains should be expected to hold. Concept: The rater’s training

Knowledge check

Try each question first, then reveal the explanation.

Question 1

In your own words: what are the three stages of AsyncVLA’s action generation, and what changes between the first and the last?

Explanation

Draft: write the whole action chunk from noise in ten steps. Rate: a small network scores each action from 0 to 1. Refine: actions scoring below 0.5 restart from noise while the others stay fixed as context, and ten more steps rewrite only those. The final chunk keeps the confident draft actions and replaces the doubtful ones.

Question 2

Why can’t the model’s own probabilities be used as confidence, and what is used instead?

Explanation

The model outputs continuous velocities, not a probability for each action token, so there are no logits to read. A separate confidence rater, a small transformer trained on soft labels made from the draft’s own errors, gives each token a score.

Question 3

In the ablation, what do the “random mask” and “rater” rows tell you, and why be cautious about the rater’s part?

Explanation

Random masks already raise WidowX from 47.9% to 62.5%; the rater adds 8.3 points (70.8%). With about 24 episodes per task, the averages carry roughly ±9 point intervals that overlap, so the rater’s own contribution is promising but uncertain.

Question 4

Name one claim in the paper that is stronger than its table and one detail it does not state.

Explanation

For example: the paper says AsyncVLA is highest on all four LIBERO suites, but π0.5 has 98.8 against 98.4 on Spatial. And: the action-chunk length L, or the real-world fine-tuning protocol, is not given.

Glossary

VLA
Vision-language-action model: images and an instruction in, robot actions out.
VLM
Vision-language model: reads images and text together.
Action chunk
A short sequence of future actions produced at once.
Token
One slot in the sequence a transformer reads: a word, an image patch, a robot state or one action.
Flow matching (FM)
A way to generate a sample by starting from noise and following a learned direction toward clean data in a few steps.
Synchronous flow matching (SFM)
Flow matching in which every action token is at the same stage of cleaning at every step.
Asynchronous flow matching (AFM)
Flow matching in which different tokens are at different stages: kept tokens are fixed and only flagged tokens are regenerated.
Confidence rater
A small transformer that scores each draft action token between 0 and 1.
Mask
A 0/1 list marking which tokens are regenerated (1) and which are kept (0).
Context
The kept tokens and the scene that the regenerated tokens can look at.
Velocity
The direction the network predicts for moving a noisy action toward a clean one.
Euler step
The simplest way to follow a direction: move a small distance along it.
KV cache
Stored attention keys and values that avoid recomputing unchanged tokens.
MLP
Multi-layer perceptron: a small, simple neural network.
Pseudo-label
A label made automatically (here from the draft’s errors) instead of by a person.
TSI
Task success indicator: labelling every action by whether the whole trajectory succeeded.
Ablation
An experiment that removes or replaces one part of a method to see what it contributes.
OXE
Open X-Embodiment: a pooled multi-robot dataset.
Wilson interval
A 95% range for a success rate measured over a limited number of trials.
SimplerEnv
A simulation benchmark that copies real robot setups (WidowX and the Google Robot).

References

Numbered notes in the text, like [1], point here. Each entry says what it is cited for and how that was checked. Papers and books can be revised or misread, so follow the links before relying on a detail. Code marked “Toy model” is our own illustration of an idea, not the code of the cited system.

  1. Jiang, Y., Cheng, S., Ding, Y., Gao, F., Qi, B. (2025). AsyncVLA: Asynchronous flow matching for vision-language-action models. arXiv. arXiv:2511.14148

    Cited for:

    • Two-stage action generation: a synchronous flow-matching draft of the action chunk, a confidence rater (a 4-layer transformer, 308 million of 4.08 billion parameters) that scores each action token, and an asynchronous flow-matching pass that regenerates the tokens scoring below a threshold of 0.5 while the others stay fixed as context; one model trained for both modes, on a Qwen2.5-VL-3B backbone. Checked against the full text of the paper (arXiv v2 PDF), read sentence by sentence.

Go further

All paper guides · Back to the VLA track