# EVO1

EVO1 là một chính sách Vision-Language-Action cho điều khiển robot, được xây dựng dựa trên khung xương InternVL3 và đầu action flow-matching liên tục. Tích hợp LeRobot này phơi bày EVO1 như một kiểu chính sách chuẩn, cho phép huấn luyện và đánh giá bằng các API dataset, checkpoint và processor thông thường của LeRobot.

## Tổng quan về Mô hình

Chính sách nhúng một hoặc nhiều hình ảnh từ camera và prompt của tác vụ ngôn ngữ bằng InternVL3, đệm các vector trạng thái/hành động của robot lên các chiều tối đa cố định, và dự đoán các khối hành động tương lai bằng đầu ra hành động khớp dòng (flow-matching). Trong suy luận, chính sách lấy mẫu một khối hành động và trả về `n_action_steps` hành động từ khối đó trước khi lấy mẫu lại.

### Những gì Tích hợp LeRobot Bao Gồm

- Cấu hình `policy.type=evo1` tiêu chuẩn thông qua LeRobot
- Nhúng hình ảnh/văn bản InternVL3 với tùy chọn dự phòng FlashAttention
- Các tùy chọn điều khiển theo giai đoạn cho các lần huấn luyện lại chỉ đầu hành động và huấn luyện lại VLM
- Dự đoán hành động khớp dòng liên tục
- Lưu/tải checkpoint thông qua các API chính sách của LeRobot
- Huấn luyện với `lerobot-train` và đánh giá với các API suy luận chính sách tiêu chuẩn

Dự án EVO1 rộng hơn có thể bao gồm các script huấn luyện và công cụ xử lý tập dữ liệu bổ sung. Trang này tập trung vào đường dẫn chính sách điều khiển robot của LeRobot.

## Yêu cầu cài đặt

1. Cài đặt LeRobot bằng cách làm theo [Hướng dẫn cài đặt](./installation).
2. Cài đặt các phụ thuộc của EVO1:

   ```bash
   pip install -e ".[training,evo1]"
   ```

   Để huấn luyện và đánh giá LIBERO, hãy cài đặt thêm phần mở rộng LIBERO:

   ```bash
   pip install -e ".[training,evo1,libero]"
   ```

3. Chỉ cài đặt wheel `flash-attn` nếu nó tương thích với Python, PyTorch, CUDA và bộ GPU của bạn. EVO1 sẽ chuyển sang cơ chế attention tiêu chuẩn khi `flash_attn` không khả dụng.

EVO1 sử dụng bản triển khai InternVL của `transformers` Hugging Face gốc, do đó `policy.vlm_model_name` phải trỏ đến một checkpoint đã được chuyển đổi theo cách gốc, chẳng hạn như `OpenGVLab/InternVL3-1B-hf` (lưu ý hậu tố `-hf`). Lần chạy đầu tiên sẽ tải xuống checkpoint VLM đã cấu hình và các lần chạy sau đó sẽ tái sử dụng nó từ bộ nhớ đệm Hugging Face.

## Yêu cầu về dữ liệu

EVO1 mong đợi một tập dữ liệu LeRobot có:

- Một đến `policy.max_views` quan sát trực quan, ví dụ `observation.images.image`
- `observation.state`
- `action`
- Lệnh nhiệm vụ ngôn ngữ trong trường `task` của bộ dữ liệu, hoặc một trường khác được cấu hình bằng `policy.task_field`

Các vector trạng thái và hành động được đệm (padding) đến `policy.max_state_dim` và `policy.max_action_dim`. Các dự đoán được cắt (crop) lại về chiều kích hành động của bộ dữ liệu trước khi được trả về.

## Cách sử dụng

Để sử dụng EVO1 trong một cấu hình LeRobot, hãy chỉ định:

```python
policy.type=evo1
```

Mặc định, một chính sách EVO1 mới sẽ khởi tạo VLM của nó từ:

```python
policy.vlm_model_name=OpenGVLab/InternVL3-1B-hf
```

Khi checkpoint EVO1 định dạng LeRobot đã có sẵn, hãy tải nó bằng cách:

