MiniVLA là một nhánh thực dụng của họ OpenVLA: giữ cách nhìn vision-language-action nhưng giảm kích thước từ mô hình 7B xuống khoảng 1B parameters, dùng Qwen 2.5 0.5B làm language backbone, thêm Vector Quantized action chunking, rồi mở rộng đầu vào bằng image history hoặc wrist camera. Điểm hấp dẫn của MiniVLA không chỉ là nhỏ hơn. Nó cho phép một nhóm nhỏ có thể iterate policy manipulation nhanh hơn, chạy evaluation nhiều lần hơn, và test robustness trong mô phỏng MuJoCo trước khi nghĩ đến robot thật.
Bài này hướng dẫn theo hướng beginner nhưng vẫn đủ chi tiết để bạn tự chạy: đọc ý tưởng gốc, hiểu architecture, cài môi trường, chạy LIBERO/MuJoCo evaluation, thêm perturbation để đánh giá robustness, train hoặc fine-tune lại, inference, và đọc kết quả. Chủ đề có cụm "MiniVLA V3" và mốc 97,92% success rate. Cần nói rõ ngay từ đầu: trong nguồn public mình kiểm tra được, paper/blog chính thức gọi là MiniVLA, MiniVLA VQ h8, MiniVLA history=2, hoặc MiniVLA wrist images, không thấy một paper chính thức tên "MiniVLA V3" gắn với MuJoCo và 97,92%. Vì vậy trong bài này, "V3" được dùng như một tên thực hành cho cấu hình thế hệ thứ ba: MiniVLA 1B + VQ action chunking + multi-image/history + robustness evaluation trên LIBERO/robosuite/MuJoCo. Mốc 97,92% được trình bày như target/reported-run metric bạn phải tự xác nhận bằng log rollout, ví dụ 47/48 trial thành công hoặc 235/240 trial thành công, không phải con số mình gán cho paper gốc nếu paper không công bố.
Nguồn chính:
- Stanford SAIL Blog: MiniVLA: A Better VLA with a Smaller Footprint
- GitHub gốc: Stanford-ILIAD/openvla-mini
- Repo triển khai edge/TensorRT: Zhenxintao/MiniVLA
- Weights: xintaozhen/MiniVLA và Stanford-ILIAD/minivla-vq-libero90-prismatic
- Benchmark: LIBERO trên nền robosuite/MuJoCo
- Simulator layer: robosuite và MuJoCo
Nếu bạn mới bước vào VLA, đọc trước VLA và LeRobot: framework tổng quan. Nếu bạn chưa quen simulator, đọc Getting Started with MuJoCo trước khi debug lỗi OpenGL, camera, XML asset hoặc offscreen rendering.
Ý tưởng paper: nhỏ hơn, nhanh hơn, nhưng không bỏ action structure
OpenVLA chứng minh hướng "VLM sinh action token" có thể dùng cho robot manipulation. Nhưng mô hình 7B khiến training và inference nặng: GPU memory cao, latency cao, khó chạy nhiều ablation. MiniVLA đặt câu hỏi thực tế hơn: nếu giữ visual encoder kiểu Prismatic/OpenVLA, nhưng thay Llama 2 7B bằng Qwen 2.5 0.5B, policy có giữ được success rate không? Theo Stanford SAIL Blog, MiniVLA giảm footprint từ 7B xuống khoảng 1B parameters và trên LIBERO-90 có thể đạt mức gần OpenVLA base: OpenVLA 62%, MiniVLA 61,4% khi cùng trained tới 95% action accuracy.
Đóng góp quan trọng hơn nằm ở action representation. OpenVLA cơ bản rời rạc hóa từng chiều action thành bin token. Cách này đơn giản, nhưng robot manipulation hiếm khi chỉ cần một action độc lập. Khi gắp bát, đóng ngăn kéo, đặt sách, chuyển động tốt thường là một đoạn trajectory ngắn, liên tục, có quán tính và có pha tiếp cận/rút lui. MiniVLA dùng Residual VQ để nén một chunk action (H x A) thành các codeword index. Mô hình không phải sinh 8 action liên tục dưới dạng số thực; nó sinh token đại diện cho chunk hành động đã học từ demonstration. Trong kết quả blog, MiniVLA + VQ h8 tăng LIBERO-90 từ 61,4% lên 77%.
Bước thứ ba là multi-image. Robot tabletop thường cần biết trạng thái trước đó: gripper đang mở hay đóng, object vừa bị đẩy lệch chưa, drawer đã nhúc nhích chưa. Một ảnh đơn dễ thiếu vận tốc ngầm và lịch sử tiếp xúc. MiniVLA thêm history=2 hoặc wrist images; blog báo cáo MiniVLA VQ h8 + history=2 đạt 82% và + wrist images đạt 82,1% trên LIBERO-90. Đây là lý do bài này gọi cấu hình thực hành là "V3": base nhỏ hơn, action chunking, và multi-image/robustness loop.
Vì sao nói LIBERO là MuJoCo?
Nhiều người đọc README thấy lệnh run_libero_eval.py rồi nghĩ đây không phải MuJoCo vì không trực tiếp gọi mujoco.viewer. Thực tế LIBERO dùng môi trường manipulation trên robosuite, còn robosuite là framework robot learning chạy trên MuJoCo physics engine. Vì vậy khi bạn chạy LIBERO evaluation cho MiniVLA, bạn đang chạy policy trong pipeline camera, object, controller và contact dynamics do robosuite/MuJoCo cung cấp.
Điều này quan trọng khi đánh giá robustness. Một VLA có thể đạt điểm tốt ở seed mặc định nhưng fail khi:
- object pose lệch vài centimet;
- camera crop khác training;
- ánh sáng/rendering thay đổi;
- action horizon không khớp VQ tokenizer;
- gripper threshold hoặc controller frequency sai;
- task language paraphrase khác câu huấn luyện;
- drawer/cabinet contact cần lực nhưng policy chỉ học motion đẹp.
Do đó, đừng đọc một success rate duy nhất như "năng lực tổng quát". Hãy coi nó là kết quả của một evaluation protocol cụ thể: task suite nào, bao nhiêu trial, seed nào, camera nào, checkpoint nào, perturbation nào, và success predicate nào.
Kiến trúc chạy thực tế
Pipeline bạn sẽ chạy gồm bốn lớp:
Instruction + RGB image/history/wrist
|
v
Vision encoder: DINOv2 / SigLIP style ViT
|
v
Qwen 2.5 0.5B language backbone inside Prismatic VLM
|
v
Action tokenizer:
- base binning for single action, or
- VQ h8 chunk tokenization for short horizon
|
v
LIBERO environment on robosuite/MuJoCo
|
v
success/failure, video rollout, latency, perturbation logs
Repo Zhenxintao/MiniVLA thêm một lớp deployment thực dụng: vision encoder có thể export sang ONNX/TensorRT và chạy qua microservice. Bản baseline PyTorch trong README dùng khoảng 4115 MiB trên RTX 4060 Laptop GPU 8 GB, còn TensorRT vision-only giảm còn khoảng 3892 MiB và latency end-to-end từ 365 ms xuống 274 ms. Nhưng full Vision+LLM TensorRT cho latency thấp hơn nữa lại tạo output invalid và success 0%. Kết luận thực dụng: nếu mục tiêu là robustness, tối ưu vừa đủ. Đừng hy sinh action correctness chỉ để có latency đẹp.
Chuẩn bị máy
Bạn nên dùng Ubuntu 22.04, Python 3.10, CUDA 12.x, GPU NVIDIA tối thiểu 8 GB để inference/eval nhẹ. Nếu full training hoặc train từ đầu, cần GPU mạnh hơn nhiều; README OpenVLA-Mini dùng ví dụ 8 GPU cho training config. Với beginner, mục tiêu hợp lý là:
- cài môi trường;
- tải checkpoint có sẵn;
- chạy 5-10 trial sanity;
- chạy 48 hoặc 240 trial robustness;
- chỉ sau đó mới fine-tune.
Lệnh cài cơ bản:
conda create -n minivla python=3.10 -y
conda activate minivla
conda install pytorch torchvision torchaudio pytorch-cuda=12.4 -c pytorch -c nvidia -y
git clone https://github.com/Stanford-ILIAD/openvla-mini.git
cd openvla-mini
pip install -e .
pip install packaging ninja
pip install "flash-attn==2.5.5" --no-build-isolation
git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git
cd LIBERO
pip install -e .
cd ../openvla-mini
pip install -r experiments/robot/libero/libero_requirements.txt
Nếu bạn dùng repo Zhenxintao/MiniVLA để thử TensorRT vision service:
git clone https://github.com/Zhenxintao/MiniVLA.git
cd MiniVLA
pip install -e .
cd tensorRT-scripts
python tensorRT_vision_service.py
Ở bước đầu, đừng bật TensorRT ngay. Hãy chạy baseline PyTorch trước để biết checkpoint, VQ path, LIBERO data và rendering đều đúng. Khi baseline ổn, bạn mới thay vision backbone bằng TensorRT và so lại success.
Tải checkpoint và VQ tokenizer
Cấu hình MiniVLA VQ cần hai phần: checkpoint Prismatic và VQ-VAE action tokenizer. Ví dụ:
mkdir -p ~/models
cd ~/models
git lfs install
git clone https://huggingface.co/Stanford-ILIAD/minivla-vq-libero90-prismatic
cd ~/openvla-mini
mkdir -p vq
huggingface-cli download Stanford-ILIAD/pretrain_vq \
--local-dir ./vq \
--local-dir-use-symlinks False
Kiểm tra structure:
~/models/minivla-vq-libero90-prismatic/checkpoints/*.pt
~/openvla-mini/vq/pretrain_vq+mx-libero_90+fach-7+ng-7+nemb-128+nlatent-512/
checkpoints/model.pt
config.json
Nếu thiếu VQ tokenizer, lỗi thường không nằm ở MuJoCo mà nằm ở action decoder: model sinh token nhưng không giải mã đúng thành chunk action. Với VLA manipulation, đây là lỗi rất nguy hiểm vì policy có thể vẫn "chạy" nhưng action scale sai, gripper đảo chiều, hoặc robot đứng im.
Smoke test LIBERO/MuJoCo
Chạy evaluation nhỏ trước:
python experiments/robot/libero/run_libero_eval.py \
--model_family prismatic \
--pretrained_checkpoint ~/models/minivla-vq-libero90-prismatic/checkpoints/step-150000-epoch-67-loss=0.0934.pt \
--task_suite_name libero_90 \
--center_crop True \
--hf_token $HF_TOKEN \
--num_trials_per_task 1
Kỳ vọng của smoke test không phải success rate cao. Kỳ vọng là:
- MuJoCo/robosuite render được offscreen image;
- checkpoint load không lỗi;
- VQ tokenizer path đúng;
- policy output action đúng shape 7-DoF;
- video rollout được lưu;
- task success/failure được log rõ.
Nếu lỗi GL, EGL, mujoco_py, robosuite==1.4.0, hoặc camera blank, dừng ở đây. Đừng train. Đừng chỉnh prompt. Sửa simulator trước. Một VLA evaluation không có image đúng là vô nghĩa.

Thiết kế robustness test để đạt hoặc bác bỏ 97,92%
Mốc 97,92% rất dễ bị hiểu sai. 97,92% tương đương:
| Tổng trial | Success | Success rate |
|---|---|---|
| 48 | 47 | 97,9167% |
| 96 | 94 | 97,9167% |
| 240 | 235 | 97,9167% |
| 480 | 470 | 97,9167% |
Với robotics, 47/48 chưa đủ mạnh để claim general robustness. Nó là dấu hiệu tốt cho một task set hẹp. Nếu muốn viết báo cáo kỹ thuật nghiêm túc, dùng ít nhất 240 trial, chia theo task, seed, perturbation và paraphrase. Một protocol beginner có thể như sau:
Tasks:
8 LIBERO desktop manipulation tasks
Trials:
6 seeds per task = 48 trials for quick check
30 seeds per task = 240 trials for publishable internal report
Perturbations:
P0: default scene
P1: object xy shift ±2 cm
P2: object yaw shift ±10 deg
P3: camera crop jitter 0.90-1.00
P4: language paraphrase
P5: distractor object present
Metrics:
success_rate
mean_steps_to_success
failure_mode
invalid_action_rate
gripper_misfire_rate
wall_clock_latency_ms
Đừng chỉ log success=True/False. Ghi failure mode. Một policy fail vì không chạm được object khác hẳn fail vì chạm đúng nhưng không đủ lực đóng drawer. Với MiniVLA, các lỗi hay gặp là: action chunk quá dài nên overshoot, camera crop lệch nên nhận nhầm object, gripper đóng muộn, hoặc policy kẹt ở sub-step vì image history không đúng thứ tự training.
Cách thêm perturbation nhẹ
Tùy version LIBERO, bạn có thể cần sửa wrapper environment hoặc task initial state. Beginner nên bắt đầu bằng perturbation không đụng sâu vào XML:
import random
import numpy as np
def sample_eval_case(seed: int):
rng = random.Random(seed)
return {
"seed": seed,
"object_xy_jitter": np.array([
rng.uniform(-0.02, 0.02),
rng.uniform(-0.02, 0.02),
]),
"object_yaw_jitter_deg": rng.uniform(-10.0, 10.0),
"center_crop": rng.choice([True, True, False]),
"language_variant": rng.choice([
"put the black bowl in the tray",
"pick up the black bowl on the left and place it in the tray",
"move the left black bowl into the tray",
]),
}
Sau đó truyền seed vào env reset, thay instruction nếu evaluation script cho phép, và lưu một JSONL log:
{"task":"black_bowl_to_tray","seed":17,"perturb":"P1+P4","success":true,"steps":142,"latency_ms":281}
{"task":"black_bowl_to_tray","seed":18,"perturb":"P1+P4","success":false,"steps":400,"failure":"gripper_closed_late"}
Nếu bạn chưa từng viết wrapper cho LIBERO, hãy đọc code experiments/robot/libero/run_libero_eval.py trước. Tìm các điểm: tạo benchmark suite, lấy task, reset env, lấy image observation, gọi policy, step env, kiểm tra success. Bạn chỉ cần can thiệp quanh reset và language instruction; đừng sửa model trước khi có baseline.
Training và fine-tuning
Có ba mức training:
| Mức | Khi nào dùng | Chi phí |
|---|---|---|
| Chạy checkpoint có sẵn | Học pipeline, benchmark, robustness | thấp |
| Fine-tune trên task suite mới | Có demonstration của robot/task riêng | trung bình đến cao |
| Train MiniVLA từ đầu | Nghiên cứu architecture hoặc dataset lớn | rất cao |
Ví dụ training MiniVLA trên LIBERO-90 từ README:
torchrun --standalone --nnodes 1 --nproc-per-node 8 vla-scripts/train.py \
--vla.type "prism-qwen25-dinosiglip-224px+0_5b+mx-libero-90" \
--data_root_dir <PATH_TO_LIBERO_DATA_ROOT> \
--run_root_dir <PATH_TO_LOG_CHECKPOINT_ROOT> \
--wandb_project "<PROJECT>" \
--wandb_entity "<ENTITY>"
Với VQ action chunking, bạn cần train hoặc tải VQ trước. Ý tưởng là VQ học codebook cho action chunks, sau đó VLA học sinh codeword token. Nếu bạn đổi robot, action dimension, frequency hoặc horizon, đừng dùng lại VQ cũ một cách mù quáng. Ví dụ action dim 7 ở LIBERO thường là delta pose + gripper; robot khác có joint position 6D hoặc bimanual 14D sẽ cần tokenizer khác.
Nếu mục tiêu là 97,92% trên một set task hẹp, fine-tune thường hiệu quả hơn prompt engineering. Nhưng fine-tune phải có dữ liệu phủ đủ perturbation. OpenVLA-Mini README cũng nhấn mạnh data collection nên liên tục, ít pause, đủ đa dạng initial condition và control frequency hợp lý khoảng 5-10 Hz cho model không chunking. Với chunking, bạn vẫn cần nhất quán giữa frequency train và inference.
Inference loop
Inference conceptually rất đơn giản:
obs = env.reset()
instruction = task.language
for t in range(max_steps):
image = obs["agentview_image"]
wrist = obs.get("robot0_eye_in_hand_image")
state = obs.get("robot_state")
action = policy.predict_action(
image=image,
instruction=instruction,
state=state,
do_sample=False,
)
obs, reward, done, info = env.step(action)
if info.get("success", False):
break
Trong code thật, phần khó là preprocessing. Bạn phải dùng đúng crop, đúng image order, đúng tokenizer, đúng unnormalization key, đúng dtype. Với multi-image, README cảnh báo image phải đưa vào đúng thứ tự và đúng số lượng như training vì token sequence chỉ là concat image1_tokens image2_tokens ..., không có tag rõ ràng cho camera nào. Nếu train history=2 mà inference chỉ đưa một ảnh hiện tại, success rate có thể tụt mạnh nhưng lỗi không hiện thành exception.

Đọc kết quả
Kết quả đã công bố từ Stanford MiniVLA:
| Cấu hình | LIBERO-90 success |
|---|---|
| OpenVLA | 62% |
| MiniVLA | 61,4% |
| MiniVLA + VQ h8 | 77% |
| MiniVLA + VQ h8 + history=2 | 82% |
| MiniVLA + VQ h8 + wrist images | 82,1% |
Kết quả repo Zhenxintao/MiniVLA cho deployment:
| Cấu hình | Latency | Memory | Success |
|---|---|---|---|
| Baseline PyTorch | 365 ms | 4115 MiB | 80,0% |
| TensorRT vision-only | 274 ms | 3892 MiB | 75,5% |
| TensorRT vision + LLM | 192 ms | 3292 MiB | 0,0% |
Nếu log của bạn ghi 47/48 success, bạn có thể báo cáo:
MiniVLA V3-style configuration:
checkpoint: minivla-vq-libero90-prismatic
eval: 8 tasks x 6 seeds
simulator: LIBERO on robosuite/MuJoCo
perturbations: object xy ±2 cm, yaw ±10 deg, paraphrase
success: 47/48 = 97.92%
Nhưng nếu chỉ có 48 trial, hãy gọi là "quick robustness check". Để claim mạnh hơn, hãy chạy 240 trial:
success_rate = 235 / 240 = 97.92%
95% Wilson confidence interval should be reported.
Khi success rate cao, vẫn xem video failure. Một failure duy nhất có thể chỉ ra bug nghiêm trọng: policy không nhận ra object màu đen khi ánh sáng đổi, hoặc gripper đóng sai pha khi object ở mép tray. Đó là thông tin quan trọng hơn phần trăm đẹp.
Checklist debug
| Triệu chứng | Nguyên nhân thường gặp | Cách kiểm tra |
|---|---|---|
| Robot đứng im | VQ path sai, action token decode sai | in action norm và gripper command |
| Robot vung quá mạnh | action scale/unnormalization sai | replay demo action trong env |
| Success thấp khi bật TensorRT | vision embedding mismatch | so cosine embedding PyTorch vs TRT |
| Camera đen | EGL/OpenGL/offscreen render | lưu frame đầu tiên ra PNG |
| History model fail | sai thứ tự image | log shape và thứ tự camera |
| Seed tốt, perturb fail | data quá hẹp | thêm demonstration có object pose đa dạng |
Nếu bạn muốn test policy robustness sâu hơn, đọc thêm StressDREAM cho robot manipulation policy test. Nếu muốn đi tiếp sang fine-tuning và deploy, xem PEFT và deploy VLA.
Kết luận
MiniVLA đáng học vì nó làm VLA manipulation bớt xa vời: nhỏ hơn OpenVLA, nhanh hơn, có action chunking, có multi-image, và có repo thực tế để thử inference/deployment. LIBERO/robosuite/MuJoCo là nơi phù hợp để đánh giá trước khi robot thật chịu rủi ro. Nhưng hãy nghiêm túc với mốc 97,92%: nó chỉ có ý nghĩa khi bạn công khai task set, số trial, seed, perturbation, checkpoint, success predicate và log failure.
Với beginner, mục tiêu tốt nhất không phải là lập tức đạt một con số đẹp. Mục tiêu là dựng được pipeline lặp lại: baseline chạy được, media rollout nhìn đúng, perturbation log rõ, action decode đúng, rồi mới fine-tune. Khi pipeline đó sạch, success rate cao mới đáng tin.



