Hầu hết VLA model đang mắc kẹt trong thế tiến thoái lưỡng nan: muốn đủ mạnh thì phải đủ nặng. π₀ cần 3.5B tham số, OpenVLA cần 7B — những con số đó đồng nghĩa với GPU A100 hoặc H100 chỉ để chạy inference ở 4–5 Hz. Deploy trong lab thì được, nhưng trên robot edge giá rẻ? Gần như không thể.
EVO1 từ nhóm MINT Lab tại Shanghai Jiao Tong University thách thức điều đó. Chỉ 0.77B tham số, nhưng trên benchmark thực tế nó vượt SmolVLA (2.25B), OpenVLA-OFT (7B), và thậm chí cả π₀ (3.5B) trên nhiều task manipulation. Quan trọng hơn: nó chạy ở 16.4 Hz với chỉ 2.3 GB VRAM — đủ để deploy real-time trên robot mà không cần offload lên cloud.
Bài viết này là hướng dẫn đầy đủ để fine-tune EVO1 trên robot SO-101 sử dụng LeRobot v0.6.0 — phiên bản đã tích hợp EVO1 như một policy type chuẩn.
EVO1 là gì?
EVO1 được giới thiệu trong paper "Evo-1: Lightweight Vision-Language-Action Model with Preserved Semantic Alignment" bởi nhóm MINT Lab (Shanghai Jiao Tong University), công bố trên arXiv tháng 11/2025 và được chấp nhận tại CVPR 2026 (Efficient CVPR Badge).
Tên "Evo" gợi lên hướng tiếp cận: evolution — không scale model to hơn như xu hướng chung, mà tìm cách "tiến hóa" kiến trúc để đạt hiệu quả tốt hơn với ít tham số hơn. Đóng góp kỹ thuật cốt lõi là two-stage training paradigm bảo toàn "semantic alignment" của VLM backbone trong khi vẫn dạy model điều khiển robot.
Tại sao "semantic alignment" lại quan trọng? Khi bạn fine-tune một VLM (InternVL3, LLaVA) trực tiếp cho robot end-to-end ngay từ đầu, VLM sẽ bắt đầu "quên" ý nghĩa ngôn ngữ-hình ảnh gốc của nó — nó học cách khớp token với hành động nhưng mất khả năng hiểu ngữ cảnh. Kết quả: model không generalize khi gặp task hoặc object chưa thấy trong training data. EVO1 giải quyết đúng vấn đề này.
Kiến trúc EVO1
Kiến trúc tổng thể EVO1 — nguồn: MINT-SJTU/Evo-1
EVO1 gồm ba khối chính kết nối tuần tự:
1. InternVL3-1B Backbone
Backbone là InternVL3-1B, kết hợp hai component:
- InternViT-300M: vision encoder xử lý ảnh camera ở độ phân giải 448×448
- Qwen2.5-0.5B (14 layers đầu): language decoder hiểu task instruction
Lý do chọn InternVL3? Model này được pre-train theo paradigm native multimodal — vision và language được train cùng lúc từ đầu, không phải ghép hai model riêng lại. Điều này tạo ra cross-modal alignment chặt chẽ hơn nhiều so với các VLM ghép nối. Khi fine-tune cho robot, alignment này là thứ cần giữ để model generalize.
2. Integration Module
Đây là điểm độc đáo nhất của EVO1 so với các kiến trúc VLA khác. Thay vì lấy output của VLM layer cuối cùng và đẩy vào action head, Integration Module lấy mid-layer features của InternVL3 và concatenate trực tiếp với proprioceptive state (joint angles + gripper state của robot).
Tại sao mid-layer? Features ở layer giữa VLM mang nhiều thông tin spatial và semantic hơn layer cuối. Layer cuối thường bị "collapse" về phân phối token hẹp, phục vụ cho language generation chứ không phải robot control. Bằng cách hook vào đây, action head nhận được biểu diễn phong phú hơn mà không cần unroll toàn bộ VLM.
3. Cross-modulated Diffusion Transformer (DiT)
Action head là một Diffusion Transformer sử dụng flow-matching:
- Query: action tokens có noise (random initialization)
- Key-Value: multimodal embeddings từ Integration Module kết hợp với state vector
- Cross-attention học cách "denoising" action chunk dựa trên visual + language context
- Output: chunk 50 actions liên tục (joint positions)
Flow-matching ở đây là continuous normalizing flow — không phải DDPM hay DDIM truyền thống với 100+ denoising steps. EVO1 chỉ cần 32 denoising steps để sample một action chunk hoàn chỉnh, đây là lý do chính giải thích tại sao inference đạt 16.4 Hz.
So sánh: SmolVLA dùng kiến trúc tương tự nhưng không có Integration Module và two-stage training — đó là lý do EVO1 generalize tốt hơn dù nhỏ hơn bản SmolVLA đầy đủ (2.25B). Đọc thêm chi tiết về SmolVLA architecture để thấy sự khác biệt cụ thể.
Tại sao Two-Stage Training là Chìa khóa?
Đây là đóng góp kỹ thuật cốt lõi nhất của paper và cũng là thứ tạo ra sự khác biệt thực sự khi deploy.
Nếu bạn fine-tune toàn bộ VLM + action head cùng lúc ngay từ đầu, gradient từ action loss (điều khiển khớp robot) sẽ "distort" representations trong VLM — model học những pattern lạ phục vụ actuator thay vì giữ nguyên semantic understanding gốc. Attention map của VLM sẽ bắt đầu "nhìn sai chỗ" — thay vì focus vào object mà task đề cập, nó focus vào các vùng ảnh tương quan với hành động cơ học.
Stage 1 — Warmup Action Head (5,000 steps):
- Freeze hoàn toàn InternVL3 backbone
- Chỉ train Integration Module và DiT action head
- VLM cung cấp features ổn định, action head học decode chúng thành actions
- Kết quả: action head có warm start tốt, gradient ổn định
Stage 2 — Joint Fine-tuning (lên đến 80,000 steps):
- Unfreeze VLM, train toàn bộ end-to-end
- Action head đã có warm start → gradient không còn "sốc" VLM
- VLM được fine-tune nhẹ nhàng, giữ được semantic alignment
- Kết quả: model generalize sang object unseen nhờ VLM vẫn "hiểu" ngôn ngữ
Kết quả kiểm chứng: attention map của VLM sau Stage 2 vẫn focus đúng vào object được nhắc đến trong task instruction, trong khi các baseline fine-tune end-to-end từ đầu thường bị attention collapse.
Kết quả Benchmark

