# EVO1

EVO1 é uma política Vision-Language-Action para controle de robôs, construída em torno de um backbone InternVL3 e uma cabeça de ação contínua de flow-matching. Esta integração com LeRobot expõe o EVO1 como um tipo de política padrão, permitindo que ele seja treinado e avaliado com as APIs usuais de dataset, checkpoint e processor do LeRobot.

## Visão geral do modelo

A política incorpora uma ou mais imagens de câmera e o prompt da tarefa de linguagem com InternVL3, preenche os vetores de estado/ação do robô até dimensões máximas fixas e prevê blocos futuros de ações com uma cabeça de ação de flow-matching. Durante a inferência, a política amostra um bloco de ações e retorna `n_action_steps` ações desse bloco antes de amostrar novamente.

### O que a Integração do LeRobot Abrange

- Configuração padrão `policy.type=evo1` por meio do LeRobot
- Embedding de imagem/texto do InternVL3 com fallback opcional para FlashAttention
- Controles de ajuste fino por estágio para execuções de ajuste fino apenas da cabeça de ação e de VLM
- Previsão de ações por fluxo contínuo
- Salvamento/carregamento de checkpoints por meio das APIs de política do LeRobot
- Treinamento com `lerobot-train` e avaliação com APIs padrão de inferência de política

O projeto EVO1 mais amplo pode incluir scripts de treinamento adicionais e ferramentas de conjunto de dados. Esta página se concentra no caminho de política de controle de robô do LeRobot.

## Requisitos de instalação

1. Instale o LeRobot seguindo o [Guia de Instalação](./installation).
2. Instale as dependências do EVO1:

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

   Para o treinamento e a avaliação do LIBERO, instale também o extra do LIBERO:

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

3. Instale uma wheel do `flash-attn` apenas se for compatível com seu Python, PyTorch, CUDA e stack de GPU. O EVO1 recorre à atenção padrão quando o `flash_attn` não está disponível.

O EVO1 usa a implementação nativa do InternVL do `transformers` do Hugging Face, portanto `policy.vlm_model_name` deve apontar para um checkpoint convertido nativamente, como `OpenGVLab/InternVL3-1B-hf` (observe o sufixo `-hf`). A primeira execução baixa o checkpoint do VLM configurado e as execuções subsequentes o reutilizam do cache do Hugging Face.

## Requisitos de Dados

O EVO1 espera um dataset LeRobot com:

- De um a `policy.max_views` observações visuais, por exemplo `observation.images.image`
- `observation.state`
- `action`
- Uma instrução de tarefa de linguagem no campo `task` do conjunto de dados, ou em outro campo configurado com `policy.task_field`

Os vetores de estado e ação são preenchidos até `policy.max_state_dim` e `policy.max_action_dim`. As previsões são recortadas de volta para a dimensão de ação do conjunto de dados antes de serem retornadas.

## Uso

Para usar o EVO1 em uma configuração do LeRobot, especifique:

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

Por padrão, uma nova política EVO1 inicializa seu VLM a partir de:

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

Quando um checkpoint EVO1 no formato LeRobot estiver disponível, carregue-o com:

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

## Treinamento

### Etapa 1

A Etapa 1 congela o VLM e treina a cabeça de ação:

```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
```

### Etapa 2

A Etapa 2 carrega a política da Etapa 1, mas inicia um otimizador e um agendador novos:

```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
```

Por padrão, `policy.training_stage` reaplica os padrões de finetuning para aquela etapa. Isso é importante ao iniciar a Etapa 2 a partir de um checkpoint da Etapa 1, porque a configuração do checkpoint da Etapa 1 armazena as flags de finetuning do VLM como desativadas. Esses padrões de etapa têm precedência sobre as flags `policy.finetune_*` salvas ou fornecidas manualmente, a menos que `policy.apply_training_stage_defaults=false`, portanto, defina essa flag apenas quando estiver controlando manualmente todas as flags de finetuning.

### Parâmetros Principais de Treinamento

| Parâmetro                                     | Padrão                     | Descrição                                                       |
| --------------------------------------------- | --------------------------- | ----------------------------------------------------------------- |
| `policy.vlm_model_name`                       | `OpenGVLab/InternVL3-1B-hf` | Checkpoint do InternVL3 convertido nativamente ou diretório local do modelo  |
| `policy.training_stage`                       | `stage1`                    | `stage1` treina a cabeça de ação; `stage2` faz o ajuste fino dos ramos do VLM  |
| `policy.apply_training_stage_defaults`        | `true`                      | Reaplica os padrões de ajuste fino do estágio após carregar um checkpoint    |
| `policy.vlm_num_layers`                       | `14`                        | Número de camadas de linguagem do InternVL3 mantidas para a política           |
| `policy.dtype`                                | `bfloat16`                  | Dtype do VLM solicitado                                               |
| `policy.use_flash_attn`                       | `true`                      | Solicita o FlashAttention quando instalado; caso contrário, usa um método alternativo      |
| `policy.enable_gradient_checkpointing`        | `true`                      | Ativa o checkpointing nos módulos InternVL3 compatíveis              |
| `policy.gradient_checkpointing_use_reentrant` | `false`                     | Configuração reentrante passada para o checkpointing de gradiente quando suportado |
| `policy.chunk_size`                           | `50`                        | Número de ações futuras previstas por bloco                      |
| `policy.n_action_steps`                       | `50`                        | Número de ações consumidas de um bloco amostrado                   |
| `policy.max_state_dim`                        | `24`                        | Dimensão de preenchimento do estado                                           |
| `policy.max_action_dim`                       | `24`                        | Dimensão de preenchimento de ação                                          |
| `policy.postprocess_action_dim`               | `null`                      | Dimensão de ação opcional retornada após o pós-processamento do EVO1      |
| `policy.binarize_gripper`                     | `false`                     | Binariza o canal do garra pós-processado para avaliação no estilo LIBERO |
| `policy.task_field`                           | `task`                      | Campo de lote usado como prompt de idioma                           |

