{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7082c8b7",
   "metadata": {},
   "source": [
    "# 部署已训练的 SmolVLA 策略\n",
    "\n",
    "<img src=\"./media/rollout3.gif\" width=\"480\" height=\"360\">\n",
    "\n",
    "在仿真中部署已训练策略。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ab95e0af",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting transformers==4.50.3\n",
      "  Downloading transformers-4.50.3-py3-none-any.whl.metadata (39 kB)\n",
      "Requirement already satisfied: filelock in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (3.18.0)\n",
      "Requirement already satisfied: huggingface-hub<1.0,>=0.26.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (0.29.3)\n",
      "Requirement already satisfied: numpy>=1.17 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (1.26.4)\n",
      "Requirement already satisfied: packaging>=20.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (24.2)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (6.0.2)\n",
      "Requirement already satisfied: regex!=2019.12.17 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (2024.11.6)\n",
      "Requirement already satisfied: requests in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (2.32.3)\n",
      "Requirement already satisfied: tokenizers<0.22,>=0.21 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (0.21.1)\n",
      "Requirement already satisfied: safetensors>=0.4.3 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (0.5.3)\n",
      "Requirement already satisfied: tqdm>=4.27 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from transformers==4.50.3) (4.67.1)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface-hub<1.0,>=0.26.0->transformers==4.50.3) (2024.12.0)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface-hub<1.0,>=0.26.0->transformers==4.50.3) (4.12.2)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->transformers==4.50.3) (3.4.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->transformers==4.50.3) (3.10)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->transformers==4.50.3) (2.3.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->transformers==4.50.3) (2025.1.31)\n",
      "Downloading transformers-4.50.3-py3-none-any.whl (10.2 MB)\n",
      "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m10.2/10.2 MB\u001b[0m \u001b[31m9.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m \u001b[36m0:00:01\u001b[0mm\n",
      "\u001b[?25hInstalling collected packages: transformers\n",
      "  Attempting uninstall: transformers\n",
      "    Found existing installation: transformers 4.48.0\n",
      "    Uninstalling transformers-4.48.0:\n",
      "      Successfully uninstalled transformers-4.48.0\n",
      "Successfully installed transformers-4.50.3\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
      "Collecting num2words\n",
      "  Downloading num2words-0.5.14-py3-none-any.whl.metadata (13 kB)\n",
      "Collecting docopt>=0.6.2 (from num2words)\n",
      "  Downloading docopt-0.6.2.tar.gz (25 kB)\n",
      "  Installing build dependencies ... \u001b[?25ldone\n",
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25ldone\n",
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n",
      "\u001b[?25hDownloading num2words-0.5.14-py3-none-any.whl (163 kB)\n",
      "Building wheels for collected packages: docopt\n",
      "  Building wheel for docopt (pyproject.toml) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for docopt: filename=docopt-0.6.2-py2.py3-none-any.whl size=13783 sha256=ef1ba085d70e4411967fffcddc818dc531cb337d06df7da9950b01795d4b3b20\n",
      "  Stored in directory: /home/jeongeun/.cache/pip/wheels/fc/ab/d4/5da2067ac95b36618c629a5f93f809425700506f72c9732fac\n",
      "Successfully built docopt\n",
      "Installing collected packages: docopt, num2words\n",
      "Successfully installed docopt-0.6.2 num2words-0.5.14\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
      "Collecting accelerate\n",
      "  Downloading accelerate-1.8.1-py3-none-any.whl.metadata (19 kB)\n",
      "Requirement already satisfied: numpy<3.0.0,>=1.17 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (1.26.4)\n",
      "Requirement already satisfied: packaging>=20.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (24.2)\n",
      "Requirement already satisfied: psutil in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (7.0.0)\n",
      "Requirement already satisfied: pyyaml in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (6.0.2)\n",
      "Requirement already satisfied: torch>=2.0.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (2.6.0)\n",
      "Requirement already satisfied: huggingface_hub>=0.21.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (0.29.3)\n",
      "Requirement already satisfied: safetensors>=0.4.3 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from accelerate) (0.5.3)\n",
      "Requirement already satisfied: filelock in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface_hub>=0.21.0->accelerate) (3.18.0)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface_hub>=0.21.0->accelerate) (2024.12.0)\n",
      "Requirement already satisfied: requests in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface_hub>=0.21.0->accelerate) (2.32.3)\n",
      "Requirement already satisfied: tqdm>=4.42.1 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface_hub>=0.21.0->accelerate) (4.67.1)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from huggingface_hub>=0.21.0->accelerate) (4.12.2)\n",
      "Requirement already satisfied: networkx in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (3.4.2)\n",
      "Requirement already satisfied: jinja2 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (3.1.6)\n",
      "Requirement already satisfied: nvidia-cuda-nvrtc-cu12==12.4.127 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.4.127)\n",
      "Requirement already satisfied: nvidia-cuda-runtime-cu12==12.4.127 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.4.127)\n",
      "Requirement already satisfied: nvidia-cuda-cupti-cu12==12.4.127 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.4.127)\n",
      "Requirement already satisfied: nvidia-cudnn-cu12==9.1.0.70 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (9.1.0.70)\n",
      "Requirement already satisfied: nvidia-cublas-cu12==12.4.5.8 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.4.5.8)\n",
      "Requirement already satisfied: nvidia-cufft-cu12==11.2.1.3 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (11.2.1.3)\n",
      "Requirement already satisfied: nvidia-curand-cu12==10.3.5.147 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (10.3.5.147)\n",
      "Requirement already satisfied: nvidia-cusolver-cu12==11.6.1.9 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (11.6.1.9)\n",
      "Requirement already satisfied: nvidia-cusparse-cu12==12.3.1.170 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.3.1.170)\n",
      "Requirement already satisfied: nvidia-cusparselt-cu12==0.6.2 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (0.6.2)\n",
      "Requirement already satisfied: nvidia-nccl-cu12==2.21.5 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (2.21.5)\n",
      "Requirement already satisfied: nvidia-nvtx-cu12==12.4.127 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.4.127)\n",
      "Requirement already satisfied: nvidia-nvjitlink-cu12==12.4.127 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (12.4.127)\n",
      "Requirement already satisfied: triton==3.2.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (3.2.0)\n",
      "Requirement already satisfied: sympy==1.13.1 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from torch>=2.0.0->accelerate) (1.13.1)\n",
      "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from sympy==1.13.1->torch>=2.0.0->accelerate) (1.3.0)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from jinja2->torch>=2.0.0->accelerate) (3.0.2)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->huggingface_hub>=0.21.0->accelerate) (3.4.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->huggingface_hub>=0.21.0->accelerate) (3.10)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->huggingface_hub>=0.21.0->accelerate) (2.3.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages (from requests->huggingface_hub>=0.21.0->accelerate) (2025.1.31)\n",
      "Downloading accelerate-1.8.1-py3-none-any.whl (365 kB)\n",
      "Installing collected packages: accelerate\n",
      "Successfully installed accelerate-1.8.1\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install transformers==4.50.3\n",
    "!pip install num2words\n",
    "!pip install accelerate\n",
    "!pip install safetensors>=0.4.3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c036d1f",
   "metadata": {},
   "source": [
    "### 【可选】下载数据集\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3c3d929",
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "If you want to use the collected dataset, please download it from Hugging Face.\n",
    "'''\n",
    "# Optional: skip cloning if demo_data_language already contains your collected data.\n",
    "!git lfs install\n",
    "!git clone https://huggingface.co/datasets/Datawhale/datawhale_eai_pnp_language demo_data_language\n",
    "!git -C demo_data_language lfs pull"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a246fa3e",
   "metadata": {},
   "source": [
    "## 第 2 步：训练模型\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7ca989d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Use smolvla_datawhale_eai.yaml in this directory; see README.md for dataset paths.\n",
    "!python train_model.py --config_path smolvla_datawhale_eai.yaml"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20673462",
   "metadata": {},
   "source": [
    "## 第 3 步：部署\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "07386e5a",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/jeongeun/.pyenv/versions/3.10.2/envs/lerobot/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "source": [
    "from lerobot.common.datasets.lerobot_dataset import LeRobotDataset, LeRobotDatasetMetadata\n",
    "import numpy as np\n",
    "from lerobot.common.datasets.utils import write_json, serialize_dict\n",
    "from lerobot.common.policies.smolvla.configuration_smolvla import SmolVLAConfig\n",
    "from lerobot.common.policies.smolvla.modeling_smolvla import SmolVLAPolicy\n",
    "from lerobot.configs.types import FeatureType\n",
    "from lerobot.common.datasets.factory import resolve_delta_timestamps\n",
    "from lerobot.common.datasets.utils import dataset_to_policy_features\n",
    "import torch\n",
    "from PIL import Image\n",
    "import torchvision"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0b1f651f",
   "metadata": {},
   "outputs": [],
   "source": [
    "device = 'cuda'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "381de80f",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:root:Device 'None' is not available. Switching to 'cuda'.\n"
     ]
    }
   ],
   "source": [
    "dataset_metadata = LeRobotDatasetMetadata(\"datawhale_eai_pnp_language\", root='./demo_data_language')\n",
    "features = dataset_to_policy_features(dataset_metadata.features)\n",
    "output_features = {key: ft for key, ft in features.items() if ft.type is FeatureType.ACTION}\n",
    "input_features = {key: ft for key, ft in features.items() if key not in output_features}\n",
    "# Policies are initialized with a configuration class, in this case `DiffusionConfig`. For this example,\n",
    "# we'll just use the defaults and so no arguments other than input/output features need to be passed.\n",
    "# Temporal ensemble to make smoother trajectory predictions\n",
    "cfg = SmolVLAConfig(input_features=input_features, output_features=output_features, chunk_size= 5, n_action_steps=5)\n",
    "delta_timestamps = resolve_delta_timestamps(cfg, dataset_metadata)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8f580fb-d968-460c-9628-2067c249fcbd",
   "metadata": {},
   "source": [
    "# We can now instantiate our policy with this config and the dataset stats.\n",
    "policy = SmolVLAPolicy.from_pretrained('./ckpt/smolvla_datawhale_eai/checkpoints/last/pretrained_model', dataset_stats=dataset_metadata.stats)\n",
    "# You can load the trained policy from hub if you don't have the resources to train it.\n",
    "# policy = SmolVLAPolicy.from_pretrained(\"datawhale-eai/smolvla_datawhale_eai\", config=cfg, dataset_stats=dataset_metadata.stats)\n",
    "policy.to(device)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "85ebd9c8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "-----------------------------------------------------------------------------\n",
      "name:[Tabletop] dt:[0.002] HZ:[500]\n",
      " n_qpos:[31] n_qvel:[28] n_qacc:[28] n_ctrl:[10]\n",
      " integrator:[IMPLICITFAST]\n",
      "\n",
      "n_body:[23]\n",
      " [0/23] [world] mass:[0.00]kg\n",
      " [1/23] [front_object_table] mass:[1.00]kg\n",
      " [2/23] [camera] mass:[0.00]kg\n",
      " [3/23] [camera2] mass:[0.00]kg\n",
      " [4/23] [camera3] mass:[0.00]kg\n",
      " [5/23] [link1] mass:[2.06]kg\n",
      " [6/23] [link2] mass:[3.68]kg\n",
      " [7/23] [link3] mass:[2.39]kg\n",
      " [8/23] [link4] mass:[1.40]kg\n",
      " [9/23] [link5] mass:[1.40]kg\n",
      " [10/23] [link6] mass:[0.65]kg\n",
      " [11/23] [camera_center] mass:[0.00]kg\n",
      " [12/23] [tcp_link] mass:[0.32]kg\n",
      " [13/23] [rh_p12_rn_r1] mass:[0.07]kg\n",
      " [14/23] [rh_p12_rn_r2] mass:[0.02]kg\n",
      " [15/23] [rh_p12_rn_l1] mass:[0.07]kg\n",
      " [16/23] [rh_p12_rn_l2] mass:[0.02]kg\n",
      " [17/23] [body_obj_mug_5] mass:[0.00]kg\n",
      " [18/23] [object_mug_5] mass:[0.08]kg\n",
      " [19/23] [body_obj_plate_11] mass:[0.00]kg\n",
      " [20/23] [object_plate_11] mass:[0.10]kg\n",
      " [21/23] [body_obj_mug_6] mass:[0.00]kg\n",
      " [22/23] [object_mug_6] mass:[0.08]kg\n",
      "body_total_mass:[13.35]kg\n",
      "\n",
      "n_geom:[116]\n",
      "geom_names:['floor', None, 'front_object_table', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]\n",
      "\n",
      "n_mesh:[112]\n",
      "mesh_names:['base_unit', 'link1', 'link2', 'link3', 'link4', 'link5', 'link6', 'flange', 'base', 'r1', 'r2', 'l1', 'l2', 'mug_5_normalized_0_vis', 'mug_5_normalized_collision_22._coll', 'mug_5_normalized_collision_23._coll', 'mug_5_normalized_collision_21._coll', 'mug_5_normalized_collision_20._coll', 'mug_5_normalized_collision_24._coll', 'mug_5_normalized_collision_30._coll', 'mug_5_normalized_collision_18._coll', 'mug_5_normalized_collision_19._coll', 'mug_5_normalized_collision_31._coll', 'mug_5_normalized_collision_25._coll', 'mug_5_normalized_collision_27._coll', 'mug_5_normalized_collision_26._coll', 'mug_5_normalized_collision_9._coll', 'mug_5_normalized_collision_8._coll', 'mug_5_normalized_collision_6._coll', 'mug_5_normalized_collision_7._coll', 'mug_5_normalized_collision_5._coll', 'mug_5_normalized_collision_4._coll', 'mug_5_normalized_collision_0._coll', 'mug_5_normalized_collision_1._coll', 'mug_5_normalized_collision_3._coll', 'mug_5_normalized_collision_2._coll', 'mug_5_normalized_collision_17._coll', 'mug_5_normalized_collision_16._coll', 'mug_5_normalized_collision_28._coll', 'mug_5_normalized_collision_14._coll', 'mug_5_normalized_collision_15._coll', 'mug_5_normalized_collision_29._coll', 'mug_5_normalized_collision_11._coll', 'mug_5_normalized_collision_10._coll', 'mug_5_normalized_collision_12._coll', 'mug_5_normalized_collision_13._coll', 'plate_11_normalized_0_vis', 'plate_11_normalized_collision_22._coll', 'plate_11_normalized_collision_23._coll', 'plate_11_normalized_collision_21._coll', 'plate_11_normalized_collision_20._coll', 'plate_11_normalized_collision_24._coll', 'plate_11_normalized_collision_30._coll', 'plate_11_normalized_collision_18._coll', 'plate_11_normalized_collision_19._coll', 'plate_11_normalized_collision_31._coll', 'plate_11_normalized_collision_25._coll', 'plate_11_normalized_collision_27._coll', 'plate_11_normalized_collision_26._coll', 'plate_11_normalized_collision_9._coll', 'plate_11_normalized_collision_8._coll', 'plate_11_normalized_collision_6._coll', 'plate_11_normalized_collision_7._coll', 'plate_11_normalized_collision_5._coll', 'plate_11_normalized_collision_4._coll', 'plate_11_normalized_collision_0._coll', 'plate_11_normalized_collision_1._coll', 'plate_11_normalized_collision_3._coll', 'plate_11_normalized_collision_2._coll', 'plate_11_normalized_collision_17._coll', 'plate_11_normalized_collision_16._coll', 'plate_11_normalized_collision_28._coll', 'plate_11_normalized_collision_14._coll', 'plate_11_normalized_collision_15._coll', 'plate_11_normalized_collision_29._coll', 'plate_11_normalized_collision_11._coll', 'plate_11_normalized_collision_10._coll', 'plate_11_normalized_collision_12._coll', 'plate_11_normalized_collision_13._coll', 'mug_6_normalized_0_vis', 'mug_6_normalized_collision_22._coll', 'mug_6_normalized_collision_23._coll', 'mug_6_normalized_collision_21._coll', 'mug_6_normalized_collision_20._coll', 'mug_6_normalized_collision_24._coll', 'mug_6_normalized_collision_30._coll', 'mug_6_normalized_collision_18._coll', 'mug_6_normalized_collision_19._coll', 'mug_6_normalized_collision_31._coll', 'mug_6_normalized_collision_25._coll', 'mug_6_normalized_collision_27._coll', 'mug_6_normalized_collision_26._coll', 'mug_6_normalized_collision_9._coll', 'mug_6_normalized_collision_8._coll', 'mug_6_normalized_collision_6._coll', 'mug_6_normalized_collision_7._coll', 'mug_6_normalized_collision_5._coll', 'mug_6_normalized_collision_4._coll', 'mug_6_normalized_collision_0._coll', 'mug_6_normalized_collision_1._coll', 'mug_6_normalized_collision_3._coll', 'mug_6_normalized_collision_2._coll', 'mug_6_normalized_collision_17._coll', 'mug_6_normalized_collision_16._coll', 'mug_6_normalized_collision_28._coll', 'mug_6_normalized_collision_14._coll', 'mug_6_normalized_collision_15._coll', 'mug_6_normalized_collision_29._coll', 'mug_6_normalized_collision_11._coll', 'mug_6_normalized_collision_10._coll', 'mug_6_normalized_collision_12._coll', 'mug_6_normalized_collision_13._coll']\n",
      "\n",
      "n_joint:[13]\n",
      " [0/13] [joint1] axis:[0. 0. 1.]\n",
      " [1/13] [joint2] axis:[0. 1. 0.]\n",
      " [2/13] [joint3] axis:[0. 1. 0.]\n",
      " [3/13] [joint4] axis:[0. 1. 0.]\n",
      " [4/13] [joint5] axis:[0. 0. 1.]\n",
      " [5/13] [joint6] axis:[0. 1. 0.]\n",
      " [6/13] [rh_r1] axis:[1. 0. 0.]\n",
      " [7/13] [rh_r2] axis:[-1.  0.  0.]\n",
      " [8/13] [rh_l1] axis:[-1.  0.  0.]\n",
      " [9/13] [rh_l2] axis:[1. 0. 0.]\n",
      " [10/13] [None] axis:[0. 0. 1.]\n",
      " [11/13] [None] axis:[0. 0. 1.]\n",
      " [12/13] [None] axis:[0. 0. 1.]\n",
      "\n",
      "n_dof:[28] (=number of rows of Jacobian)\n",
      " [0/28] [None] attached joint:[joint1] body:[link1]\n",
      " [1/28] [None] attached joint:[joint2] body:[link2]\n",
      " [2/28] [None] attached joint:[joint3] body:[link3]\n",
      " [3/28] [None] attached joint:[joint4] body:[link4]\n",
      " [4/28] [None] attached joint:[joint5] body:[link5]\n",
      " [5/28] [None] attached joint:[joint6] body:[link6]\n",
      " [6/28] [None] attached joint:[rh_r1] body:[rh_p12_rn_r1]\n",
      " [7/28] [None] attached joint:[rh_r2] body:[rh_p12_rn_r2]\n",
      " [8/28] [None] attached joint:[rh_l1] body:[rh_p12_rn_l1]\n",
      " [9/28] [None] attached joint:[rh_l2] body:[rh_p12_rn_l2]\n",
      " [10/28] [None] attached joint:[None] body:[body_obj_mug_5]\n",
      " [11/28] [None] attached joint:[None] body:[body_obj_mug_5]\n",
      " [12/28] [None] attached joint:[None] body:[body_obj_mug_5]\n",
      " [13/28] [None] attached joint:[None] body:[body_obj_mug_5]\n",
      " [14/28] [None] attached joint:[None] body:[body_obj_mug_5]\n",
      " [15/28] [None] attached joint:[None] body:[body_obj_mug_5]\n",
      " [16/28] [None] attached joint:[None] body:[body_obj_plate_11]\n",
      " [17/28] [None] attached joint:[None] body:[body_obj_plate_11]\n",
      " [18/28] [None] attached joint:[None] body:[body_obj_plate_11]\n",
      " [19/28] [None] attached joint:[None] body:[body_obj_plate_11]\n",
      " [20/28] [None] attached joint:[None] body:[body_obj_plate_11]\n",
      " [21/28] [None] attached joint:[None] body:[body_obj_plate_11]\n",
      " [22/28] [None] attached joint:[None] body:[body_obj_mug_6]\n",
      " [23/28] [None] attached joint:[None] body:[body_obj_mug_6]\n",
      " [24/28] [None] attached joint:[None] body:[body_obj_mug_6]\n",
      " [25/28] [None] attached joint:[None] body:[body_obj_mug_6]\n",
      " [26/28] [None] attached joint:[None] body:[body_obj_mug_6]\n",
      " [27/28] [None] attached joint:[None] body:[body_obj_mug_6]\n",
      "\n",
      "Free joint information. n_free_joint:[3]\n",
      " [0/3] [None] body_name_attached:[body_obj_mug_5]\n",
      " [1/3] [None] body_name_attached:[body_obj_plate_11]\n",
      " [2/3] [None] body_name_attached:[body_obj_mug_6]\n",
      "\n",
      "Revolute joint information. n_rev_joint:[10]\n",
      " [0/10] [joint1] range:[-6.283]~[6.283]\n",
      " [1/10] [joint2] range:[-6.283]~[6.283]\n",
      " [2/10] [joint3] range:[-6.283]~[6.283]\n",
      " [3/10] [joint4] range:[-6.283]~[6.283]\n",
      " [4/10] [joint5] range:[-6.283]~[6.283]\n",
      " [5/10] [joint6] range:[-6.283]~[6.283]\n",
      " [6/10] [rh_r1] range:[0.000]~[1.100]\n",
      " [7/10] [rh_r2] range:[0.000]~[1.000]\n",
      " [8/10] [rh_l1] range:[0.000]~[1.100]\n",
      " [9/10] [rh_l2] range:[0.000]~[1.000]\n",
      "\n",
      "Prismatic joint information. n_pri_joint:[0]\n",
      "\n",
      "Control information. n_ctrl:[10]\n",
      " [0/10] [actuator_joint1] range:[-6.283]~[6.283] gear:[1.00] type:[JOINT]\n",
      " [1/10] [actuator_joint2] range:[-6.283]~[6.283] gear:[1.00] type:[JOINT]\n",
      " [2/10] [actuator_joint3] range:[-6.283]~[6.283] gear:[1.00] type:[JOINT]\n",
      " [3/10] [actuator_joint4] range:[-6.283]~[6.283] gear:[1.00] type:[JOINT]\n",
      " [4/10] [actuator_joint5] range:[-6.283]~[6.283] gear:[1.00] type:[JOINT]\n",
      " [5/10] [actuator_joint6] range:[-6.283]~[6.283] gear:[1.00] type:[JOINT]\n",
      " [6/10] [actuator_rh_r1] range:[0.000]~[1.100] gear:[1.00] type:[JOINT]\n",
      " [7/10] [actuator_rh_r2] range:[0.000]~[1.000] gear:[1.00] type:[JOINT]\n",
      " [8/10] [actuator_rh_l1] range:[0.000]~[1.100] gear:[1.00] type:[JOINT]\n",
      " [9/10] [actuator_rh_l2] range:[0.000]~[1.000] gear:[1.00] type:[JOINT]\n",
      "\n",
      "Camera information. n_cam:[4]\n",
      " [0/4] [agentview] fov:[60.0]\n",
      " [1/4] [topview] fov:[90.0]\n",
      " [2/4] [sideview] fov:[90.0]\n",
      " [3/4] [egocentric] fov:[90.0]\n",
      "\n",
      "n_sensor:[0]\n",
      "sensor_names:[]\n",
      "n_site:[9]\n",
      "site_names:['bottom_site_mug_5', 'top_site_mug_5', 'horizontal_radius_site_mug_5', 'bottom_site_plate_11', 'top_site_plate_11', 'horizontal_radius_site_plate_11', 'bottom_site_mug_6', 'top_site_mug_6', 'horizontal_radius_site_mug_6']\n",
      "-----------------------------------------------------------------------------\n",
      "env:[Tabletop] reset\n",
      "env:[Tabletop] reset\n",
      "env:[Tabletop] initalize viewer\n",
      "DONE INITIALIZATION\n"
     ]
    }
   ],
   "source": [
    "from mujoco_env.y_env2 import SimpleEnv2\n",
    "xml_path = './asset/example_scene_y2.xml'\n",
    "PnPEnv = SimpleEnv2(xml_path, action_type='joint_angle')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "db761f31",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torchvision import transforms\n",
    "# Approach 1: Using torchvision.transforms\n",
    "def get_default_transform(image_size: int = 224):\n",
    "    \"\"\"\n",
    "    Returns a torchvision transform that:\n",
    "     Converts to a FloatTensor and scales pixel values [0,255] -> [0.0,1.0]\n",
    "    \"\"\"\n",
    "    return transforms.Compose([\n",
    "        transforms.ToTensor(),  # PIL [0–255] -> FloatTensor [0.0–1.0], shape C×H×W\n",
    "    ])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0a7d54a5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DONE INITIALIZATION\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_3326535/3859105902.py:30: UserWarning: Creating a tensor from a list of numpy.ndarrays is extremely slow. Please consider converting the list to a single numpy.ndarray with numpy.array() before converting to a tensor. (Triggered internally at /pytorch/torch/csrc/utils/tensor_new.cpp:254.)\n",
      "  'observation.state': torch.tensor([state]).to(device),\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Success\n",
      "DONE INITIALIZATION\n",
      "Success\n",
      "DONE INITIALIZATION\n"
     ]
    }
   ],
   "source": [
    "step = 0\n",
    "PnPEnv.reset(seed=0)\n",
    "policy.reset()\n",
    "policy.eval()\n",
    "save_image = True\n",
    "IMG_TRANSFORM = get_default_transform()\n",
    "while PnPEnv.env.is_viewer_alive():\n",
    "    PnPEnv.step_env()\n",
    "    if PnPEnv.env.loop_every(HZ=20):\n",
    "        # Check if the task is completed\n",
    "        success = PnPEnv.check_success()\n",
    "        if success:\n",
    "            print('Success')\n",
    "            # Reset the environment and action queue\n",
    "            policy.reset()\n",
    "            PnPEnv.reset()\n",
    "            step = 0\n",
    "            save_image = False\n",
    "        # Get the current state of the environment\n",
    "        state = PnPEnv.get_joint_state()[:6]\n",
    "        # Get the current image from the environment\n",
    "        image, wirst_image = PnPEnv.grab_image()\n",
    "        image = Image.fromarray(image)\n",
    "        image = image.resize((256, 256))\n",
    "        image = IMG_TRANSFORM(image)\n",
    "        wrist_image = Image.fromarray(wirst_image)\n",
    "        wrist_image = wrist_image.resize((256, 256))\n",
    "        wrist_image = IMG_TRANSFORM(wrist_image)\n",
    "        data = {\n",
    "            'observation.state': torch.tensor([state]).to(device),\n",
    "            'observation.image': image.unsqueeze(0).to(device),\n",
    "            'observation.wrist_image': wrist_image.unsqueeze(0).to(device),\n",
    "            'task': [PnPEnv.instruction],\n",
    "        }\n",
    "        # Select an action\n",
    "        action = policy.select_action(data)\n",
    "        action = action[0,:7].cpu().detach().numpy()\n",
    "        # Take a step in the environment\n",
    "        _ = PnPEnv.step(action)\n",
    "        PnPEnv.render()\n",
    "        step += 1\n",
    "        success = PnPEnv.check_success()\n",
    "        if success:\n",
    "            print('Success')\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "9b593df4",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "model.safetensors: 100%|██████████| 1.20G/1.20G [02:26<00:00, 8.19MB/s]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "CommitInfo(commit_url='https://huggingface.co/datawhale-eai/smolvla_datawhale_eai/commit/738e2cb9235562d58842ceb8a9469ae21278bb53', commit_message='Add trained policy for PnP task', commit_description='', oid='738e2cb9235562d58842ceb8a9469ae21278bb53', pr_url=None, repo_url=RepoUrl('https://huggingface.co/datawhale-eai/smolvla_datawhale_eai', endpoint='https://huggingface.co', repo_type='model', repo_id='datawhale-eai/smolvla_datawhale_eai'), pr_revision=None, pr_num=None)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# policy.push_to_hub(\n",
    "#     repo_id='datawhale-eai/smolvla_datawhale_eai',\n",
    "#     commit_message='Add trained policy for PnP task',\n",
    "# )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a2b3993-f972-49cf-a7a8-fe3b797fa2c8",
   "metadata": {},
   "source": [
    "**从小步快跑的巨兽（$\\pi_0$），走向精干灵巧的刺客（SmolVLA）。**\n",
    "\n",
    "SmolVLA（\"Smol\" 是网络流行语，意思是“小巧可爱的”）直接继承了 $\\pi_0$ 最核心的“双脑融合 + 流匹配”架构，但把底座全部换成了极度轻量化的组件。\n",
    "\n",
    "我们先用一张图来看看它的内部构造，再来解答“为什么它这么小却这么强”。\n",
    "\n",
    "### 📊 SmolVLA 架构工作流\n",
    "\n",
    "代码段\n",
    "\n",
    "```mermaid\n",
    "graph TD\n",
    "    %% Inputs\n",
    "    subgraph Inputs [输入层]\n",
    "        IMG[视觉观察 Image 16x16 Patch]\n",
    "        TXT[语言指令 Language Prompt]\n",
    "        STATE[本体状态 State 32-dim]\n",
    "        NOISE[噪声动作 Action Noise 32-dim]\n",
    "        TIME[时间步 t]\n",
    "    end\n",
    "\n",
    "    %% Vision-Language Backbone\n",
    "    subgraph Brain [SmolVLM 大脑：轻量级语义理解]\n",
    "        ViT[SmolVLM Vision Transformer 12层, 768维]\n",
    "        PROJ[简单MLP投影器 Connector 768->960维]\n",
    "        LLM_MAIN[Llama 主语言模型 16层, 960维]\n",
    "    end\n",
    "\n",
    "    %% Action Expert\n",
    "    subgraph Cerebellum [Llama Expert 小脑：高效运动控制]\n",
    "        STATE_PROJ[State Proj 32->960]\n",
    "        ACT_PROJ[Action Proj 32->720]\n",
    "        TIME_MLP[Time MLP 1440->720]\n",
    "        EXPERT_LLM[Llama 动作专家 16层, 720维]\n",
    "    end\n",
    "\n",
    "    %% Flow Matching Output\n",
    "    subgraph Outputs [输出层]\n",
    "        OUT_PROJ[Action Out Proj 720->32]\n",
    "        FLOW[VLA Flow Matching]\n",
    "        ACT_CLEAN[平滑连续动作 Continuous Actions]\n",
    "    end\n",
    "\n",
    "    %% Connections\n",
    "    IMG --> ViT --> PROJ --> LLM_MAIN\n",
    "    TXT --> LLM_MAIN\n",
    "\n",
    "    STATE --> STATE_PROJ --> EXPERT_LLM\n",
    "    NOISE --> ACT_PROJ --> EXPERT_LLM\n",
    "    TIME --> TIME_MLP --> EXPERT_LLM\n",
    "    \n",
    "    %% Cross-communication\n",
    "    LLM_MAIN -.->|特征条件化| EXPERT_LLM\n",
    "\n",
    "    EXPERT_LLM --> OUT_PROJ --> FLOW\n",
    "    FLOW -->|迭代去噪| ACT_CLEAN\n",
    "```\n",
    "\n",
    "------\n",
    "\n",
    "### 🆚 核心对比：SmolVLA vs. $\\pi_0$\n",
    "\n",
    "从你提供的网络结构打印信息，我们可以清晰地看到 SmolVLA 对 $\\pi_0$ 进行了全面的“瘦身”：\n",
    "\n",
    "| **模块**           | **π0 (重型装甲)**     | **SmolVLA (轻量级刺客)**     | **瘦身效果与意义**                                           |\n",
    "| ------------------ | --------------------- | ---------------------------- | ------------------------------------------------------------ |\n",
    "| **视觉编码器**     | SigLIP (27层, 1152维) | SmolVLM Vision (12层, 768维) | 计算量锐减。去掉了冗余的深层视觉特征，只保留抓取所需的关键空间信息。 |\n",
    "| **主语言模型**     | Gemma (18层, 2048维)  | Llama架构 (16层, 960维)      | 维度砍半。主脑不再追求“无所不知”的互联网百科，而是专注于“看图说话”的具身指令理解。 |\n",
    "| **动作专家(小脑)** | Gemma (18层, 1024维)  | Llama架构 (16层, 720维)      | 专家网络更紧凑，大大降低了推理延迟（Latency）。              |\n",
    "\n",
    "------\n",
    "\n",
    "### 🚀 为什么 SmolVLA 这么小，效果却这么好？\n",
    "\n",
    "你可能会问：模型变小了，智商不就低了吗？为什么在具身智能里它还能表现出色？这得益于以下几个关键技术与理念：\n",
    "\n",
    "#### 1. 守住了“版本答案”：双脑架构 + Flow Matching\n",
    "\n",
    "模型可以变小，但**范式不能降级**。\n",
    "\n",
    "SmolVLA 完全保留了 $\\pi_0$ 最精髓的 `vlm_with_expert` 设计。这意味着它依然避免了“语义对齐税”（大脑和小脑分开工作），并且依然使用 `VLAFlowMatching` 来生成连续的、极其平滑的动作。只要保留了流匹配（Flow Matching），即使专家网络的特征维度从 1024 降到了 720，它依然能精准地拟合复杂的机器人动作分布。\n",
    "\n",
    "#### 2. Llama 架构的底层优化 (GQA 的魔力)\n",
    "\n",
    "仔细看你提供的 `lm_expert` 代码：\n",
    "\n",
    "Plaintext\n",
    "\n",
    "```\n",
    "(q_proj): Linear(in_features=720, out_features=960, bias=False)\n",
    "(k_proj): Linear(in_features=720, out_features=320, bias=False)\n",
    "```\n",
    "\n",
    "你会发现，Query ($q$) 的维度是 960，而 Key ($k$) 和 Value ($v$) 的维度只有 320！\n",
    "\n",
    "这是典型的 **GQA (Grouped Query Attention, 分组查询注意力)** 机制。相比于传统的注意力机制，GQA 极大地减少了模型在推理时 KV Cache 占用的显存，提升了计算速度。对于需要高频输出动作指令（比如 50Hz）的机器人来说，**推理速度比绝对的参数量更重要**。\n",
    "\n",
    "#### 3. “数据质量”战胜了“模型体积”\n",
    "\n",
    "在 AI 界有一个共识（比如微软的 Phi 系列小模型验证的）：**Small models + High quality data = Big performance**。\n",
    "\n",
    "具身智能领域目前最大的瓶颈是“高质量的机器人操作数据不足”，而不是“模型参数量不够”。SmolVLA 证明了，只要给它喂入清晰、干净的遥操作（Teleoperation）数据，一个小巧的 Llama 网络足以学会“如何完美地煎一个鸡蛋”或“折叠一件衣服”。巨大的模型（如千亿参数的 LLM）在干这些“肌肉活”时，大部分算力其实是处于闲置或浪费状态的。\n",
    "\n",
    "#### 4. 模态连接器的极简主义\n",
    "\n",
    "代码中 `SmolVLMConnector` 是一个极其简单的 `Linear(12288 -> 960)`。它没有使用复杂的重采样器（Resampler）或 Q-Former。这种“直筒子”设计让视觉特征无损、快速地拍脸传给语言模型，非常适合需要快速反应的控制任务。\n",
    "\n",
    "------\n",
    "\n",
    "### 💡 总结\n",
    "\n",
    "如果说 $\\pi_0$ 是一辆装备了顶级雷达和超算中心的重型坦克，用来探索具身智能的**能力天花板**；\n",
    "\n",
    "那么 **SmolVLA** 就是一辆经过极其专业改装的拉力赛车。它卸掉了不必要的重量（超大维度的 LLM 和深层 ViT），换上了最高效的引擎（Llama GQA），并保留了最顶级的底盘调校（Flow Matching 和 Expert 架构）。\n",
    "\n",
    "它在具身智能界引起轰动的原因很简单：**它让普通实验室甚至个人开发者，用一两张消费级显卡（比如 RTX 4090），就能跑得起甚至训练得起最前沿的机器人策略模型！**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d59f5277-e822-4c3b-ab2f-24f9981cee5c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