```python
policy.path=your-org/your-evo1-checkpoint
```

## Huấn luyện

### Giai đoạn 1

Giai đoạn 1 đóng băng VLM và huấn luyện đầu hành động:

```bash
lerobot-train \
  --dataset.repo_id=your_org/your_dataset \
  --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.optimizer_lr=1e-5 \
  --batch_size=4 \
  --steps=5000 \
  --output_dir=./outputs/evo1_stage1
```

### Giai đoạn 2

Stage 2 tải chính sách của Stage 1, nhưng khởi tạo một bộ tối ưu hóa và trình lập lịch mới:

```bash
lerobot-train \
  --dataset.repo_id=your_org/your_dataset \
  --policy.path=./outputs/evo1_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.optimizer_lr=1e-5 \
  --batch_size=4 \
  --steps=80000 \
  --output_dir=./outputs/evo1_stage2
```

Mặc định, `policy.training_stage` áp dụng lại các giá trị mặc định cho việc tinh chỉnh (finetuning) của giai đoạn đó. Điều này quan trọng khi bắt đầu Giai đoạn 2 từ một checkpoint của Giai đoạn 1, vì cấu hình checkpoint của Giai đoạn 1 lưu các cờ (flags) tinh chỉnh VLM ở trạng thái tắt. Các giá trị mặc định theo giai đoạn này có độ ưu tiên cao hơn so với các cờ `policy.finetune_*` đã lưu hoặc được cung cấp thủ công, trừ khi `policy.apply_training_stage_defaults=false`, do đó chỉ đặt cờ đó khi bạn kiểm soát thủ công mọi cờ tinh chỉnh.

### Các tham số huấn luyện chính

| Tham số                                     | Mặc định                     | Mô tả                                                       |
| --------------------------------------------- | --------------------------- | ----------------------------------------------------------------- |
| `policy.vlm_model_name`                       | `OpenGVLab/InternVL3-1B-hf` | Checkpoint InternVL3 đã được chuyển đổi bản địa hoặc thư mục mô hình cục bộ  |
| `policy.training_stage`                       | `stage1`                    | `stage1` huấn luyện đầu hành động; `stage2` tinh chỉnh các nhánh VLM  |
| `policy.apply_training_stage_defaults`        | `true`                      | Áp dụng lại các giá trị mặc định của fine-tuning theo giai đoạn sau khi tải checkpoint    |
| `policy.vlm_num_layers`                       | `14`                        | Số lượng lớp ngôn ngữ của InternVL3 được giữ lại cho chính sách           |
| `policy.dtype`                                | `bfloat16`                  | Kiểu dữ liệu VLM được yêu cầu                                               |
| `policy.use_flash_attn`                       | `true`                      | Yêu cầu FlashAttention khi đã được cài đặt; nếu không, sẽ chuyển sang phương án dự phòng      |
| `policy.enable_gradient_checkpointing`        | `true`                      | Bật checkpointing trên các module InternVL3 được hỗ trợ              |
| `policy.gradient_checkpointing_use_reentrant` | `false`                     | Cài đặt reentrant được truyền vào gradient checkpointing khi được hỗ trợ |
| `policy.chunk_size`                           | `50`                        | Số lượng hành động tương lai được dự đoán cho mỗi khối                      |
| `policy.n_action_steps`                       | `50`                        | Số lượng hành động được tiêu thụ từ một khối được lấy mẫu                   |
| `policy.max_state_dim`                        | `24`                        | Kích thước đệm trạng thái                                           |
| `policy.max_action_dim`                       | `24`                        | Kích thước đệm cho hành động                                          |
| `policy.postprocess_action_dim`               | `null`                      | Chiều kích thước hành động tùy chọn được trả về sau khi xử lý hậu kỳ EVO1      |
| `policy.binarize_gripper`                     | `false`                     | Thực hiện nhị phân hóa kênh kẹp tay đã xử lý hậu kỳ cho đánh giá theo phong cách LIBERO |
| `policy.task_field`                           | `task`                      | Trường batch được sử dụng làm lời nhắc ngôn ngữ                           |

