DM0.5 là một trong những release VLA open-source đáng chú ý nhất hiện nay vì nó không chỉ đưa ra model checkpoint, mà còn mở kèm OpenDM: script training, dataset registry, inference service và các guide cho LIBERO, RoboTwin2.0, SO101. Với người mới bắt đầu học robot manipulation, điểm hấp dẫn là bạn không phải tự ghép từng mảnh rời rạc như model card, data loader, normalization, action chunking và HTTP inference. OpenDM đã đóng gói một workflow có thể lần theo từ dữ liệu đến robot thật.
Bài này tập trung vào một bài toán cụ thể: fine-tune DM0.5/OpenDM trên SO101 Pick Cube bằng LoRA, rồi dùng RoboTwin2.0 để hiểu cách Dexmal đánh giá khả năng manipulation generalist của DM0.5. SO101 là robot arm giá dễ tiếp cận trong hệ sinh thái LeRobot, còn RoboTwin2.0 là benchmark/dataset simulation hai tay lớn hơn nhiều. Hai phần này không phải một bài toán giống hệt nhau, nhưng đặt cạnh nhau rất có ích: SO101 cho ta pipeline real-robot nhỏ để tự làm, RoboTwin2.0 cho ta chuẩn đánh giá và dữ liệu synthetic lớn để hiểu model có đang thật sự học robust manipulation hay không.
Nếu bạn đã đọc series VLA & LeRobot cơ bản, hãy xem bài này như bước tiếp theo: thay vì chỉ hiểu policy training ở mức khái niệm, ta sẽ đi vào cấu trúc data JSONL, action dimension, LoRA target modules, checkpoint và inference command.
DM0.5 và OpenDM là gì?
Theo model card chính thức trên Hugging Face, DM0.5 là VLA thế hệ mới của Dexmal cho open-world robot control. Nó kế thừa hướng "embodied-native" từ DM0: coi dữ liệu robot, dữ liệu vision-language và dữ liệu hành động là thành phần trung tâm của quá trình huấn luyện, không chỉ là phần fine-tune ở cuối. OpenDM là repo đi kèm để train, fine-tune, evaluate và deploy DM0.5.
DM0 paper mô tả framework theo ba giai đoạn: pretraining, mid-training và post-training. Điểm quan trọng với roboticist là DM0 không chỉ học caption hay VQA rồi gắn thêm action head. Nó trộn nhiều nguồn dữ liệu: vision-language corpus, driving logs, manipulation trajectories, navigation trajectories, embodied reasoning và dữ liệu robot một tay/hai tay. Với robot data, mỗi timestep thường có multi-view images, instruction, proprioceptive state và action target. Collator sẽ xếp các timestep liên tiếp thành action chunk để model dự đoán một đoạn hành động thay vì chỉ một điểm đơn lẻ.
DM0.5 là bản nâng cấp thực dụng hơn cho open-world manipulation. OpenDM công bố bốn nhóm model chính:
| Model | Vai trò |
|---|---|
Dexmal/DM05 |
Base DM0.5 để fine-tune downstream |
Dexmal/DM05-libero |
Checkpoint fine-tune cho LIBERO |
Dexmal/DM05-robotwin2 |
Checkpoint fine-tune cho RoboTwin2.0 |
Dexmal/DM05-SO101-Pick-Cube |
Checkpoint fine-tune bằng LoRA cho SO101 Pick Cube |
OpenDM README công bố kết quả benchmark rất mạnh: DM0.5 đạt 99.0 average trên LIBERO và 93.5 average trên RoboTwin2.0, gồm 93.6 Clean và 93.3 Randomized. Với SO101, điểm đáng chú ý hơn là repo đã có SO101 pick cube fine-tuned checkpoint và LoRA SFT workflow, nghĩa là người học có thể bắt đầu từ một task nhỏ nhưng vẫn dùng cùng triết lý training của model lớn.

