Connect your own model¶
Reported results belong to a fixed benchmark version: a benchmark is frozen once numbers are
reported on it. New tasks, new layouts or a new execution constant make a new version (a new directory
under conf/benchmarks/), so a reported number keeps its meaning. v1.0
ships one version, axis-heldout-v1: 24 held-out tasks, 50 seeds each. Compare your results only with
results of the same version (the benchmark).
Any policy can be evaluated on the 24 held-out tasks if it runs behind a small WebSocket server that speaks the benchmark's protocol. On connect, the server sends a handshake. For each observation (two camera frames, the 8-D state and the instruction) it replies with a chunk of actions. The whole contract is on Policy server.
You need a GPU with EGL, the evaluation environment (qvla env build eval) and what your model needs.
1. Write a server¶
experiments/examples/policy_server.py is a complete server. This policy holds the arm still; replace act
with your model:
import numpy as np
from openpi_client import msgpack_numpy
from websockets.sync.server import serve
HANDSHAKE = {
"protocol": "qvla.policy_server/1",
"supports_client_noise": True, # required: the server takes the noise the client sends
"action_horizon": 8, # the noise tensor's shape; this policy ignores the noise
"action_dim": 8,
"image_geometry": {"base_0_rgb": "raw", "left_wrist_0_rgb": "raw"},
"state_order": ["q0", "q1", "q2", "q3", "q4", "q5", "q6", "gripper"],
"action_units": "rad_s",
"action_fps": 15,
"action_dim_out": 8,
}
def act(obs: dict) -> np.ndarray:
"""Eight rows of [7 joint velocities in rad/s, gripper closedness]: hold still, gripper open."""
assert obs["state"].shape == (8,) and obs["base_0_rgb"].shape == (360, 640, 3)
return np.zeros((8, 8), dtype=np.float32)
def handler(ws) -> None:
ws.send(msgpack_numpy.packb(HANDSHAKE))
for message in ws:
obs = msgpack_numpy.unpackb(message)
obs.pop("__noise__") # the sampler's noise: a stochastic policy starts from it
ws.send(msgpack_numpy.packb({"actions": act(obs)}))
Start it with the evaluation environment's interpreter, which has its packages (numpy, websockets and
openpi's client; qvla env build eval builds it), and leave it running:
.venv-eval/bin/python experiments/examples/policy_server.py --port 8000
2. Check it¶
check-server runs from any interpreter: it runs itself in the evaluation environment, as the
evaluation does. It connects, reads the handshake and sends a few observations shaped as the
evaluation sends them:
qvla bench check-server --policy 127.0.0.1:8000 --timeout 60
…: conformant (qvla.policy_server/1)
3. Get the benchmark¶
qvla data get bench
4. Evaluate¶
qvla bench eval --policy 127.0.0.1:8000 --run my_model
It runs the 24 tasks with 50 seeds each, writes the results file and prints the all-24 success rate with a
per-task table in the layout of the paper's main results. If the server runs on another machine,
--policy takes its address.
What to report: reporting rules.