Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

Evo-1: Lightweight Vision-Language-Action Model with Preserved Semantic Alignment [CVPR 2026]

📄 Paper
🤗 HuggingFace Models
🤗 HuggingFace Models 📦 Dataset
🌍 Website

📰 News

  • 🗓️ 2026-08-05 — Evo-1 is now supported in the official RLinf framework 🔥: full-parameter SFT and GRPO fine-tuning on the LIBERO simulator (doc).
  • 🗓️ 2026-07-21 — Released RoboTwin evaluation (Evo-1 policy plugin + 50 bimanual tasks). See RoboTwin benchmark part.
  • 🗓️ 2026-07-20 — Release LIBERO-plus benchmark evaluation scripts and results. See LIBERO-plus benchmark part.
  • 🗓️ 2026-07-05 — Evo-1 has been added to the official LeRobot framework 🎉🎉.
  • 🗓️ 2026-06-07 — Evo-1 received the 🎖️ Efficient CVPR Badge 🎖️.
  • 🗓️ 2026-04-10 — Updated the evo1-flash branch: faster training with reduced GPU memory usage.
  • 🗓️ 2026-04-10 — Updated the evo1-lerobot branch: Evo-1 is now fully integrated into the LeRobot framework.
  • 🗓️ 2026-04-08 — Evo-1 is now fully integrated into the LeRobot framework!
  • 🗓️ 2026-04-08 — We released Evo-1 Docker support for Jetson (https://huggingface.co/datasets/MINT-SJTU/Evo-1_JetsonOrin).
  • 🗓️ 2026-02-20 — Evo-1 is accepted by CVPR 2026 🎉🎉
  • 🗓️ 2025-12-15 — Added Evo-1 inference code in Aloha dual arm (Implemented by community user @meijie-jesse)
  • 🗓️ 2025-11-15 — Added Evo-1 inference in the LeRobot framework for SO100/SO101
  • 🗓️ 2025-11-10 — Released inference script in xarm6
  • 🗓️ 2025-11-06 — Released Meta-World & LIBERO evaluation scripts
  • 🗓️ 2025-11-06 — Uploaded model weights to HuggingFace
  • 🗓️ 2025-11-06 — Released official code

✅ To-Do List

  • ✅ Release inference script in xarm6
  • ✅ Update evo1-flash branch (faster training + reduced GPU memory usage)
  • ✅ Update evo1-lerobot branch (fully integrated Evo-1 into the LeRobot framework)
  • ✅ Release instructions for deploying Evo-1 on Jetson Orin (https://huggingface.co/datasets/MINT-SJTU/Evo-1_JetsonOrin)
  • ✅ Release RoboTwin evaluation script
  • ✅ Release results of all 50 RoboTwin tasks

⚙️ Installation

Prepare the environment for Evo-1

# Clone this repo
git clone https://github.com/MINT-SJTU/Evo-1.git

cd Evo-1/

# Create a Conda environment
conda create -n Evo1 python=3.10 -y

conda activate Evo1

# Install requirements
cd Evo_1

pip install -r requirements.txt

# You may need to reduce MAX_JOBS to suit your computer
# (!!! This is a critical step — skipping it may cause lower success rate or unstable robot motion !!!)
MAX_JOBS=64 pip install -v flash-attn --no-build-isolation

🧪 Simulation Benchmark

💡 Tips

In downstream tasks, the client script needs to be processed according to different task configurations. Because the client executes states or actions in the absolute/original action space, while the actions sent by the server are in the relative action space. Therefore, if the benchmark evaluation uses absolute actions, an additional logic is required in the client script: convert the relative actions returned by the model back to absolute actions through accumulation. If the evaluation uses relative actions, no modification is needed.

🧪 Meta-World Benchmark

1️⃣ Prepare the environment for Meta-World

conda create -n metaworld python=3.10 -y
conda activate metaworld
pip install mujoco
pip install metaworld
pip install websockets
pip install opencv-python
pip install packaging
pip install huggingface_hub

2️⃣ Model Preparation

📥 2.1 Download Model Weight
hf download MINT-SJTU/Evo1_MetaWorld --local-dir /path/to/save/checkpoint/
✏️ 2.2 Modify config
  1. Modify checkpoint dir: Evo1_server.py
  2. Modify arm key and dataset key: The arm_key and dataset_key used during server inference must completely match the corresponding arm-dataset keys in the norm_stats.json in checkpoint. Located in Evo1_server.py
arm_key = "metaworld_robot"
dataset_key = "metaworld_dataset"

Tips: When using the old version model checkpoints, you only need to change the arm_key to the key name of the norm_stats.json file in the model checkpoint. For the new model checkpoints trained by the new version, you need to modify both arm_key and dataset_key.

  1. (Optional) Modify server port: Evo1_server.py
  2. (Optional) Modify client port: mt50_evo1_client_prompt.py

3️⃣ Run Meta-World Evaluation

# Terminal 1
conda activate Evo1

cd Evo_1

python scripts/Evo1_server.py
# Terminal 2
conda activate metaworld

cd MetaWorld_evaluation

python mt50_evo1_client_prompt.py

🧪 LIBERO Benchmark

1️⃣ Prepare the environment for LIBERO

conda create -n libero python=3.8.13 -y

conda activate libero

cd LIBERO_evaluation/

git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git

cd LIBERO

pip install -r requirements.txt

pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 torchaudio==0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113

pip install -e .

pip install websockets

pip install huggingface_hub

2️⃣ Model Preparation

📥 2.1 Download Model Weight
hf download MINT-SJTU/Evo1_LIBERO --local-dir /path/to/save/checkpoint/
✏️ 2.2 Modify config
  1. Modify checkpoint dir: Evo1_server.py
  2. Modify ckpt name: libero_client_4tasks.py
  3. Modify arm key and dataset key: The arm_key and dataset_key used during server inference must completely match the corresponding arm-dataset keys in the norm_stats.json in checkpoint. Located in Evo1_server.py
# Specialized for different downstream tasks.

# Old version checkpoint:
arm_key = "libero_robot"
dataset_key = "libero_4_datasets"

# New version trained checkpoint:
# Keep the same name as in your norm_stats.json, which is usually the same as the arm name in config.yaml
arm_key = "franka_ee_pose_delta"
dataset_key = "libero_10_no_noops_lerobot"

Tips: When using the old version model checkpoints, you only need to change the arm_key to the key name of the norm_stats.json file in the model checkpoint. For the new model checkpoints trained by the new version, you need to modify both arm_key and dataset_key.

  1. (Optional) Modify server port: Evo1_server.py
  2. (Optional) Modify client port: libero_client_4tasks.py

3️⃣ Run LIBERO Evaluation

# Terminal 1
conda activate Evo1

cd Evo_1

python scripts/Evo1_server.py
# Terminal 2
conda activate libero

cd LIBERO_evaluation

python libero_client_4tasks.py


🧪 LIBERO-plus Benchmark

1️⃣ Prepare the environment for LIBERO-plus

Prepare LIBERO-plus evaluation environment, detailed instructions can be found in libero-plus-eval/README.md. Follow Step 1 to Step 6 to set up the environment and download the necessary assets.

2️⃣ Model Preparation

📥 2.1 Download Model Weight

LIBERO-plus model use the same Evo-1 model weight as LIBERO, you can download it from HuggingFace:

hf download MINT-SJTU/Evo1_LIBERO --local-dir /path/to/save/checkpoint/
✏️ 2.2 Modify server config
  1. Modify checkpoint dir: Evo1_server.py
  2. Modify arm key and dataset key to match your LIBERO checkpoint's norm_stats.json, same as step 2.2 of the LIBERO Benchmark: Evo1_server.py
  3. (Optional) Modify server port: Evo1_server.py

3️⃣ Run LIBERO-plus Evaluation

# Terminal 1
conda activate Evo1

cd Evo_1

python scripts/Evo1_server.py

Open another terminal and run the evaluation script for LIBERO-plus, more specific instructions can be found in libero-plus-eval/README.md Step 7. Following is an simple example of running the evaluation for the libero_spatial suite:

# Terminal 2
conda activate libero_plus
export LIBERO_CONFIG_PATH="$HOME/.libero-plus"
cd /path/to/libero-plus-eval

bash test_libero_plus.sh libero_spatial


🧪 RoboTwin Benchmark

RoboTwin (50 bimanual manipulation tasks in SAPIEN) uses a policy-plugin architecture: start the Evo-1 server, drop the Evo-1 policy adapter into a RoboTwin checkout, and launch RoboTwin's evaluator as the client.

1️⃣ Prepare the environment for RoboTwin

RoboTwin is not bundled in this repo. Clone and install it separately (SAPIEN + CuRobo are required).

Version note: all RoboTwin results in this repo were produced against the official stable_2.0 branch. RoboTwin main has since migrated to the XPolicyLab evaluation stack and removed the policy/ plugin layout these instructions rely on — make sure to clone stable_2.0 as below.

conda create -n RoboTwin python=3.10 -y
conda activate RoboTwin

git clone -b stable_2.0 https://github.com/RoboTwin-Platform/RoboTwin.git
cd RoboTwin
pip install -r script/requirements.txt
pip install websockets

# CuRobo is REQUIRED — expert solvability check and scene setup use its motion planner
cd envs && git clone -b v0.7.8 --depth 1 https://github.com/NVlabs/curobo.git
cd curobo && python -m pip install -e . --no-build-isolation && cd ../..

See the RoboTwin README (stable_2.0) for full setup (assets, SAPIEN, mplib).

2️⃣ Model Preparation

📥 2.1 Download Model Weight
hf download MINT-SJTU/Evo1_RoboTwin2_clean --local-dir /path/to/save/checkpoint/
✏️ 2.2 Modify config
  1. Modify checkpoint dir: Evo1_server.py
  2. arm_key / dataset_key: no server edit needed for RoboTwin. The client sends them per request (arm_key=aloha_joint, per-task dataset_key=robotwin_<task>) and the server reads them from the payload. RoboTwin norm_stats.json is keyed per task (50 keys under aloha_joint), so a single fixed dataset_key would be wrong for 49/50 tasks — the per-request key is required.
  3. (Optional) Modify server port: Evo1_server.py
🔌 2.3 Install the Evo-1 policy plugin into RoboTwin
cp -r RoboTwin_evaluation/policy/Evo1  /path/to/RoboTwin/policy/Evo1

3️⃣ Run RoboTwin Evaluation

# Terminal 1 — Evo-1 server (PYTHONPATH=. lets the server import scripts.* and config)
conda activate Evo1
cd Evo_1
PYTHONPATH=. python scripts/Evo1_server.py
# Terminal 2 — RoboTwin client, one task
conda activate RoboTwin
cd /path/to/RoboTwin/policy/Evo1

# Usage: bash eval.sh <task_name> [task_config] [ckpt_setting] [seed] [gpu_id] [server_url] [horizon]
bash eval.sh place_burger_fries demo_clean step_20000 0 0 ws://0.0.0.0:9000 37

Each task runs 100 episodes with expert solvability check; results are written under RoboTwin/eval_result/.


🧠 Training on Your Own Dataset

We support lerobot v2.1 format, please convert your data to this format.

Below we will demonstrate how to prepare the dataset, modify configurations, and start the two-stage pretraining along with standard VLA finetuning.

🗂️ 1. Data Preparation

First, you need to download the dataset for pretraining. Taking the Libero dataset as an example, assuming you are located in the project root directory, run the following commands to download the dataset:

mkdir -p Evo1_training_dataset/libero_standard
cd Evo1_training_dataset/libero_standard

# 1) spatial
GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/datasets/IPEC-COMMUNITY/libero_spatial_no_noops_1.0.0_lerobot
cd libero_spatial_no_noops_1.0.0_lerobot
git lfs pull
cd ..

# 2) object
GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/datasets/IPEC-COMMUNITY/libero_object_no_noops_1.0.0_lerobot
cd libero_object_no_noops_1.0.0_lerobot
git lfs pull
cd ..

# 3) goal
GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/datasets/IPEC-COMMUNITY/libero_goal_no_noops_1.0.0_lerobot
cd libero_goal_no_noops_1.0.0_lerobot
git lfs pull
cd ..

# 4) libero_10
GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/datasets/IPEC-COMMUNITY/libero_10_no_noops_1.0.0_lerobot
cd libero_10_no_noops_1.0.0_lerobot
git lfs pull
cd ../../..

✏️ 2. Data Configuration & Norm Stats

✏️ 2.1 Modify config.yaml

You need to modify the detailed config. For detailed dataset configuration (how to define suite, modify config.yaml, configure cache_dir, etc.), please refer to: Detailed Tutorial for Dataset Configuration.

✏️ 2.2 Compute Norm Stats

After configuring the config.yaml, it is necessary to calculate the statistical values (norm_stats) of each feature in the dataset:

cd Evo_1/
python -m dataset.compute_normstats dataset/config.yaml --action_horizon 50

Run the command above to compute the statistical characteristics for the datasets included in the config, which consist of max, min, q01, q99, mean, and std.

If an OOM error occurs while running the above code, you can run the streaming version instead:

cd Evo_1/
python -m dataset.compute_normstats_streaming dataset/config.yaml --action_horizon 50

🚀 3. Start Training

We use the two-stage training paradigm.

🚀 3.1 Setup deepspeed

accelerate config     

You can check this setup guide


🚀 3.2 Training Stage 1

We only train the integration module and action expert in stage 1.

If you are training with multiple GPU, set --num_processes to the GPU number.
You need to change the --wandb_project, --run_name, --save_dir, and --cache_dir base on your own config. You may also change other options based on your need.

conda activate Evo1

cd Evo_1/

accelerate launch --num_processes 1 --num_machines 1 --deepspeed_config_file ds_config.json scripts/train.py --wandb_project your_project_name --run_name Evo1_flash_libero4_stage1 --action_head flowmatching --use_augmentation --lr 1e-5 --dropout 0.2 --weight_decay 1e-3 --batch_size 16 --image_size 448 --max_steps 20000 --log_interval 10 --ckpt_interval 5000 --warmup_steps 1000 --grad_clip_norm 1.0 --num_layers 8 --horizon 50 --finetune_action_head --disable_wandb --prefetch_factor 2 --video_backend av --cache_dir /your/path/to/dataset_cache/evo1_libero_4_cache --vlm_name OpenGVLab/InternVL3-1B --dataset_config_path dataset/config.yaml --per_action_dim 24 --state_dim 24 --save_dir /your/path/checkpoints/stage1

🚀 3.3 Training Stage 2

We perform Full-scale training in stage 2. You need to change the --wandb_project, --run_name, --save_dir, --resume_path and --cache_dir base on your own config. You may also change other options based on your need.

conda activate Evo1

cd Evo_1/

accelerate launch --num_processes 1 --num_machines 1 --deepspeed_config_file ds_config.json scripts/train.py --wandb_project your_project_name --run_name Evo1_libero_stage2 --action_head flowmatching --use_augmentation --lr 1e-5 --dropout 0.2 --weight_decay 1e-3 --batch_size 16 --image_size 448 --max_steps 80000 --log_interval 10 --ckpt_interval 5000 --warmup_steps 1000 --grad_clip_norm 1.0 --num_layers 8 --horizon 50 --finetune_vlm --finetune_action_head --disable_wandb --prefetch_factor 2 --video_backend av --cache_dir /your/path/to/dataset_cache/evo1_libero_4_seg_cache --vlm_name OpenGVLab/InternVL3-1B --dataset_config_path dataset/config.yaml --per_action_dim 24 --state_dim 24 --save_dir /your/path/checkpoints/stage2 --resume --resume_pretrain --resume_path /your/path/checkpoints/stage1/step_10000

🚀 3.4 (Optional) Resume Training

If you want to resume the training process, you can use the following command (we use stage 2 as an example):

accelerate launch --num_processes 1 --num_machines 1 --deepspeed_config_file ds_config.json scripts/train.py --wandb_project your_project_name --run_name Evo1_libero_stage2_resume --action_head flowmatching --use_augmentation --lr 1e-5 --dropout 0.2 --weight_decay 1e-3 --batch_size 16 --image_size 448 --max_steps 80000 --log_interval 10 --ckpt_interval 5000 --warmup_steps 1000 --grad_clip_norm 1.0 --num_layers 8 --horizon 50 --finetune_vlm --finetune_action_head --disable_wandb --prefetch_factor 2 --video_backend av --cache_dir /your/path/to/dataset_cache/evo1_libero_4_seg_cache --vlm_name OpenGVLab/InternVL3-1B --dataset_config_path dataset/config.yaml --per_action_dim 24 --state_dim 24 --save_dir /your/path/checkpoints/stage2 --resume  --resume_path /the/checkpoint/path/you/want/to/resume/from/step_20000

🦾 4. Inference in Your Own Embodiment

We provide an example of inference client script Evo1_client_xarm6 for xArm6.

The key is to construct an observation dict and pass it to the server.

      obs = {
            # You need to change the image size to 448x448 before send in obs
            "image": [base_proc.tolist(), wrist_proc.tolist(), dummy_proc.tolist()],  
            # This shows which image is valid.
            "image_mask": [int(i) for i in [1, 1, 0]],
            # This is the state of the robot.
            "state": state.astype(float).tolist(),
            # This is the action mask that shows which action is valid.
            "action_mask": [[int(i) for i in action_mask[0]]],
            # This is the instruction of the task
            "prompt": task_instruction
      }

      try:
            # Send the observation to the server
            await ws.send(json.dumps(obs))
            result = await ws.recv()
            # Get the action chunk
            action_chunk = torch.tensor(json.loads(result))
            
      except Exception as e:
            print(f"❌ Inference Error: {e}")
            await asyncio.sleep(0.5)
            continue

🤖 5.Inference in Lerobot SO100/SO101

For detailed instructions, please check out the evo1-lerobot branch.

📚 Citation

@article{lin2025evo,
  title={Evo-1: Lightweight Vision-Language-Action Model with Preserved Semantic Alignment},
  author={Lin, Tao and Zhong, Yilei and Du, Yuxin and Zhang, Jingjing and Liu, Jiting and Chen, Yinxinyu and Gu, Encheng and Liu, Ziyan and Cai, Hongyi and Zou, Yanwen and others},
  journal={arXiv preprint arXiv:2511.04555},
  year={2025}
}

📬 Contact

If you encounter any issues or have suggestions,
please open an issue or start a discussion on GitHub.
We sincerely welcome your feedback and contributions.

You can also scan the QR code below to connect with me or join chatting group on WeChat:

关于 About

Evo-1: Lightweight Vision-Language-Action Model with Preserved Semantic Alignment

语言 Languages

Python93.2%
MDX6.6%
Makefile0.2%
Shell0.0%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
83
Total Commits
峰值: 25次/周
Less
More

核心贡献者 Contributors