Ý tưởng paper: embodied-native thay vì chỉ "VLM + robot head"
Nhiều VLA đời đầu đi theo cách dễ hiểu: lấy một VLM đã pretrained trên ảnh và text, thêm action tokenizer hoặc regression head, rồi fine-tune trên robot demonstrations. Cách này hoạt động, nhưng thường có ba vấn đề:
- Model hiểu ảnh/ngôn ngữ tốt nhưng không có physical prior đủ mạnh.
- Dữ liệu robot ít, nên policy dễ overfit vào camera, bàn, vật thể và tốc độ demo.
- Action prediction bị tách khỏi temporal reasoning: model biết "pick cube" nhưng không luôn biết trạng thái task đang ở bước nào.
DM0/DM0.5 cố giải quyết bằng cách đưa embodied data vào sâu hơn trong training. Paper DM0 nhấn mạnh unified pretraining trên vision-language, driving và embodied corpus để model học đồng thời semantic knowledge và physical priors. Mid-training thêm embodied reasoning như task decomposition, subtask prediction, action QA, temporal reasoning và task progress estimation. Với robot manipulation, dữ liệu được biểu diễn theo episodic JSONL: mỗi dòng là một frame/timestep, gồm ảnh multi-view, instruction, state và action.
Với beginner, hãy hiểu đơn giản như sau: VLA không chỉ cần "nhìn ra cube màu cam". Nó còn phải biết cube đã được cầm chưa, gripper đang mở hay đóng, robot có đang ở pha tiếp cận hay pha đặt xuống, và nếu camera wrist hơi rung thì hành động tiếp theo vẫn phải hợp lý. LoRA fine-tune trên SO101 giúp model thích nghi với embodiment nhỏ này mà không phải cập nhật toàn bộ base model.
Kiến trúc thực tế: VLM backbone, Action Expert và action chunk
Trong OpenDM, bạn có thể nghĩ DM0.5 gồm ba lớp chức năng:
| Thành phần | Vai trò |
|---|---|
| Vision-language backbone | Nhận ảnh RGB nhiều view và instruction text, giữ khả năng hiểu vật thể/ngôn ngữ |
| Action Expert | Sinh hành động liên tục cho robot, không phải token text thông thường |
| Dataset/training registry | Khai báo image keys, state/action dimension, action mode, normalization và chunk size |
Action chunking là chi tiết rất quan trọng. Thay vì gọi model ở mỗi timestep để lấy đúng một action, OpenDM thường để model dự đoán một chuỗi action dài chunk-size. Với SO101 guide, chunk size là 50; action dimension là 6; action mode là relative. Với RoboTwin2.0, chunk size cũng là 50, nhưng action dimension là 14 vì ALOHA bimanual embodiment có hai tay, mỗi tay 6 joints + 1 gripper.
Điều này tạo ra một quy tắc sống còn: training, inference và evaluation phải dùng cùng action dimension, action mode, camera order và chunk size. Nếu train SO101 với relative action nhưng inference lại interpret như absolute joint position, robot có thể di chuyển sai hướng. Nếu training dùng images_1 là top camera và images_2 là wrist camera, inference phải gửi ảnh đúng thứ tự đó.
Tại sao dùng LoRA cho SO101?
Full fine-tune một VLA 6B parameters là tốn kém. LoRA giải quyết bằng cách giữ phần lớn weight của model ở trạng thái frozen và chỉ train các adapter low-rank nhỏ gắn vào linear layers. Với OpenDM SO101 guide, LoRA được bật bằng use_lora=True, target modules là all-linear, optimizer là AdamW trên LoRA và trainable weights.
Recipe chính thức cho SO101 Pick Cube:
| Hạng mục | Giá trị |
|---|---|
| Dataset | so101_pick_cube |
| Data root | ./data/so101_pick_cube |
| Image keys | images_1, images_2 |
| Action mode | relative |
| Action dim | 6 |
| Chunk size | 50 |
| Train steps | 10,000 mặc định |
| Save interval | 1,000 steps |
| Per-device batch | 8 |
| LR / warmup | 1e-4 / 1000 |
| Attention | LLM flex_attention, vision flash_attention_2, action sdpa |
| Gradient checkpointing | bật cho VLM và Action Expert |
LoRA là lựa chọn hợp lý cho SO101 vì task Pick Cube nhỏ hơn rất nhiều so với pretraining distribution. Bạn không muốn làm base model quên khả năng hiểu ảnh/ngôn ngữ tổng quát; bạn chỉ muốn nó học mapping từ top/wrist camera + state của SO101 sang action 6 chiều của arm này.
Cài đặt OpenDM
OpenDM khuyến nghị Docker để tránh lệch phiên bản CUDA, PyTorch và flash-attn. Nếu bạn chỉ muốn học pipeline, Docker là đường ít lỗi nhất. Máy nên chạy Ubuntu 20.04/22.04, NVIDIA driver, Docker và NVIDIA Container Toolkit. Training reference dùng nhiều GPU, nhưng bạn vẫn có thể chạy smoke test một GPU để kiểm tra data loader, model load và checkpoint path.
git clone https://github.com/dexmal/opendm.git
cd opendm
docker run -it --rm --gpus all --network host \
--name opendm \
--shm-size=16g \
-v "$PWD":/app/opendm \
-w /app/opendm \
dexmal/opendm:latest /bin/bash
conda activate opendm
pip install -e .
Nếu cài local, dùng Python 3.10:
conda create -n opendm python=3.10 -y
conda activate opendm
pip install torch torchvision \
--index-url https://download.pytorch.org/whl/cu128
pip install ninja packaging
MAX_JOBS=2 pip install flash-attn --no-build-isolation
pip install -e .
Với beginner, lỗi phổ biến nhất là flash-attn build fail vì CUDA/PyTorch không khớp. Nếu gặp lỗi này, quay lại Docker trước; đừng mất một ngày debug environment khi mục tiêu thật là hiểu data và training.
Chuẩn bị dữ liệu SO101 Pick Cube
SO101 guide dùng dataset Dexmal/so101_pick_cube. Script chính thức sẽ download dataset về cache Hugging Face, extract nếu cần và tổ chức lại dưới ./data/so101_pick_cube.
pip install -U huggingface_hub
script/so101_runner.sh dataset
Nếu bạn mount data ở nơi khác:
script/so101_runner.sh dataset --data-root /path/to/data/so101_pick_cube
Sau khi chuẩn bị, cấu trúc mong đợi là:
data/so101_pick_cube/
jsonl/
episode_00000.jsonl
episode_00001.jsonl
...
videos/
so101_YYYYMMDD_HHMMSS_filtered/
file-000.mp4_top.mp4
file-000.mp4_wrist.mp4
...
Mỗi dòng JSONL là một frame. Ví dụ rút gọn:
{
"prompt": "Pick the cube and place it in the plate.",
"state": [-2.29, -102.81, 95.82, 54.02, 2.68, 0.68],
"action": [-0.84, -104.22, 99.16, 54.24, 2.24, 0.16],
"is_robot": true,
"extra": {
"subtask": "Pick the cube and place it in the plate.",
"timestamp": 0.70,
"episode_index": 0,
"cube_color": "orange"
},
"images_1": {
"type": "video",
"url": "episode_00000/camera_top.mp4",
"frame_idx": 21,
"_camera_name": "top"
},
"images_2": {
"type": "video",
"url": "episode_00000/camera_wrist.mp4",
"frame_idx": 21,
"_camera_name": "wrist"
}
}
Ba trường đáng kiểm tra kỹ:
| Trường | Vì sao quan trọng |
|---|---|
state |
Phải đúng thứ tự 6 chiều mà dataset registry định nghĩa |
action |
Với SO101 guide là relative action 6 chiều |
images_1, images_2 |
Phải khớp top camera và wrist camera khi inference |
OpenDM sẽ tự tính normalization stats khi file tương ứng chưa có trong ./norm_stats/. Nhưng nếu bạn thay action mode, action dimension, chunk size hoặc distribution dữ liệu, hãy xóa/tính lại stats. Dùng stats cũ cho data mới là một lỗi âm thầm: training vẫn chạy, loss vẫn giảm, nhưng action scale sai.

