# FLUX 3 Action

FLUX 3 Action predice las acciones del robot a partir de observaciones de la cámara, el estado y una instrucción de la tarea. Un Video VAE congelado y un codificador de texto alimentan a un diffusion transformer que predice latentes de video y bloques de acciones; en la inferencia solo se devuelven las acciones. LeRobot admite inferencia y PEFT: LoRA adapta el tronco, mientras que las cabezas de acción y condicionamiento del robot se entrenan por completo.

Incluimos `flux-3-action-base` como modelo de acción base, junto con ajustes finos para los robots SO-101 `flux-3-action-so101` y Franka Panda `flux-3-action-droid` (ajustado en el conjunto de datos DROID). El ejemplo central aquí es una adaptación de tarea mediante un LoRA basado en el modelo `flux-3-action-so101`.

Para entrenar una nueva encarnación de robot a partir del modelo base o realizar un ajuste completo, utilice nuestro repositorio independiente [flux-action](https://github.com/black-forest-labs/flux-action).

## Instalación

El Video VAE requiere **NATTEN** 0.21.6 o una versión más reciente, como una rueda compilada para tus versiones exactas de torch y CUDA, desde https://whl.natten.org. NATTEN publica ruedas para torch 2.10 a 2.13, pero aún no para el torch 2.15 que LeRobot instala por defecto, por lo que primero debe instalar un torch compatible. Por ejemplo, desde el checkout de LeRobot, torch 2.13 con CUDA 13.0 junto con las dependencias de entrenamiento, policy, PEFT y EMA. Como en la [guía de instalación](./installation#pytorch-cuda-variant-linux-only), TorchCodec proviene del índice de CPU:

```bash
pip install --index-url https://download.pytorch.org/whl/cu130 \
    'torch==2.13.0+cu130' 'torchvision==0.28.0+cu130' 'numpy>=2.0,<2.3'
pip install --index-url https://download.pytorch.org/whl/cpu 'torchcodec==0.13.0+cpu'
pip install -e ".[training,flux3,peft,diffusion]" \
    'torch==2.13.0+cu130' 'torchvision==0.28.0+cu130' 'torchcodec==0.13.0+cpu'
pip install 'natten==0.21.7+torch2130cu130' --find-links https://whl.natten.org
```

Para un controlador de NVIDIA anterior a 580.65, use la compilación de CUDA 12.6 en su lugar: el índice `cu126`, las etiquetas `+cu126` de torch y torchvision, y `natten==0.21.7+torch2130cu126`. Para otra versión de torch, use la rueda de NATTEN cuya etiqueta coincida con ella, como `natten==0.21.6+torch2110cu130` para torch 2.11 con CUDA 13.0.

## Adaptación de tareas para SO-101

Use un conjunto de datos de LeRobot v3 a **30 Hz**, con seis canales de acciones comandadas absolutas y seis canales de estado medido en el mismo orden de articulaciones y unidades. El agarre es el último. Proporcione valores crudos, una calibración de robot coherente e instrucciones en `task`.

### Cámaras

Los nombres, la cantidad y la disposición de las cámaras son configurables. El paquete SO-101 nombra a sus dos cámaras según lo que muestran:

| Cámara | Clave                        |
| ------ | -------------------------- |
| Escena  | `observation.images.scene` |
| Muñeca  | `observation.images.wrist` |

![SO-101 scene camera (left) and wrist camera (right), showing the blue box and container](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/lerobot/so101_camera_tiling.png)

Puede usar `--rename_map` para mapear los nombres de las cámaras a las claves esperadas, por ejemplo:

```bash
--rename_map='{"observation.images.top":"observation.images.scene","observation.images.gripper_cam":"observation.images.wrist"}'
```

Use el mismo mapeo para el rollout; las claves coincidentes no necesitan un mapa. Consulte [mapas de renombrado](https://huggingface.co/docs/lerobot/main/en/rename_map).

### Cargar y entrenar

Cargue la política SO-101 desde [`black-forest-labs/flux-3-action-so101`](https://huggingface.co/black-forest-labs/flux-3-action-so101). La configuración guardada carga automáticamente el VAE y el codificador de texto compartidos desde una revisión fijada de `black-forest-labs/flux-3-action-base`. Si el acceso está restringido, autentíquese con `hf auth login` utilizando una cuenta con acceso. Ejecute desde el checkout de LeRobot:

```bash
lerobot-train \
  --config_path=examples/flux3/lora.json \
  --policy.path=black-forest-labs/flux-3-action-so101 --policy.device=cuda \
  --dataset.repo_id=YOUR_ORG/YOUR_SO101_DATASET \
  --output_dir=outputs/so101_lora
```

La caché de Hub conserva el modelo descargado y los codificadores compartidos para la reanudación y la inferencia de adaptadores.

El punto de control fijado de SO-101-finetuned utiliza las claves de cámara `scene` / `wrist`, ocho pasos temporales de observación, dos instantáneas visuales codificadas de forma independiente y condicionamiento por acciones/estado pasados. Predice 42 acciones, ejecuta las primeras 32 a 30 Hz y luego vuelve a planificar. Sus procesadores guardados incluyen las estadísticas de normalización coincidentes de la base. Estas configuraciones del punto de control se conservan durante la adaptación de la tarea. El archivo compartido `examples/flux3/lora.json` solo proporciona las configuraciones de entrenamiento/ejecución y el presupuesto de entrenamiento; el mismo archivo se incluye como `lora.json` en cada paquete de Hub. La disposición de las cámaras, el condicionamiento, la representación de acciones y las configuraciones de pérdida provienen del punto de control. Estos comandos conservan la longitud de ejecución guardada de 32, la guía 3/3 y la ejecución eager. Para la guía 4/1 y la compilación, añade `--policy.guidance_scale=4 --policy.guidance_scale_action=1 --policy.compile_model=true`.

> **Experimentos de condicionamiento:** LeRobot expone `n_obs_steps`, `history_snapshots` y `condition_on_past_actions`. Cambiarlos requiere configuraciones compatibles de modelo/procesador y ajuste fino; mantenga los valores guardados en el punto de control para la adaptación ordinaria de tareas.

El preset habilita LoRA con rank/alpha 32 y EMA con decaimiento 0.999; nada se sube automáticamente. Habilite nuevos adaptadores a través de la configuración de `peft` de nivel superior, no con `--policy.use_peft=true`, que identifica un adaptador guardado.

En nuestros experimentos, EMA proporcionó beneficios sustanciales en DROID, mientras que los resultados en SO-101 han sido mixtos hasta ahora. Su beneficio depende de los datos y la configuración de entrenamiento. Recomendamos mantener EMA habilitado y evaluar tanto los checkpoints crudos como los de EMA bajo el mismo protocolo de rollout antes de elegir cuál desplegar. La pérdida de validación offline periódica utiliza pesos crudos; no compara automáticamente ambas variantes.

Comience con el presupuesto de una sola GPU para iterar rápidamente. Para un presupuesto de entrenamiento mayor, use la misma configuración con estas sobrescrituras:

```bash
accelerate launch --num_processes=4 --multi_gpu -m lerobot.scripts.lerobot_train \
  --config_path=examples/flux3/lora.json \
  --policy.path=black-forest-labs/flux-3-action-so101 --policy.device=cuda \
  --dataset.repo_id=YOUR_ORG/YOUR_SO101_DATASET \
  --batch_size=8 --steps=14000 \
  --output_dir=outputs/so101_lora_large
```

| Presupuesto                   | GPUs | Lote por GPU | Acumulación | Lote efectivo | Micropasos (`steps`) | Actualizaciones del optimizador |
| ------------------------ | ---- | ------------- | ------------ | --------------- | -------------------- | ----------------- |
| Iteración rápida (predeterminado) | 1    | 2             | 4            | 8               | 10,000               | 2,500             |
| Presupuesto mayor            | 4    | 8             | 4            | 128             | 14,000               | 3,500             |

El lote efectivo es GPUs × lote por GPU × acumulación. LeRobot cuenta `steps`, `save_freq` y `eval_steps` en micropasos; divida entre la acumulación para las actualizaciones del optimizador. La configuración preestablecida guarda y evalúa cada 500 micropasos (125 actualizaciones). Mantenga los tres ajustes divisibles entre la acumulación al modificarla. Las longitudes de congelación, calentamiento, decaimiento y enfriamiento del programador también usan micropasos. Multiplique el número deseado de actualizaciones del optimizador por el factor de acumulación al establecer estas longitudes de fase. Ambos presupuestos usan los mismos ajustes de LoRA, optimizador y EMA, y preservan la condicionamiento, las dimensiones de acción y la normalización de la base cargada. Los puntos de control incluyen tanto los adaptadores crudos como los de EMA. Elija el presupuesto y el punto de control usando evaluación con datos retenidos y ejecuciones; un lote más grande no garantiza mejores resultados.

El preset reserva el 20% final de episodios por tarea para la evaluación. Ajusta el tamaño del lote y la acumulación para tu hardware; consulta [entrenamiento multi-GPU](https://huggingface.co/docs/lerobot/main/en/multi_gpu_training) y [entrenamiento PEFT](https://huggingface.co/docs/lerobot/main/en/peft_training).

## Adaptación de tareas de DROID

**Experimental:** `examples/flux3/lora.json` reutiliza la configuración del optimizador PEFT de SO-101, LoRA, dropout, EMA y presupuesto de entrenamiento. La carga de la configuración se ha verificado, pero el entrenamiento PEFT de DROID de extremo a extremo y el rendimiento de la tarea aún no se han validado.

Cargue la [política DROID](https://huggingface.co/black-forest-labs/flux-3-action-droid) directamente por ID de repositorio; sus codificadores compartidos se resuelven automáticamente:

```bash
lerobot-train \
  --config_path=examples/flux3/lora.json \
  --policy.path=black-forest-labs/flux-3-action-droid \
  --dataset.repo_id=YOUR_ORG/YOUR_DROID_TASK_DATASET \
  --output_dir=outputs/droid_lora
```

Esto utiliza un lote efectivo de 8 y 2.500 actualizaciones del optimizador, con EMA habilitado y puntos de control raw/EMA guardados cada 125 actualizaciones. Las subidas automáticas al Hub están deshabilitadas. Para el presupuesto mayor, inicie con cuatro GPUs como en el ejemplo SO-101 y agregue `--batch_size=8 --steps=14000`.

El preset carga la disposición de cámaras, el condicionamiento, la representación de acciones, la tasa de control y los procesadores del checkpoint de DROID, reemplazando únicamente los ajustes de entrenamiento/ejecución enumerados. Tu conjunto de datos debe cumplir con el contrato del checkpoint: el paquete actual utiliza tres cámaras, ocho canales de estado/acción y comandos de posición absoluta de articulaciones a 15 Hz. Mapea los nombres de las cámaras con `--rename_map` si es necesario. Ambos robots utilizan el mismo ejemplo de entrenamiento; no se necesita ninguna receta específica del robot para la carga o la inferencia.

## Valores predeterminados y normalización

Las nuevas configuraciones usan estos valores predeterminados de PEFT. Al cargar `--policy.path` se usan los ajustes guardados en el checkpoint; las configuraciones o CLI explícitas tienen prioridad. Los checkpoints de DROID conservan su propia configuración.

| Configuración                                     | Predeterminado                                                        |
| ------------------------------------------- | -------------------------------------------------------------- |
| Condicionamiento                                | Imágenes actuales y estado medido; 1 instantánea, sin acciones anteriores |
| Acciones                                     | Deltas de comandos; 32 predichos y 32 ejecutados a 30 Hz          |
| Cámaras                                     | Dos vistas lado a lado en un lienzo de 256 × 512                   |
| Tasa de aprendizaje del adaptador / cabeza                | `1e-4` / `5e-4`                                                |
| Decaimiento de pesos / recorte de gradientes            | `0` / `1`                                                      |
| Congelar / calentamiento                             | Ninguno                                                           |
| Checkpointing de gradientes / aumento de imágenes | Activado / desactivado                                                       |

Las nuevas configuraciones usan `n_obs_steps=1`, `history_snapshots=1` y `condition_on_past_actions=false`. Al cargar un punto de control, se conservan sus valores explícitos: el paquete SO-101 fijado usa ocho pasos de tiempo de historial, dos instantáneas visuales y condicionamiento sobre acciones/estado pasados. `conditioning="history"` selecciona la codificación independiente de instantáneas; por sí solo no determina el número de pasos de tiempo. El entrenamiento también lee fotogramas y comandos futuros como objetivos, además del comando precedente para calcular las diferencias de acción.

Los nombres/orden de las cámaras, las dimensiones de estado/acción y los canales de acción absoluta siguen siendo específicos del robot. El checkpoint de SO-101 mantiene el último canal absoluto (`delta_absolute_dims=[-1]`) y utiliza pesos de canal `[1, 1, 1, 1, 1, 2]`. Los valores predeterminados de la clase no usan excepciones de canal absoluto y utilizan pesos iguales.

Los procesadores guardados de la base poseen estadísticas de normalización. Alimente estados/acciones crudos y mantenga las mismas estadísticas para el entrenamiento, la reanudación y la inferencia. Los cuantiles del paquete SO-101 asumen su orden de articulaciones, unidades y calibración; no son valores de calibración universales para SO-101. Para usar estadísticas diferentes, prepare una base separada con procesadores coincidentes antes del entrenamiento. Las estadísticas de conjuntos de datos de acciones absolutas no pueden sustituir a las estadísticas de delta de comandos.

El entrenamiento guarda los adaptadores y las cabezas entrenadas con una referencia a la base completa. Mantén esa base y sus archivos de codificador congelado accesibles al recargar; los adaptadores no se fusionan automáticamente en ella.

## Resumen

```bash
lerobot-train \
  --config_path=outputs/so101_lora/checkpoints/last/pretrained_model/train_config.json \
  --resume=true
```

Reanuda desde el punto de control `pretrained_model` sin procesar, que restaura el estado del optimizador y de EMA. Para la inferencia, puedes seleccionar su pariente `pretrained_model_ema` cuando EMA está habilitado. Mantén la base y los procesadores originales de cada adaptador; una base descargada recientemente no es un reemplazo para una utilizada por un adaptador anterior.

## Inferencia

Apunta el parámetro `--policy.path` del ejecutor de LeRobot al punto de control del adaptador entrenado; este carga la base referenciada y los procesadores guardados. Para llamadas directas con una **base completa**, carga los procesadores junto con ella:

```python
from lerobot.policies.factory import make_pre_post_processors
from lerobot.policies.flux3 import Flux3Policy

checkpoint = "black-forest-labs/flux-3-action-so101"
policy = Flux3Policy.from_pretrained(checkpoint).eval()
preprocessor, postprocessor = make_pre_post_processors(policy.config, pretrained_path=checkpoint)

# Run on every control tick, including while actions are queued:
prepared = preprocessor(observation)
normalized_action = policy.select_action(prepared)
absolute_command = postprocessor(normalized_action)
```

El preprocesador almacena en búfer el historial de observaciones/comandos. El postprocesador deshace la normalización, integra los deltas y actualiza el historial de comandos compartido en cada tick. El primer comando se ancla al estado medido; los comandos posteriores se integran a partir del comando anterior. Las salidas directas de la política se normalizan y deben postprocesarse. Reinicia la política y ambos procesadores en los límites de episodio o tras una intervención; el ejecutor síncrono de LeRobot lo hace. No se admite la inferencia RTC/asíncrona.

Para la política de un solo paso de tiempo predeterminada, las imágenes actuales y el estado medido son suficientes. Para la predicción sin conexión con una ancla de delta explícita, proporcione `observation.command_history` con un comando anterior; esto ancla la integración de la salida sin añadir un comando a la condicionamiento del modelo. Los puntos de control configurados explícitamente para múltiples pasos de tiempo de observación requieren `policy.config.n_obs_steps` imágenes/estados e historial de comandos. Pase las entradas a través del preprocesador, llame a `predict_action_chunk` y luego realice el posprocesamiento. `--policy.compile_model=true` habilita la compilación perezosa de los codificadores congelados y el DiT de inferencia; no compila el DiT de entrenamiento.

Para reducir la VRAM de inferencia, mueva Qwen a la CPU después de cargarlo y de la llamada final `policy.to(...)`:

```python
policy.frozen.text_encoder.cpu()
```

Esto mueve aproximadamente 8.3 GiB de pesos a la RAM del host; las instrucciones no cacheadas se codifican más lentamente, mientras que los embeddings aún se transfieren al dispositivo de la política y se cachean. No reduce la memoria pico durante la carga, y un `policy.to(...)` posterior mueve Qwen de vuelta con la política.

## Entrenamiento de otras encarnaciones

Para las implementaciones en las que aún no ofrecemos un punto de control afinado, comience desde el modelo base en [flux-action](https://github.com/black-forest-labs/flux-action). Ese flujo de trabajo requiere definir las cabezas de acción y de condicionamiento del robot, la disposición de las cámaras, la representación de la acción y su normalización. Que las dimensiones sean iguales por sí solo no hace que las cabezas de otro robot sean reutilizables.

Para la inferencia o la adaptación de tareas posteriores con LeRobot, empaquete el modelo entrenado como una política completa de LeRobot, junto con su configuración y los procesadores correspondientes. Un archivo de pesos en bruto por sí solo no constituye un paquete `--policy.path` cargable. Esta guía se centra en adaptar las políticas existentes de SO-101 y DROID a nuevas tareas.

Todas las políticas construyen únicamente los flujos de contenido `video` y `video_cond`, además de los flujos de acción del robot. Los pesos de imagen/áudio no utilizados se filtran antes de la carga, lo que ahorra aproximadamente el 28% de los parámetros de DiT sin alterar las predicciones de acción. Las listas de flujos guardadas no habilitan las ramas de imagen/áudio; al cargar y guardar una base completa se registra el diseño reducido. Los adaptadores que apuntan a flujos eliminados requieren su base original y una revisión de código anterior.

Las políticas completas se cargan de forma estricta por defecto. Después de filtrar los flujos conocidos no utilizados, los pesos faltantes, inesperados o con forma incorrecta generan un error. El parámetro explícito `strict=False` permite únicamente inicializar cabezas de encarnamiento faltantes o redimensionar cabezas con forma no coincidente; los pesos del tronco siguen siendo obligatorios y se verifica su forma.

## Validación

Las pruebas de CPU cubren el empaquetado, los procesadores, las actualizaciones de PEFT y el checkpoint/reanudación. Las comprobaciones previas con pesos reales en H200 precedieron a la refactorización actual del procesador. Esta revisión exacta aún requiere validación en GPU y en el robot; las comprobaciones existentes no establecen la capacidad de cuatro GPUs ni la calidad de PEFT en una nueva encarnación.