## Inferência

Experimente com um checkpoint treinado do EVO1:

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

## Resultados

### Avaliação LIBERO

#### Resultado de referência

> [!NOTE]
> O checkpoint da Etapa 2 publicado passou na verificação de download limpo e rollout: [`zuoxingdong/evo1_libero`](https://huggingface.co/zuoxingdong/evo1_libero), revisão [`515921f4a2c1d3f3ad523721eafa26fdf2af315b`](https://huggingface.co/zuoxingdong/evo1_libero/commit/515921f4a2c1d3f3ad523721eafa26fdf2af315b). A avaliação de download limpo utilizou a revisão [`e40b58a8dfa9e7b86918c374791599d070518d11`](https://github.com/huggingface/lerobot/commit/e40b58a8dfa9e7b86918c374791599d070518d11) do LeRobot.

O checkpoint de Stage-2 de uma única execução no passo 70.000 produziu:

| Suite          | Episódios bem-sucedidos |  Episódios | Taxa de sucesso |
| -------------- | ------------------: | --------: | -----------: |
| LIBERO Spatial |                 485 |       500 |        97.0% |
| Objeto LIBERO  |                 496 |       500 |        99.2% |
| Objetivo do LIBERO    |                 483 |       500 |        96.6% |
| LIBERO-10      |                 469 |       500 |        93.8% |
| **Geral**    |           **1,933** | **2,000** |   **96.65%** |

Esses resultados usam um checkpoint treinado e uma semente de avaliação `1000`; eles não são uma média de múltiplas sementes nem uma estimativa de confiança.

#### Receita de treinamento de referência

O checkpoint publicado registra a configuração completa e resolvida da Etapa 2 em [`train_config.json`](https://huggingface.co/zuoxingdong/evo1_libero/blob/515921f4a2c1d3f3ad523721eafa26fdf2af315b/train_config.json). A execução medida utilizou duas GPUs H100 com dois processos DDP e batch 64 por processo, resultando em batch global 128. Ambas as etapas utilizaram a mesma topologia. O VLM base veio da revisão `014c0583a0d4bedf29fbe2dbff4f865eb998e171` de `OpenGVLab/InternVL3-1B-hf`. O artefato publicado não registra o commit exato de treinamento do LeRobot nem seu lock de dependências original, portanto, os comandos abaixo reproduzem a configuração e a topologia registradas a partir de um checkout atual, em vez de reconstruir o ambiente de software bit a bit.

A partir de um checkout da fonte do LeRobot, instale as dependências fixadas e baixe aquela revisão exata do VLM:

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

A Etapa 1 congela o VLM e treina a cabeça de ação por 5.000 passos:

```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
```

A Etapa 2 carrega a política da Etapa 1, mas inicia um otimizador e um agendador novos. O treinamento é executado por 80.000 passos; o checkpoint reportado é o salvo no passo 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
```

#### Perfil de avaliação no formato do autor

O perfil EVO1 LIBERO no formato do autor usa os nomes brutos dos recursos da câmera do LIBERO (`observation.images.agentview_image` e `observation.images.robot0_eye_in_hand_image`), replaneja a cada 14 ações e binariza o comando do garra antes de executar o passo no simulador. O pós-processador de política do EVO1 pode recortar a ação de 24D com preenchimento de volta para o espaço de ação de 7D do LIBERO e aplicar essa binarização do garra. Para avaliar um checkpoint no formato do autor sob a mesma configuração de um episódio por tarefa, mantenha os nomes brutos das câmeras em vez do mapeamento padrão `image`/`image2` e defina as flags de pós-processamento de ação do 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
```

#### Perfil nativo `lerobot/libero` v3

A revisão `a1aaacb7f6cd6ee5fb43120f673cebb0cfea7dd4` armazena os recursos da câmera como `image` e `image2`. Este exemplo avalia as dez tarefas LIBERO Object, iniciando cada tarefa em um novo processo:

```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
```

Execute os dez IDs de tarefa de cada suíte com esses horizontes:

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

Defina `suite` e `horizon` para cada linha. Isso resulta em 500 episódios por suite e 2.000 episódios no total, enquanto o processo novo por tarefa do loop corresponde à topologia de redefinição de RNG medida.

## Referências

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

## Licença

Esta integração do LeRobot segue a Licença Apache 2.0 utilizada pelo LeRobot. Consulte as páginas dos modelos EVO1 e InternVL3 no repositório original para verificar as licenças dos checkpoints e dados liberados.