| Benchmark | EVO1 (0.77B) | SmolVLA (2.25B)¹ | π₀ (3.5B) | OpenVLA-OFT (7B) |
|---|---|---|---|---|
| Meta-World MT50 | 80.6% | 68.2% | 47.9% | — |
| RoboTwin (bimanual) | 37.8% | — | 30.9% | — |
| Real-world xArm6 | 78% | 50% | 73% | 55% |
| Inference tốc độ | 16.4 Hz | ~12.7 Hz | ~11.5 Hz | ~7.9 Hz |
| VRAM (inference) | 2.3 GB | ~2.0 GB | ~17.9 GB | ~15.1 GB |
¹ SmolVLA trong benchmark paper dùng bản đầy đủ với PaliGemma backbone (2.25B). SmolVLA-Base là 450M nhưng đó là phiên bản chưa có VLM.
LeRobot LIBERO, Stage 2 checkpoint tại 70,000 steps (single run, seed 1000):
| Suite | Số episodes thành công | Tổng | Success Rate |
|---|---|---|---|
| LIBERO Spatial | 485 | 500 | 97.0% |
| LIBERO Object | 496 | 500 | 99.2% |
| LIBERO Goal | 483 | 500 | 96.6% |
| LIBERO-10 | 469 | 500 | 93.8% |
| Overall | 1,933 | 2,000 | 96.65% |
Đáng chú ý nhất: trên real robot (xArm6), EVO1 vượt cả π₀ — model lớn hơn gần 5 lần — với 78% so với 73%. Điều này chứng minh rằng semantic alignment preservation không chỉ là lý thuyết mà có tác động thực tế đến generalization trên hardware.
Cài đặt
Yêu cầu phần cứng và phần mềm
- Python 3.10+ và CUDA 11.8+
- Stage 1: GPU ≥ 12 GB VRAM (RTX 3060 12GB đủ)
- Stage 2: GPU ≥ 24 GB VRAM (RTX 4090 hoặc A100 khuyến nghị; RTX 3090 24GB với batch nhỏ)
- Inference: GPU ≥ 4 GB VRAM (RTX 3060 dư sức)
Cài đặt LeRobot với EVO1 extra
# Clone LeRobot v0.6.0
git clone https://github.com/huggingface/lerobot.git
cd lerobot
# Cài với evo1 extra (bao gồm InternVL3 và dependencies)
pip install -e ".[training,evo1]"
# Optional nhưng khuyến nghị: Flash Attention cho inference nhanh hơn ~20%
# Chỉ cài nếu Python + PyTorch + CUDA stack tương thích
pip install flash-attn --no-build-isolation
Lưu ý quan trọng về VLM checkpoint: policy.vlm_model_name BẮT BUỘC phải trỏ đến OpenGVLab/InternVL3-1B-hf — có hậu tố -hf. LeRobot dùng native HuggingFace transformers implementation của InternVL3, không phải implementation gốc từ MINT-SJTU repo. Thiếu hậu tố -hf sẽ lỗi tokenizer ngay từ đầu.
Lần chạy đầu tiên sẽ tự download checkpoint InternVL3-1B-hf về HuggingFace cache (~2GB). Các lần sau dùng cache.
Chuẩn bị Dữ liệu SO-101
EVO1 nhận input theo format LeRobot chuẩn. Với SO-101 (6 DOF + gripper = 7D action):
observation.images.top # Camera nhìn từ trên hoặc front-facing (bắt buộc)
observation.images.wrist # Camera gắn trên wrist (tùy chọn, cải thiện ~10-15%)
observation.state # Joint angles + gripper (7D: 6 khớp + 1 gripper)
action # Target joint positions (7D)
task # Chuỗi text mô tả task ("Pick up the red cube...")
Thu thập dữ liệu teleop
lerobot-record \
--robot.type=so101 \
--dataset.repo_id=your_hf_username/so101_pick_place \
--dataset.task="Pick up the red cube and place it in the bowl" \
--dataset.fps=30 \
--dataset.num_episodes=100 \
--cameras.top=0 \
--cameras.wrist=1
Số demonstrations cần thiết: 50–100 demo cho task đơn giản (pick and place một object). 100–200 demo cho task phức tạp hơn hoặc nếu muốn generalize sang multiple objects. EVO1 benefit từ VLM backbone mạnh — generalize tốt hơn SmolVLA với cùng lượng data, nhờ semantic understanding được bảo toàn.
Verify dataset
from lerobot.common.datasets.lerobot_dataset import LeRobotDataset
dataset = LeRobotDataset("your_hf_username/so101_pick_place")
print(f"Episodes: {dataset.num_episodes}")
print(f"Total frames: {len(dataset)}")
print(f"Features: {list(dataset.features.keys())}")
# Output mong đợi:
# Episodes: 100
# Total frames: ~9000 (90 frames/episode × 100)
# Features: ['observation.images.top', 'observation.images.wrist', 'observation.state', 'action', 'task', ...]
Fine-tune Stage 1: Warmup Action Head
Stage 1 freeze InternVL3 và chỉ train Integration Module + DiT action head. Nên chạy 5,000 steps — đủ để action head học coarse motion patterns mà không overfit.
lerobot-train \
--dataset.repo_id=your_hf_username/so101_pick_place \
--policy.type=evo1 \
--policy.training_stage=stage1 \
--policy.vlm_model_name=OpenGVLab/InternVL3-1B-hf \
--policy.device=cuda \
--policy.chunk_size=50 \
--policy.n_action_steps=50 \
--policy.max_state_dim=24 \
--policy.max_action_dim=24 \
--policy.dropout=0.2 \
--policy.optimizer_lr=1e-5 \
--policy.optimizer_weight_decay=1e-3 \
--policy.optimizer_grad_clip_norm=1.0 \
--policy.use_amp=true \
--policy.enable_gradient_checkpointing=true \
--policy.gradient_checkpointing_use_reentrant=false \
--batch_size=8 \
--steps=5000 \
--save_freq=2500 \
--output_dir=./outputs/evo1_so101_stage1
Giải thích các tham số quan trọng:
| Tham số | Giá trị | Lý do |
|---|---|---|
max_state_dim=24 |
24 | Pad 7D state SO-101 lên 24D để tương thích với pretrained checkpoint LIBERO |
max_action_dim=24 |
24 | Tương tự — policy tự crop về 7D trước khi gửi lệnh cho robot |
chunk_size=50 |
50 | Dự đoán 50 future actions mỗi lần inference |
n_action_steps=50 |
50 | Thực thi cả 50 steps trước khi re-plan |
use_amp=true |
true | Mixed precision BF16 → tiết kiệm VRAM ~30% |
enable_gradient_checkpointing=true |
true | Tiết kiệm VRAM thêm ~40%, đổi bằng tốc độ train chậm hơn ~20% |
dropout=0.2 |
0.2 | Regularization, quan trọng với dataset nhỏ |
Theo dõi tiến độ: Loss Stage 1 nên giảm từ ~0.08–0.12 xuống ~0.02–0.04 sau 5k steps. Nếu loss không giảm, kiểm tra format dataset (có đủ task field không?) và learning rate.
Checkpoint Stage 1 được lưu tại ./outputs/evo1_so101_stage1/checkpoints/005000/pretrained_model.
Fine-tune Stage 2: Joint VLM Fine-tuning
Stage 2 load checkpoint Stage 1 và unfreeze VLM để joint training — đây là bước quyết định chất lượng cuối cùng.
lerobot-train \
--dataset.repo_id=your_hf_username/so101_pick_place \
--policy.path=./outputs/evo1_so101_stage1/checkpoints/005000/pretrained_model \
--policy.training_stage=stage2 \
--policy.vlm_model_name=OpenGVLab/InternVL3-1B-hf \
--policy.device=cuda \
--policy.chunk_size=50 \
--policy.n_action_steps=50 \
--policy.max_state_dim=24 \
--policy.max_action_dim=24 \
--policy.dropout=0.2 \
--policy.optimizer_lr=1e-5 \
--policy.optimizer_weight_decay=1e-3 \
--policy.optimizer_grad_clip_norm=1.0 \
--policy.vlm_dtype=bfloat16 \
--policy.use_amp=true \
--policy.use_flash_attn=true \
--policy.enable_gradient_checkpointing=true \
--policy.gradient_checkpointing_use_reentrant=false \
--batch_size=4 \
--steps=80000 \
--save_freq=5000 \
--output_dir=./outputs/evo1_so101_stage2
Lưu ý về policy.training_stage=stage2: Flag này tự động áp dụng stage2 defaults — unfreeze VLM, enable joint fine-tuning. Bạn không cần truyền thêm --policy.finetune_vlm=true riêng. Nếu muốn kiểm soát thủ công, thêm --policy.apply_training_stage_defaults=false.
Bao nhiêu steps là đủ cho SO-101? Recipe LIBERO của paper dùng 80k steps với dataset lớn (2× H100, batch 128). Nhưng với SO-101, paper gốc chỉ train 50,000 steps (batch 16, 1× A100) và đạt 78% success rate trên real robot. Với 100 episodes dataset nhỏ hơn, thậm chí 30–40k steps đã đủ. Khuyến nghị: set --save_freq=5000, kiểm tra val loss, chọn checkpoint tốt nhất trước 50k.
Về policy.vlm_dtype=bfloat16: Stage 2 dùng BF16 cho VLM để tiết kiệm VRAM. GPU không support BF16 (trước RTX 30xx) thì đổi sang float16, nhưng BF16 ổn định hơn với gradient khi fine-tune LLM.
So sánh với MolmoAct2 SO-101 guide: workflow rất giống nhau nhưng MolmoAct2 chỉ cần single-stage với LoRA, trong khi EVO1 dùng hai stage full fine-tune. Trade-off: EVO1 train lâu hơn nhưng không cần LoRA adapter, inference đơn giản hơn.
Inference trên Robot SO-101