Chạy LoRA training trên SO101
Trước tiên download hoặc mount base checkpoint:
huggingface-cli download Dexmal/DM05 \
--local-dir ./checkpoints/DM05
Sau đó chạy command chính thức:
script/dm05_launcher.sh \
--exp playground/dm05_so101_lora.py \
--task train \
--nproc_per_node 8 \
--model-config.model-name-or-path ./checkpoints/DM05
playground/dm05_so101_lora.py đã preset dataset name, action mode, chunk size, attention settings, learning rate, warmup, batch size, save interval và total steps. Khi mới bắt đầu, đừng override quá nhiều. Hãy chạy đúng recipe trước để kiểm tra baseline.
Nếu bạn chỉ có một GPU, có thể chạy smoke test:
script/dm05_launcher.sh \
--exp playground/dm05_so101_lora.py \
--task train \
--nproc_per_node 1 \
--model-config.model-name-or-path ./checkpoints/DM05 \
--trainer-config.num-train-steps 200 \
--trainer-config.save-steps 100
Smoke test không dùng để đánh giá quality. Nó chỉ trả lời bốn câu hỏi:
- Environment có load được model không?
- Dataset path và JSONL có đúng không?
- Image/video frame có decode được không?
- Checkpoint có được ghi ra đúng thư mục không?
Sau khi chạy, kiểm tra trainable summary:
user_checkpoints/<output_dir>/trainable_summaries/
dm05_lora_so101_pick_cube.json
File này phải cho thấy target_modules resolve từ all-linear, unexpected_trainable_parameters rỗng, và các dense saved modules gồm action projections, time MLPs và time modulators. Nếu có parameter ngoài dự kiến bị train, bạn đang không còn chạy đúng LoRA recipe.
Inference với checkpoint SO101
Với checkpoint công bố sẵn:
huggingface-cli download Dexmal/DM05-SO101-Pick-Cube \
--local-dir ./checkpoints/DM05-SO101-Pick-Cube
Khởi động inference:
script/dm05_launcher.sh \
--exp playground/dm05_so101_lora.py \
--task inference \
--nproc_per_node 1 \
--model-config.model-name-or-path ./checkpoints/DM05-SO101-Pick-Cube \
--inference-config.output-action-dim 6
Nếu dùng checkpoint LoRA tự train, truyền path tới checkpoint step:
script/dm05_launcher.sh \
--exp playground/dm05_so101_lora.py \
--task inference \
--nproc_per_node 1 \
--model-config.model-name-or-path ${TRAINING_OUTPUT_DIR}/checkpoint-4000 \
--inference-config.output-action-dim 6
Loader sẽ đọc adapter_config.json, tìm base model được ghi lại và merge adapter cho inference. Điều này tiện, nhưng cũng có nghĩa checkpoint phải được copy đủ: adapter files, config, normalization stats nếu có, và metadata liên quan.
Trong inference service của OpenDM, endpoint /process_frame nhận multipart/form-data: task text, state array và ảnh theo image keys. Với SO101, hãy đảm bảo state 6 chiều và camera order giống lúc train. Khi deploy lên robot thật, nên thêm một lớp safety bên ngoài:
| Safety check | Lý do |
|---|---|
| Clamp joint velocity | Tránh action chunk sinh bước nhảy quá lớn |
| Workspace bounds | Không cho end-effector đâm vào bàn/camera |
| Gripper debounce | Tránh mở/đóng liên tục vì nhiễu |
| Emergency stop | Luôn cần khi chạy policy học từ dữ liệu |
RoboTwin2.0: vì sao liên quan đến SO101?
RoboTwin2.0 không phải dataset SO101. Nó là framework/dataset/benchmark simulation cho bimanual manipulation, có 50 task, 731 object instances thuộc 147 category, domain randomization theo clutter, lighting, background, tabletop height và language. Paper công bố hơn 100,000 expert trajectories trên 50 tasks và nhiều embodiment.
Vậy tại sao bài SO101 cần quan tâm? Vì DM0.5 dùng RoboTwin2.0 để chứng minh khả năng fine-tune và evaluate trên manipulation phức tạp hơn. OpenDM có guide riêng cho DM05-robotwin2, kết quả reference:
| Method | Clean | Randomized | Average |
|---|---|---|---|
| DM0.5 | 93.6 | 93.3 | 93.5 |
Điểm Randomized gần bằng Clean là tín hiệu quan trọng. Nó cho thấy model không chỉ nhớ một layout sạch, mà chịu được biến thiên môi trường. Khi bạn chuyển sang SO101 thật, tư duy tương tự vẫn áp dụng: hãy randomize vị trí cube, ánh sáng, màu cube, góc camera vừa phải, background và câu lệnh. Nếu bạn chỉ thu 50 demo cùng một góc bàn, LoRA sẽ học "bức ảnh đó" thay vì học pick-and-place.

