Vì sao ProcVLM đáng chú ý?
Nếu bạn đã từng fine-tune một policy manipulation bằng reinforcement learning, bạn sẽ thấy vấn đề khó nhất thường không phải là optimizer. Vấn đề là reward. Với một task đơn giản như "pick up the red cup and put it into the drawer", binary reward 0/1 quá thưa: robot có thể làm đúng 80% quãng đường nhưng vẫn nhận 0 vì drawer chưa đóng, hoặc làm sai một bước nhỏ nhưng reward cuối tập không cho biết sai ở đâu. Ngược lại, reward thủ công kiểu khoảng cách end-effector tới vật, khoảng cách vật tới goal, penalty va chạm... lại rất phụ thuộc task và dễ bị hack.
ProcVLM, paper "ProcVLM: Learning Procedure-Grounded Progress Rewards for Robotic Manipulation", đề xuất một hướng thực dụng hơn: dùng một vision-language model để đọc video robot, hiểu task instruction, suy luận các atomic actions còn lại, rồi dự đoán task progress liên tục. Progress này có thể dùng như dense reward cho reward-guided fine-tuning của VLA policy. Project page ở procvlm.github.io, code ở github.com/ProcVLM/ProcVLM, model 2B ở Hugging Face, dataset gồm ProcCorpus-60M và ProcVQA-20M.
Bài này hướng dẫn theo góc nhìn engineer: ProcVLM giải quyết bài toán gì, kiến trúc hoạt động ra sao, cài đặt thế nào, chạy inference trên video như thế nào, rồi dùng reward đó để fine-tune VLA manipulation policy bằng RL/RFT. Nếu bạn mới với RL, nên đọc trước Reinforcement Learning cơ bản. Nếu bạn muốn hiểu VLA policy là gì, xem thêm Vision-Language-Action models.
Ý tưởng chính: reward phải theo procedure, không theo thời gian
Nhiều reward model cho robot lấy progress bằng cách nội suy theo timestep: frame đầu là 0%, frame cuối của demo thành công là 100%, các frame giữa chia đều. Cách này đơn giản nhưng sai trong manipulation dài. Robot có thể đứng yên 2 giây để chỉnh gripper, retry sau khi grasp hụt, hoặc hoàn thành một subtask rồi quay lại trạng thái gần giống frame trước. Timestep tăng không có nghĩa là task thật sự tiến triển.
ProcVLM định nghĩa progress theo procedure:
- Task được chia thành các atomic subtasks như "grasp bowl", "move bowl above target", "place bowl into target".
- Mỗi subtask có boundary bắt đầu/kết thúc và trạng thái complete/incomplete.
- Progress tổng được chia ngân sách theo cấu trúc subtask.
- Trong từng subtask, progress được phân bổ theo visual change, không chỉ theo index thời gian.
- Model trước hết suy luận "còn hành động nguyên tử nào?" rồi mới xuất completion percentage.
Sơ đồ đơn giản:
Robot video + task instruction
|
v
Large VLM annotator
|
+-- subtask plan
+-- temporal boundaries
+-- frame-level reasoning
+-- remaining actions
|
v
ProcCorpus-60M
|
v
ProcVQA tasks
- action segmentation
- future planning
- progress prediction
|
v
ProcVLM-2B
|
+-- text reasoning
+-- scalar progress value
|
v
dense reward for policy fine-tuning
Điểm hay là ProcVLM không chỉ hỏi "ảnh này giống goal chưa?". Nó hỏi: với instruction này, trạng thái hiện tại đang ở stage nào, action nào đã xong, action nào còn lại, và completion nên là bao nhiêu. Vì vậy cùng một video có thể nhận reward curve khác nhau nếu bạn đổi instruction. Project page minh họa ví dụ reward editing: cùng video đưa apple vào basket, nếu instruction thêm bước "move the basket to the upper corner", progress cuối video sẽ không còn là 100% nếu basket chưa được di chuyển.
Kiến trúc ProcVLM
ProcVLM được khởi tạo từ Qwen3-VL-2B-Instruct. Đây là một VLM nhỏ vừa đủ để chạy thực tế hơn các model 8B/27B, nhưng vẫn xử lý input hình ảnh + text instruction. Kiến trúc có hai nhánh:
| Thành phần | Vai trò | Output |
|---|---|---|
| VLM backbone | Nhìn observation window và task instruction | hidden states + textual response |
| Language modeling head | Sinh câu trả lời có reasoning | remaining actions, stage explanation |
| Progress value head | Hồi quy completion liên tục | scalar progress |
| Semantic gating | Chỉ bật value head khi sample có progress supervision | tránh nhiễu với task VQA khác |
Trong progress prediction, response được format kiểu:
Remaining actions:
1. Move the bowl above the target bowl.
2. Place the bowl into the target bowl.
<progress>62.5%</progress>
Trong bài viết MDX, ta đặt tag này trong code block để tránh MDX hiểu nhầm thành HTML. Về training, paper dùng joint objective:
L = L_LM + lambda * I_progress * L_value
L_LM là autoregressive language modeling loss cho mọi task VQA. L_value là regression loss cho progress scalar, chỉ áp dụng khi sample có progress supervision. Cách này giữ model vừa biết giải thích procedure bằng text, vừa có đường hồi quy số liên tục thay vì chỉ "đoán token số" như 10%, 50%, 90%.
ProcCorpus-60M và ProcVQA-20M được tạo thế nào?
Nhóm tác giả không annotate thủ công toàn bộ video. Họ xây pipeline synthetic supervision dùng large VLM làm annotator. Theo paper, ProcCorpus-60M được xây từ khoảng 400K trajectories thuộc 30 embodied datasets, gồm real-robot và simulation như DROID, BridgeData V2, Fractal, RH20T, Table30, selected OXE subsets, LIBERO, RoboTwin 2.0 và GR00T-Teleop-Sim. Tổng cộng corpus có hơn 60M annotated frames.
Pipeline annotation có bốn module chạy bất đồng bộ:
| Module | Chức năng |
|---|---|
| Data reader | Đọc episode, task instruction, camera key, frame index |
| CPU preprocessing | Resize ảnh, chuẩn bị prompt, gom frame/video window |
| GPU VLM inference | Chạy plan generation, subtask localization, frame reasoning |
| Post-processing | Parse JSONL, kiểm tra format, mở rộng segment thành frame labels |
Paper dùng Qwen3-VL-235B-A22B-Instruct cho video-level planning và temporal localization, vì cần long-context reasoning. Với frame-level reasoning và grounding, họ dùng InternVL3.5-38B để hiệu quả hơn trên từng frame.
Từ ProcCorpus, họ chuyển thành ProcVQA với ba nhóm task:
| Task trong ProcVQA | Model học gì? | Vì sao có ích cho reward? |
|---|---|---|
| Action segmentation | Chia video thành atomic actions | Biết boundary của procedure |
| Future planning | Dự đoán actions còn lại | Biết trạng thái chưa hoàn thành |
| Progress prediction | Ước lượng completion percentage | Tạo dense reward |
Training có hai giai đoạn. Stage 1 dùng full ProcVQA khoảng 20B tokens để học representation rộng. Stage 2 refine trên curated subset khoảng 15K trajectories và 2.8B tokens, được human-selected để subtask alignment chính xác hơn.
Cài đặt ProcVLM
Repo chính hiện dùng uv, Python 3.10, vLLM mặc định và có support LMDeploy cho pipeline annotation. Với người dùng thực hành, bạn nên tách hai mục tiêu:
- Inference reward: chỉ cần model checkpoint và video.
- Annotation/training pipeline đầy đủ: cần LMDeploy/vLLM và nhiều GPU hơn.
Cài đặt tối thiểu:
git clone https://github.com/ProcVLM/ProcVLM.git
cd ProcVLM
# Cài uv nếu máy chưa có
wget -qO- https://astral.sh/uv/install.sh | sh
# Tạo môi trường Python 3.10
uv sync --python 3.10
source .venv/bin/activate
# Flash Attention thường cần cài riêng
uv pip install flash-attn --no-build-isolation
Repo README lưu ý project dùng vLLM v0.18 và Transformers v4.57 theo mặc định. Nếu gặp lỗi CUDA, hãy kiểm tra lại version PyTorch/CUDA trước khi debug code. Với GPU nhỏ, có thể bắt đầu bằng inference batch nhỏ hoặc chạy model qua Transformers thay vì vLLM.
Nếu bạn muốn chạy pipeline annotation/reasoning cục bộ, repo khuyến nghị LMDeploy trong Conda env riêng:
conda create -n lmdeploy python=3.10 -y
conda activate lmdeploy
pip install lmdeploy
pip install -r envs/others_pip.txt
Chạy inference: từ video thành progress JSONL
Use case đơn giản nhất: bạn có một video rollout và instruction, muốn biết từng frame đang ở bao nhiêu phần trăm completion.
python evqa/inference.py \
--model_path /path/to/procvlm-checkpoint \
--video_path tmp/fold_cloth/R1_Lite_fold_clothes.mp4 \
--output_path tmp/fold_cloth/progress.jsonl \
--task "fold the red T-shirt" \
--window_size 8
window_size=8 nghĩa là tại mỗi thời điểm, model nhìn 8 frame gần nhất, gồm frame hiện tại. Output JSONL có dạng:
{"frame_index": 0, "progress": 0.02}
{"frame_index": 12, "progress": 0.11}
{"frame_index": 24, "progress": 0.28}
{"frame_index": 36, "progress": 0.51}
{"frame_index": 48, "progress": 0.73}
Bạn có thể visualize progress curve lên video:
python evqa/eval/visualize_progress_video \
--model_path /path/to/procvlm-checkpoint \
--video_path tmp/fold_cloth/R1_Lite_fold_clothes.mp4 \
--output_path tmp/fold_cloth/progress_vis.mp4 \
--task "fold the red T-shirt" \
--window_size 8
Trong Python, ý tưởng integration thường như sau:
from evqa.inference import infer_progress_from_video
progress = infer_progress_from_video(
model_path="/models/procvlm",
video_path="rollouts/episode_003.mp4",
task="stack the blue bowl into the target bowl",
window_size=8,
)
# Dense reward đơn giản: dùng delta progress
rewards = []
prev = progress[0]["progress"]
for item in progress[1:]:
cur = item["progress"]
rewards.append(cur - prev)
prev = cur
Trong thực tế, reward nên được clip/smooth để tránh policy học từ noise:
def procvlm_reward(progress_t, progress_prev, success_bonus=1.0):
delta = progress_t - progress_prev
dense = max(min(delta, 0.10), -0.05)
terminal = success_bonus if progress_t > 0.95 else 0.0
return dense + terminal
Dùng ProcVLM reward để fine-tune VLA policy
Paper dùng ProcVLM trong setting reward fine-tuning dựa trên SJTU Evo-RL. Base policy là pi0.5. SFT và RFT cùng xuất phát từ một policy initialization và cùng training data. Khác biệt là RFT dùng ProcVLM để gán dense progress scores cho trajectories, rồi Evo-RL ước lượng advantage trong horizon 50 steps.
Workflow dễ hiểu:
1. Thu thập trajectories bằng teleoperation hoặc policy rollout
2. Lưu video + action sequence + task instruction
3. Chạy ProcVLM để có progress p_t cho từng sampled frame
4. Tính dense reward hoặc advantage từ p_t
5. Chọn top 30% advantage samples là positive
6. Gắn auxiliary condition vào policy training
7. Fine-tune VLA bằng reward-guided objective
8. Evaluate rollout thật hoặc simulation
Pseudo-code ở mức hệ thống:
for episode in dataset:
progress = procvlm.infer(
video_path=episode.video,
task=episode.instruction,
window_size=8,
)
episode.rewards = compute_delta_rewards(progress)
episode.advantages = estimate_advantage(
rewards=episode.rewards,
horizon=50,
)
positive = select_top_percent(dataset, key="advantages", percent=30)
negative = select_rest(dataset, positive)
train_vla_policy(
base_policy="pi0.5",
positive_samples=positive,
negative_samples=negative,
objective="advantage_conditioned_rft",
)
Nếu bạn đang dùng LeRobot hoặc một VLA stack tự viết, bạn có thể bắt đầu nhẹ hơn: không cần implement toàn bộ Evo-RL ngay. Hãy dùng ProcVLM để rerank trajectories, lọc các đoạn có progress tăng đều, sau đó SFT lại policy trên các đoạn tốt. Khi pipeline ổn, mới chuyển sang advantage-conditioned training. Bài HIL-SERL với LeRobot cũng là một điểm tham chiếu tốt nếu bạn muốn kết hợp human intervention với reward model.
Kết quả paper: mạnh ở reasoning và real robot early training
Trên ProcVQA, ProcVLM-2B vượt các VLM lớn ở nhiều metric chính. Một vài số liệu nổi bật:
| Benchmark | Metric | ProcVLM-2B | Baseline đáng chú ý |
|---|---|---|---|
| ProcVQA ID | BF1@5 | 0.6924 | GPT-5.4: 0.5221 |
| ProcVQA ID | Future planning success | 0.8103 | Qwen3.5: 0.7931 |
| ProcVQA ID | VOC | 0.8058 | Qwen3.5: 0.5475 |
| ProcVQA OOD | Future planning success | 0.8448 | Qwen3.5: 0.7758 |
| ProcVQA OOD | VOC | 0.7282 | GPT-5.4: 0.6553 |
Trong zero-shot reward model comparison trên ProcVQA-OOD, ProcVLM-2B đạt VOC 0.7282, cao hơn Robometer-4B 0.5296 và RoboDopamine-4B 0.7156. Robometer có EPR@50 cao hơn, nhưng paper nhận xét VOC thấp hơn cho thấy ordering nội bộ trajectory yếu hơn trong setting local-window shuffled.
Ở RoboFAC real-robot one-shot, ProcVLM thích nghi rất nhanh:
| Setting | VOCsucc | MAEfail | MCC | Latency |
|---|---|---|---|---|
| ProcVLM zero-shot | 0.4920 | 0.2001 | 0.6665 | 50s |
| ProcVLM 1-shot success | 0.9137 | 0.1241 | 0.7918 | 81s |
| ProcVLM 1-shot success + fail | 0.9301 | 0.1187 | 0.8053 | 80s |
Quan trọng nhất với người làm policy là reward fine-tuning. Trên LIBERO-10 simulation, RFT dùng ProcVLM tăng nhẹ so với SFT: 73.2 lên 73.6 ở 1000 steps, 72.8 lên 74.0 ở 2000 steps. Trên real robot JAKA stack-bowls, hiệu ứng rõ hơn: ở 5k steps, SFT đạt 37.5 còn RFT đạt 62.5; ở 10k steps, SFT 70.8 và RFT 83.3. Lý do hợp lý: dữ liệu teleoperation thật thường có retry, grasp lỗi, chuyển động cục bộ nhiễu. Dense progress reward giúp downweight các đoạn ít tiến triển.
Checklist triển khai cho beginner
Nếu bạn muốn thử ProcVLM mà không quá tải, đi theo thứ tự này:
- Chọn một task manipulation rõ ràng: pick-place, stack bowl, close drawer.
- Thu 10-30 video thành công và 10-30 video thất bại nếu có thể.
- Viết instruction nhất quán, ví dụ "place the blue bowl into the target bowl".
- Chạy ProcVLM inference với
window_size=8. - Plot progress curve theo frame.
- Kiểm tra thủ công 5 video: progress có tăng ở đúng subtask không?
- Nếu curve nhiễu, dùng smoothing và delta clipping.
- Dùng reward để rerank/clean SFT data trước.
- Sau đó mới dùng advantage-conditioned RFT hoặc RL loop.
Một rule thực dụng: đừng tin reward model ngay từ đầu. Hãy visualize video + reward curve. Nếu curve tăng khi robot retry vô ích, task instruction có thể mơ hồ hoặc camera không thấy target. Nếu curve giảm sau khi robot đã hoàn thành, model có thể thiếu context frame hoặc instruction thiếu bước cuối.
Hạn chế cần nhớ
ProcVLM không thay thế toàn bộ evaluation thật. Nó học progress từ subtask decomposition và boundary localization, nên lỗi annotation có thể tạo reward sai. Nó cũng không trực tiếp kiểm tra lực tiếp xúc, an toàn phần cứng hay constraint động học. Với task cần force control, insertion tight tolerance hoặc tactile feedback, bạn nên kết hợp ProcVLM reward với success detector chuyên biệt, safety constraint và human review.
Ngoài ra, inference theo video window không rẻ. ProcVLM-2B nhanh hơn các model 8B/27B, nhưng nếu bạn cần reward real-time ở 30 FPS, hãy batch offline hoặc sample frame thưa hơn. Use case tốt nhất hiện tại là offline reward labeling, trajectory filtering, one-shot reward adaptation và reward-guided fine-tuning.
Kết luận
ProcVLM là một bước quan trọng trong hướng "reward model for robots": thay vì viết reward thủ công hoặc chỉ dùng binary success, ta có một model đọc video và instruction để tạo dense progress reward theo procedure. Với VLA manipulation, đặc biệt khi fine-tune từ demonstrations nhiễu, reward kiểu này giúp policy biết đoạn nào thật sự làm task tiến lên.
Nếu bạn đang xây pipeline VLA thực tế, hãy xem ProcVLM như một lớp đo progress: không phải bộ não điều khiển robot, mà là critic đánh giá video rollout. Kết hợp với SFT, LeRobot/HIL-SERL hoặc Evo-RL, nó có thể biến video robot thành tín hiệu training giàu hơn nhiều so với success/failure cuối episode.