Why does a robot need two brains — one for planning and one for execution? GalaxeaVLA G0.5 argues it doesn't. Everything — visual understanding, natural language reasoning, chain-of-thought planning, and joint-level action generation — flows through a single unified autoregressive decoder. One model, one token stream, one training objective.
This guide walks you through G0.5's architecture, how to install it, fine-tune on custom tasks, and deploy to real robots — including Galaxea R1 Lite/Pro, SO-100/101 arms, and Franka/DROID setups.
Repo: github.com/OpenGalaxea/GalaxeaVLA | Checkpoints: huggingface.co/OpenGalaxea/G05 | Technical Report: opengalaxea.github.io/G05/Galaxea_G0_5.pdf
From G0 Dual-System to G0.5 Unified — What Changed and Why
GalaxeaVLA G0 Plus used a classic dual-system architecture: a high-level VLM planner (System 2, ~1 Hz) decomposed long-horizon tasks into subtasks; a low-level VLA executor (System 1, 10–50 Hz) carried them out. The two systems communicated via language subtask strings — clean in theory, but coordination latency creeps in at runtime.
G0.5 collapses this into a single decoder. One transformer generates the full sequence: camera frames → task instruction → chain-of-thought reasoning → action tokens. No handshake, no coordinator overhead. This mirrors how human cognition actually works — "what to do" and "doing it" are the same neural stream, not two separate processes.
The shift also enables a new capability: readable robot reasoning. When G0.5 makes a decision, you can literally read why — the subtask name, the bounding box of the target object, the planned trajectory trace, all appear as text before the action. When the robot fails, you debug the reasoning, not the latent space.
Architecture: One Decoder to Rule Them All
Backbone: Qwen3.5 2B
G0.5 initializes from Qwen3.5 2B — Alibaba's 2B-parameter VLM with strong reasoning capabilities. Compared to PaliGemma-3B used in G0 Plus, Qwen3.5 brings native chain-of-thought reasoning and better multilingual grounding. The model is then pre-trained on robot demonstrations from 14 different embodiments mixed with web-scale VQA data (VQA:action ratio = 1:4), using the same cross-entropy loss for both.
ActionCodec: Teaching the LLM to Speak Robot
The core challenge of unified autoregressive VLA: continuous robot actions (joint angles, end-effector velocities) can't directly mix with discrete LLM tokens. G0.5 solves this with ActionCodec — a learned Vector Quantization (VQ) tokenizer, not a hand-crafted pipeline.
ActionCodec maps heterogeneous robot actions from 14 embodiments into a shared 27-dimensional action space:
left_control(9) | left_gripper(1) | right_control(9) | right_gripper(1) | lower_body(7)
Robots without a left arm or legs fill the unused dimensions with zeros. This shared vocabulary is what makes cross-embodiment pre-training work — every robot speaks the same action language.
This is architecturally different from FAST tokenizer used by π0-FAST. FAST applies a fixed DCT transform separately per robot, which means it can't learn cross-embodiment patterns during pre-training. G0.5's ActionCodec is learned end-to-end, cross-embodiment by design.
Token Sequence: Reason, Then Act
The most distinctive feature of G0.5 is its explicit chain-of-thought before every action:

[Image tokens] [Task instruction]
→ <Subtask>: "reach for the red cup"
→ <BBox>: [0.3, 0.4, 0.5, 0.6]
→ <Trace>: waypoint trajectory hint
→ <ActionHint>: movement direction prediction
→ <Action>: [VQ action tokens × 16 steps]
The model names the current subtask, localizes the target with a bounding box, hints at the trajectory, then generates action tokens. This structured reasoning makes G0.5 far more robust on long-horizon tasks — it's not reacting to the current frame, it's executing a legible plan.
Visual Memory: 6 Frames Over 5 Seconds
For multi-step manipulation tasks (stacking, inserting, long-reach), G0.5 doesn't just see the current frame. It receives 6 frames sampled over a 5-second window, processed via the vision encoder with factorized spatial-temporal attention — spatial attention for per-frame understanding, temporal attention for tracking motion across frames.