## Suy luận

Thử nghiệm với một checkpoint EVO1 đã được huấn luyện:

```bash
# --inference.type=rtc is optional
lerobot-rollout \
  --policy.path=your-org/your-evo1-checkpoint \
  --inference.type=rtc \
  ...
```

## Kết quả

### Đánh giá LIBERO

#### Kết quả tham chiếu

> [!NOTE]
> Checkpoint Stage-2 đã phát hành vượt qua kiểm tra tải sạch và xác minh rollout: [`zuoxingdong/evo1_libero`](https://huggingface.co/zuoxingdong/evo1_libero), revision [`515921f4a2c1d3f3ad523721eafa26fdf2af315b`](https://huggingface.co/zuoxingdong/evo1_libero/commit/515921f4a2c1d3f3ad523721eafa26fdf2af315b). Đánh giá tải sạch sử dụng revision LeRobot [`e40b58a8dfa9e7b86918c374791599d070518d11`](https://github.com/huggingface/lerobot/commit/e40b58a8dfa9e7b86918c374791599d070518d11).

Checkpoint Stage-2 chạy một lần tại bước 70.000 đã tạo ra:

| Bộ          | Các tập thành công |  Các tập | Tỷ lệ thành công |
| -------------- | ------------------: | --------: | -----------: |
| LIBERO Spatial |                 485 |       500 |        97.0% |
| LIBERO Object  |                 496 |       500 |        99.2% |
| Mục tiêu LIBERO    |                 483 |       500 |        96.6% |
| LIBERO-10      |                 469 |       500 |        93.8% |
| **Tổng thể**    |           **1,933** | **2,000** |   **96.65%** |

Các kết quả này sử dụng một checkpoint đã được huấn luyện và một hạt đánh giá `1000`; chúng không phải là giá trị trung bình đa hạt hay ước lượng độ tin cậy.

#### Công thức huấn luyện tham chiếu

Checkpoint được phát hành ghi lại cấu hình Stage-2 đã được giải quyết hoàn chỉnh trong [`train_config.json`](https://huggingface.co/zuoxingdong/evo1_libero/blob/515921f4a2c1d3f3ad523721eafa26fdf2af315b/train_config.json). Chạy đo lường sử dụng hai GPU H100 với hai tiến trình DDP và batch 64 cho mỗi tiến trình, cho ra global batch 128. Cả hai giai đoạn đều sử dụng cùng một topology. VLM cơ sở được lấy từ revision `014c0583a0d4bedf29fbe2dbff4f865eb998e171` của `OpenGVLab/InternVL3-1B-hf`. Artefact được phát hành không ghi lại commit huấn luyện LeRobot chính xác hay bản khóa phụ thuộc gốc của nó, do đó các lệnh bên dưới tái tạo cấu hình và topology đã được ghi lại từ một checkout hiện tại thay vì tái tạo môi trường phần mềm bit cho bit.

Từ bản checkout mã nguồn LeRobot, cài đặt các phụ thuộc đã khóa và tải xuống đúng phiên bản VLM đó:

```bash
uv sync --locked --extra training --extra evo1 --extra libero
VLM_DIR=$(uv run hf download OpenGVLab/InternVL3-1B-hf \
  --revision=014c0583a0d4bedf29fbe2dbff4f865eb998e171)
```

Giai đoạn 1 đóng băng VLM và huấn luyện đầu hành động trong 5.000 bước:

```bash
uv run accelerate launch --num_processes=2 -m lerobot.scripts.lerobot_train \
  --dataset.repo_id=lerobot/libero \
  --dataset.revision=a1aaacb7f6cd6ee5fb43120f673cebb0cfea7dd4 \
  --dataset.video_backend=torchcodec \
  --dataset.return_uint8=true \
  --dataset.image_transforms.enable=true \
  --dataset.use_imagenet_stats=true \
  --dataset.eval_split=0.0 \
  --policy.type=evo1 \
  --policy.training_stage=stage1 \
  --policy.apply_training_stage_defaults=true \
  --policy.vlm_model_name="${VLM_DIR}" \
  --policy.vlm_num_layers=14 \
  --policy.dtype=bfloat16 \
  --policy.device=cuda \
  --policy.use_amp=true \
  --policy.use_flash_attn=true \
  --policy.enable_gradient_checkpointing=true \
  --policy.gradient_checkpointing_use_reentrant=false \
  --policy.image_resolution='[448,448]' \
  --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.scheduler_warmup_steps=1000 \
  --policy.push_to_hub=false \
  --use_policy_training_preset=true \
  --batch_size=64 \
  --steps=5000 \
  --save_checkpoint=true \
  --save_checkpoint_to_hub=false \
  --save_freq=2500 \
  --log_freq=10 \
  --env_eval_freq=0 \
  --num_workers=4 \
  --prefetch_factor=2 \
  --persistent_workers=true \
  --seed=1000 \
  --trackio.enable=false \
  --output_dir=./outputs/evo1-libero-stage1-g128-5k
```

Stage 2 nạp chính sách từ Stage-1 nhưng khởi tạo một bộ tối ưu hóa và trình lập lịch mới. Nó huấn luyện trong 80.000 bước; checkpoint được báo cáo là bản lưu tại bước 70.000:

```bash
uv run accelerate launch --num_processes=2 -m lerobot.scripts.lerobot_train \
  --dataset.repo_id=lerobot/libero \
  --dataset.revision=a1aaacb7f6cd6ee5fb43120f673cebb0cfea7dd4 \
  --dataset.video_backend=torchcodec \
  --dataset.return_uint8=true \
  --dataset.image_transforms.enable=true \
  --dataset.use_imagenet_stats=true \
  --dataset.eval_split=0.0 \
  --policy.path=./outputs/evo1-libero-stage1-g128-5k/checkpoints/005000/pretrained_model \
  --policy.training_stage=stage2 \
  --policy.apply_training_stage_defaults=true \
  --policy.vlm_model_name="${VLM_DIR}" \
  --policy.vlm_num_layers=14 \
  --policy.dtype=float32 \
  --policy.device=cuda \
  --policy.use_amp=true \
  --policy.use_flash_attn=true \
  --policy.enable_gradient_checkpointing=true \
  --policy.gradient_checkpointing_use_reentrant=false \
  --policy.image_resolution='[448,448]' \
  --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.scheduler_warmup_steps=1000 \
  --policy.push_to_hub=false \
  --use_policy_training_preset=true \
  --batch_size=64 \
  --steps=80000 \
  --resume=false \
  --save_checkpoint=true \
  --save_checkpoint_to_hub=false \
  --save_freq=10000 \
  --log_freq=10 \
  --env_eval_freq=0 \
  --num_workers=4 \
  --prefetch_factor=2 \
  --persistent_workers=true \
  --seed=1000 \
  --trackio.enable=false \
  --output_dir=./outputs/evo1-libero-stage2-g128-80k
```

#### Hồ sơ đánh giá định dạng tác giả

Hồ sơ EVO1 LIBERO theo định dạng tác giả sử dụng tên đặc trưng camera thô của LIBERO (`observation.images.agentview_image` và `observation.images.robot0_eye_in_hand_image`), lập kế hoạch lại sau mỗi 14 hành động và nhị phân hóa lệnh kẹp trước khi bước mô phỏng. Bộ xử lý hậu kỳ chính sách EVO1 có thể cắt hành động 24D đã đệm về không gian hành động 7D của LIBERO và áp dụng việc nhị phân hóa kẹp đó. Để đánh giá một checkpoint định dạng tác giả trong cùng cài đặt một tập mỗi tác vụ, hãy giữ nguyên tên camera thô thay vì ánh xạ mặc định `image`/`image2` và đặt các cờ xử lý hậu kỳ hành động LIBERO:

```bash
lerobot-eval \
  --policy.path=your-org/your-evo1-libero-checkpoint \
  --policy.vlm_model_name=OpenGVLab/InternVL3-1B-hf \
  --policy.device=cuda \
  --policy.use_flash_attn=true \
  --policy.n_action_steps=14 \
  --policy.postprocess_action_dim=7 \
  --policy.binarize_gripper=true \
  --env.type=libero \
  --env.task=libero_object \
  --env.camera_name_mapping="{agentview_image: agentview_image, robot0_eye_in_hand_image: robot0_eye_in_hand_image}" \
  --env.observation_height=448 \
  --env.observation_width=448 \
  --eval.batch_size=1 \
  --eval.n_episodes=1
```

#### Hồ sơ v3 `lerobot/libero` bản địa

Phiên bản `a1aaacb7f6cd6ee5fb43120f673cebb0cfea7dd4` lưu trữ các đặc trưng camera dưới dạng `image` và `image2`. Ví dụ này đánh giá tất cả mười tác vụ LIBERO Object, khởi chạy mỗi tác vụ trong một tiến trình mới:

```bash
export MUJOCO_GL=egl
export PYOPENGL_PLATFORM=egl

suite=libero_object
horizon=280
for task_id in {0..9}; do
  lerobot-eval \
    --policy.path=zuoxingdong/evo1_libero \
    --policy.pretrained_revision=515921f4a2c1d3f3ad523721eafa26fdf2af315b \
    --policy.vlm_model_name=OpenGVLab/InternVL3-1B-hf \
    --policy.device=cuda \
    --policy.use_amp=true \
    --policy.dtype=bfloat16 \
    --policy.use_flash_attn=false \
    --policy.enable_gradient_checkpointing=false \
    --policy.vlm_num_layers=14 \
    --policy.image_resolution='[448,448]' \
    --policy.max_text_length=1024 \
    --policy.chunk_size=50 \
    --policy.n_action_steps=14 \
    --policy.max_state_dim=24 \
    --policy.max_action_dim=24 \
    --policy.num_inference_timesteps=32 \
    --policy.postprocess_action_dim=7 \
    --policy.binarize_gripper=true \
    --policy.gripper_threshold=0.0 \
    --policy.gripper_below_threshold_value=-1.0 \
    --policy.gripper_above_threshold_value=1.0 \
    --env.type=libero \
    --env.task="${suite}" \
    --env.task_ids="[${task_id}]" \
    --env.camera_name=agentview_image,robot0_eye_in_hand_image \
    --env.camera_name_mapping="{agentview_image: image, robot0_eye_in_hand_image: image2}" \
    --env.control_mode=relative \
    --env.obs_type=pixels_agent_pos \
    --env.observation_width=448 \
    --env.observation_height=448 \
    --env.init_states=true \
    --env.episode_length="${horizon}" \
    --env.render_mode=rgb_array \
    --env.max_parallel_tasks=1 \
    --eval.n_episodes=50 \
    --eval.batch_size=1 \
    --eval.use_async_envs=false \
    --eval.recording=false \
    --seed=1000 \
    --output_dir="./outputs/evo1-libero-stage2-70k-eval/${suite}/task-${task_id}" \
    --job_name="evo1-libero-stage2-70k-${suite}-task-${task_id}"
done
```

Chạy tất cả mười ID tác vụ cho mỗi bộ với các chân trời sau:

| `env.task`       | `env.episode_length` |
| ---------------- | -------------------: |
| `libero_spatial` |                `280` |
| `libero_object`  |                `280` |
| `libero_goal`    |                `300` |
| `libero_10`      |                `520` |

Đặt `suite` và `horizon` cho mỗi hàng. Điều này cho ra 500 episodes cho mỗi suite và 2.000 episodes tổng cộng, trong đó quy trình mới cho mỗi task của vòng lặp khớp với cấu hình topology của việc đặt lại RNG đã được đo lường.

## Tham khảo

- [kho EVO1](https://github.com/MINT-SJTU/Evo-1)
- [InternVL3-1B-hf](https://huggingface.co/OpenGVLab/InternVL3-1B-hf)

## Giấy phép

Tích hợp LeRobot này tuân theo Giấy phép Apache 2.0 được sử dụng bởi LeRobot. Hãy kiểm tra các trang mô hình EVO1 và InternVL3 nguồn để biết giấy phép của các checkpoint và dữ liệu đã phát hành.