Sau khi train xong, dùng lerobot-rollout để run trên robot:
lerobot-rollout \
--policy.path=./outputs/evo1_so101_stage2/checkpoints/best \
--policy.vlm_model_name=OpenGVLab/InternVL3-1B-hf \
--policy.device=cuda \
--policy.use_amp=true \
--policy.vlm_dtype=bfloat16 \
--policy.use_flash_attn=true \
--policy.chunk_size=50 \
--policy.n_action_steps=14 \
--policy.max_state_dim=24 \
--policy.max_action_dim=24 \
--inference.type=rtc \
--robot.type=so101 \
--cameras.top=0 \
--cameras.wrist=1
--inference.type=rtc kích hoạt Real-Time Chunking (RTC) — tính năng mới của LeRobot v0.6.0. Thay vì chờ action chunk hiện tại thực thi xong rồi mới tính chunk tiếp theo (tuần tự), RTC tính toán chunk tiếp theo song song trong khi robot đang thực thi chunk hiện tại. Kết quả: giảm effective latency ~30%.
Tại sao n_action_steps=14 cho inference thay vì 50? Đây là trade-off có chủ ý: chunk lớn (50) → motion mượt hơn nhưng phản ứng chậm với disturbance, chunk nhỏ (14) → re-plan thường xuyên hơn → responsive hơn khi robot gặp vật cản hoặc object di chuyển. Với pick-and-place trên SO-101, 14–25 steps là sweet spot. Bạn có thể experiment.
Kết quả Thực Tế và Mong Đợi
Trên SO-101 với 100 training demonstrations, dựa theo kết quả tương tự từ MINT-SJTU:
- Pick and place (single object, fixed position): ~85–90% success rate
- Pick and place (multiple objects, natural instruction): ~75–80%
- Generalize sang object màu khác (chưa thấy trong training): ~60–70% — đây là điểm mà EVO1 vượt hẳn SmolVLA nhờ VLM semantic understanding được bảo toàn
Xem thêm bài A1 VLA: Flow-Matching VLA với Latency 72% Thấp Hơn để hiểu sâu hơn về cơ chế flow-matching trong VLA và so sánh với Truncated Flow Matching — một biến thể khác giảm số denoising steps thêm nữa.
Tips Tối ưu cho Consumer GPU
1. Gradient checkpointing là bắt buộc cho Stage 2:
--policy.enable_gradient_checkpointing=true
--policy.gradient_checkpointing_use_reentrant=false
Giảm VRAM Stage 2 từ ~20 GB xuống còn ~12–14 GB. Chậm hơn ~20% về tốc độ train nhưng cần thiết với GPU ≤ 24 GB.
2. Batch size và gradient accumulation:
Stage 2, RTX 4090 (24 GB): --batch_size=4 là đủ. RTX 3090 (24 GB) có thể cần:
--batch_size=2 --gradient_accumulation_steps=4
Global effective batch size vẫn là 8.
3. Flash Attention tiết kiệm thêm ~15–20% VRAM:
pip install flash-attn --no-build-isolation
EVO1 tự detect và dùng Flash Attention nếu có, không cần flag thêm (mặc định use_flash_attn=true).
4. Chạy multi-GPU với Accelerate: Nếu có 2 GPU, Stage 2 nhanh gấp ~1.8 lần:
accelerate launch --num_processes=2 -m lerobot.scripts.lerobot_train \
--policy.type=evo1 \
--policy.training_stage=stage2 \
... (các tham số như trên)
5. Không cần robot pretraining data:
EVO1 khởi đầu từ OpenGVLab/InternVL3-1B-hf pre-trained trên internet data. Không cần dataset robot pretraining lớn như π₀ (dPlan với hàng triệu demonstrations). Đây là lợi thế lớn cho lab nhỏ, startup, hoặc sinh viên nghiên cứu.
Tổng kết
EVO1 lấp đầy khoảng trống quan trọng trong ecosystem VLA: đủ nhỏ để chạy real-time trên consumer GPU, đủ mạnh để vượt model lớn hơn nhiều trên manipulation thực tế. Two-stage training paradigm là bài học thiết kế đáng học — không phải cứ unfreeze hết từ đầu là tốt hơn; đôi khi "chờ" Stage 1 xong trước mới unlock Stage 2 lại là quyết định đúng đắn hơn.
Với SO-101 và LeRobot v0.6.0, EVO1 là lựa chọn thực tế nhất cho lab muốn thử VLA mà không cần đầu tư GPU cluster. Stage 1 chạy được trên RTX 3060 12 GB, Stage 2 cần 24 GB nhưng vẫn trong tầm consumer-grade.
Tài nguyên:
- Paper CVPR 2026: arXiv 2511.04555
- GitHub: MINT-SJTU/Evo-1
- Checkpoint SO100/SO101: MINT-SJTU/Evo1_SO100 — pretrained trực tiếp trên SO100/SO101
- Checkpoint LIBERO (community): zuoxingdong/evo1_libero
- Docs LeRobot: huggingface.co/docs/lerobot/en/evo1
- Docker Jetson Orin: MINT-SJTU/Evo-1_JetsonOrin
Bài viết liên quan
- Fine-tune MolmoAct2 trên SO-101 với LeRobot v0.6 — Hướng dẫn tương tự cho MolmoAct2, VLA vượt π₀.5 với LoRA single-stage
- SmolVLA: Train VLA 450M trên Consumer GPU — So sánh kiến trúc, EVO1 nhỏ hơn SmolVLA nhưng generalize tốt hơn nhờ two-stage training
- A1 VLA: Flow-Matching VLA với Latency 72% Thấp Hơn — Tìm hiểu sâu về flow-matching trong VLA và cách giảm denoising steps để đạt inference real-time