Training RoboTwin2.0 trong OpenDM để hiểu benchmark
OpenDM đăng ký dataset robotwin2_generalist trong opendm/dataset/robotwin2.py. Cấu hình chính:
| Hạng mục | Giá trị |
|---|---|
| Dataset root | ./data/robotwin2.0 |
| Image keys | images_1, images_2, images_3 |
| Camera meaning | head, left wrist, right wrist |
| Embodiment | ALOHA RoboTwin2 |
| State/action dim | 14 |
| Action mode | absolute |
| Chunk size | 50 |
| Train steps | 100,000 reference |
Chuẩn bị data:
mkdir -p data/.hf_downloads/robotwin
hf download Dexmal/robotwin2-full \
--repo-type dataset \
--local-dir data/.hf_downloads/robotwin
cat data/.hf_downloads/robotwin/robotwin2.tar.part-* \
| tar -xf - -C data
hf download Dexmal/DM05 --local-dir checkpoints/DM05
Chạy training:
script/dm05_launcher.sh \
--exp playground/dm05_robotwin2.py \
--task train \
--nproc_per_node 8 \
--data-config.dataset-name robotwin2_generalist \
--model-config.model-name-or-path ./checkpoints/DM05 \
--model-config.chunk-size 50 \
--trainer-config.num-train-steps 100000
Inference RoboTwin2.0:
script/dm05_launcher.sh \
--exp playground/dm05_robotwin2.py \
--task inference \
--nproc_per_node 1 \
--model-config.model-name-or-path ./checkpoints/DM05-robotwin2-bf16 \
--model-config.chunk-size 50 \
--inference-config.output-action-dim 14 \
--inference-config.image-keys images_1 images_2 images_3 \
--inference-config.port 7891
Benchmark config cần giữ action_horizon: 50, action_mode: absolute và camera order head_camera_rgb,left_camera_rgb,right_camera_rgb. Benchmark runner đánh giá 100 episodes cho mỗi task/setting. Muốn tái tạo average Clean/Randomized, bạn phải chạy toàn bộ 50 tasks ở cả hai setting rồi aggregate, không thể lấy một task đơn lẻ làm kết luận.
Checklist cho beginner trước khi train thật
Trước khi đốt GPU nhiều giờ, hãy đi qua checklist này:
| Check | Cách kiểm |
|---|---|
| Dataset name đúng | so101_pick_cube cho SO101, robotwin2_generalist cho RoboTwin2 |
| Camera order đúng | In thử một batch và xem ảnh có đúng top/wrist/head không |
| Action dimension đúng | SO101 là 6, RoboTwin2 là 14 |
| Action mode đúng | SO101 relative, RoboTwin2 absolute |
| Chunk size nhất quán | Train/inference/eval cùng 50 cho các guide này |
| Norm stats mới | Tính lại khi đổi dữ liệu hoặc action format |
| Trainable summary sạch | Không có unexpected trainable parameters |
| Inference output scale hợp lý | Action không nhảy quá lớn ở vài request đầu |
Một mẹo thực tế: trước khi đưa robot thật chạy closed-loop, log 20 request inference với cùng state/image và kiểm tra action chunk có mượt không. Nếu action dao động mạnh dù observation không đổi, hãy kiểm tra normalization, checkpoint load và camera preprocessing.
Kết luận
SO101 + DM0.5/OpenDM là một điểm vào tốt cho VLA manipulation open-source: phần cứng đủ nhỏ để học, task Pick Cube đủ rõ để debug, còn model đủ lớn để bạn thấy workflow hiện đại của robot foundation model. LoRA giúp giảm chi phí fine-tune và bảo toàn khả năng tổng quát của base model. RoboTwin2.0 bổ sung góc nhìn benchmark: muốn policy bền vững, bạn phải quan tâm domain randomization, camera order, action mode và evaluation protocol, không chỉ nhìn một video demo thành công.
Nếu chỉ nhớ ba điều, hãy nhớ: dữ liệu phải đúng schema, normalization phải đi cùng checkpoint, và train/inference/eval phải thống nhất chunk size/action mode. Phần còn lại có thể cải thiện dần qua nhiều vòng thu data, fine-tune, rollout và kiểm tra lỗi.
Nguồn tham khảo
- OpenDM GitHub repo
- DM05 model card trên Hugging Face
- DM05 SO101 LoRA Training Guide
- DM05 RoboTwin2.0 Training and Evaluation Guide
- DM0 paper: Embodied-Native VLA
- RoboTwin2.0 project
- RoboTwin2.0 paper
- LeRobot SO101 docs