Checkpoints & Benchmark Results
Available Checkpoints on HuggingFace
| Checkpoint | Size | Purpose |
|---|---|---|
g05-base |
~11 GB | General fine-tuning; R1 Lite/Pro zero-shot |
g05-so101 |
~11 GB | SO-100/101 arm deployment |
g05-droid |
~11 GB | DROID/Franka deployment |
g05-libero |
~11 GB | LIBERO simulation evaluation |
g05-robotwin20 |
~11 GB | RoboTwin 2.0 evaluation |
action_tokenizer.pt |
~484 MB | VQ tokenizer (required) |
qwen3_5_2b_base_processor |
~22 MB | Vision processor |
Download only what you need:
huggingface-cli download OpenGalaxea/G05 \
--local-dir ./checkpoints/g05-base \
--include "g05-base/*" "action_tokenizer.pt" "qwen3_5_2b_base_processor/*"
Benchmark Results
| Benchmark | Condition | Success Rate |
|---|---|---|
| LIBERO | Fine-tuned, 50 trials/task | 98.9% |
| RoboTwin 2.0 | Fine-tuned | 93.3% |
| Bridge-SimplerEnv | Zero-shot | 87.3% |
| DROID | Zero-shot | 82.5% |
| BEHAVIOR-1K | Zero-shot | 0.3136 TSS |
| Real robot (R1 Lite/Pro) | Fine-tuned | 76.7% avg |
LIBERO at 98.9% is among the highest published for any VLA — OpenVLA achieves 60–70% on the same benchmark. The zero-shot DROID result (82.5%) is arguably more impressive: G0.5 transfers to Franka arms without any Franka-specific fine-tuning.
All fine-tuning evaluations used 16x H20 GPUs, 4–10 hours per task. The compute budget was held constant across all compared models for fairness.
Installation
System Requirements
- Linux (Ubuntu 22.04+)
- Python
>=3.10.16, <3.11(strict — 3.11 breaks some dependencies) - CUDA 12.8, PyTorch 2.7.1
- GPU: ≥8 GB VRAM for inference; ≥70 GB for full fine-tuning (A100 80GB or H20 96GB)
- FFmpeg for video dataset processing
Install with uv
G0.5 uses uv instead of pip — typically 10–100× faster for resolving complex ML dependency trees:
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.local/bin/env
# Clone repo
git clone https://github.com/OpenGalaxea/GalaxeaVLA
cd GalaxeaVLA
# Create virtualenv and install all dependencies
uv sync --index-strategy unsafe-best-match
source .venv/bin/activate
# Install system dependencies
sudo apt update && sudo apt install -y ffmpeg
# Verify
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"
Fine-Tuning G0.5 on Your Own Tasks
The typical workflow: collect 50–200 demonstrations via VR teleoperation, convert to LeRobot format, then fine-tune the base checkpoint. See the LeRobot hands-on guide for detailed data collection and formatting.
Step 1: Prepare a LeRobot Dataset
G0.5 expects LeRobot format (video + Parquet):
my_task_dataset/
meta/
info.json # camera names, fps, action dimensions
tasks.jsonl # ["Pick up the red block and place on tray"]
episodes.jsonl
data/
chunk-000/
episode_000000.parquet
episode_000001.parquet
videos/
chunk-000/
observation.images.head_rgb/
episode_000000.mp4
observation.images.wrist_rgb/
episode_000000.mp4
Step 2: Create a Task Config
cp configs/task/r1lite.yaml configs/task/my_pick_task.yaml
Edit configs/task/my_pick_task.yaml:
# @package _global_
defaults:
- override /data: r1lite/eef_torso # or your robot config
- override /model: vla/g05
model:
pretrained_ckpt: ./checkpoints/g05-base/checkpoints/model_state_dict.pt
action_tokenizer_path: ./checkpoints/g05-base/action_tokenizer.pt
data:
dataset:
dataset_dirs:
- /path/to/my_task_dataset
action_norm:
type: "gaussian" # normalize from dataset stats
training:
num_epochs: 50
batch_size: 8
learning_rate: 1.0e-5
grad_accumulation_steps: 4
precision: "bf16"
Step 3: Run Fine-Tuning
# Set environment variables
export G05_OUTPUT_DIR=./outputs/my_pick_task
export HF_HOME=./hf_cache
export HF_HUB_CACHE=./hf_cache
# Single GPU (with gradient accumulation)
bash scripts/run/finetune.sh 1 configs/task/my_pick_task.yaml \
model.batch_size=4 \
model.grad_accumulation_steps=8
# Multi-GPU (8× H100/A100)
bash scripts/run/finetune.sh 8 configs/task/my_pick_task.yaml
Typical times: 100 demos, single RTX 4090, 50 epochs ≈ 4–6 hours.
Monitor training:
tensorboard --logdir ./outputs/my_pick_task/tensorboard
Common Fine-Tuning Issues
| Symptom | Cause | Fix |
|---|---|---|
| NaN loss from epoch 1 | bf16 overflow | Lower learning_rate to 5e-6 |
| CUDA OOM | Batch too large | Reduce batch_size, increase grad_accumulation_steps |
| Robot ignores language | tasks.jsonl format error |
Use short imperative: "Pick up the cup" |
| Actions in wrong direction | Wrong coordinate frame | Check action_space: absolute vs relative |
Deploying to Real Robots
For a deep dive into the full deployment pipeline with G0Tiny on Jetson Orin, see the G0Tiny LeRobot fine-tune guide.
Galaxea R1 Lite
# Start policy server on GPU machine
python scripts/serve_policy.py \
--ckpt_path ./outputs/my_pick_task/checkpoints/model_state_dict.pt \
--host 0.0.0.0 \
--port 8080 \
--device cuda \
eval_embodiment=galaxea_r1lite
The robot-side ROS2 node connects to port 8080 over the local network and receives action chunks at ~10 Hz.
Galaxea R1 Pro (Multi-Frame)
R1 Pro sends historical frames, so use serve_policy_mem.py:
python scripts/serve_policy_mem.py \
--ckpt_path ./outputs/my_pick_task/checkpoints/model_state_dict.pt \
--host 0.0.0.0 \
--port 8080 \
--device cuda \
eval_embodiment=galaxea_r1pro \
num_history_frames=6
SO-100 / SO-101 Arms
cd experiments/so100/
# Configure in so100_config.yaml (server IP, task string, etc.)
python run_so100_client.py \
--server_host 192.168.1.100 \
--server_port 8080 \
--task "Pick up the block and place it in the box"
DROID / Franka
DROID uses a separate client repo:
git clone https://github.com/OpenGalaxea/droid-franka-client
cd droid-franka-client
pip install -e .
python run_droid_client.py \
--policy_host 192.168.1.100 \
--policy_port 8080 \
--task "place the mug on the plate"
G0.5 vs Other VLAs: Where It Stands
| G0.5 | G0 Plus | OpenVLA-OFT | π0-FAST | |
|---|---|---|---|---|
| Architecture | Unified AR | Dual-system | Transformer + flow | Flow-matching |
| Backbone | Qwen3.5 2B | PaliGemma 3B | Llama 2 7B | PaliGemma 3B |
| Embodiments | 14 (cross) | 1 (single) | Cross (OXE) | Benchmark only |
| LIBERO | 98.9% | N/A | ~82% | ~95% |
| DROID zero-shot | 82.5% | N/A | ~45% | ~60% |
| Chain-of-Thought | ✅ Native | ❌ | ❌ | ❌ |
| Open-source | ✅ | ✅ | ✅ | ❌ |
| Edge variant | G0Tiny (250M) | G0Tiny | None | None |
The critical practical advantage: native chain-of-thought means debuggable failures. When your robot misses a grasp, you can read the reasoning trace and see exactly where the model went wrong — wrong bounding box, wrong subtask, wrong trajectory hint. No other mainstream VLA gives you this.
For a broader survey of the VLA landscape, see AI Series #5: VLA Models Overview.
Licensing
G0.5 uses a tiered license based on commit date:
- Pre-Jan 4, 2026 commits: Apache 2.0 (fully open)
- Jan 4 – Jun 15, 2026: G0 PLUS Community License (non-commercial)
- Jun 16, 2026 onward: G0.5 Community License (non-commercial + limited patent)
- Qwen3.5 components: Apache 2.0
Research, prototyping, and internal demos: free. Commercial product deployment: contact Galaxea for a commercial license.
Summary
GalaxeaVLA G0.5 makes a strong case that unified autoregressive VLA — one model, one token stream, one loss — is the right direction for manipulation policies. The numbers back it up: 98.9% on LIBERO, 82.5% zero-shot on DROID, deployed on 4 different robot platforms with a clean config-based workflow.
Three things worth carrying forward from this guide:
- ActionCodec is the architectural keystone: Learned cross-embodiment action tokenization is what makes it possible to pre-train on 14 robots simultaneously and actually benefit from the diversity
- Chain-of-thought is a production feature, not a research novelty: The ability to read reasoning traces makes failure analysis tractable at scale
uv+ YAML configs = reproducible fine-tuning: The setup is more reproducible than most prior VLA frameworks — same YAML, same hardware, same result



