LeRobot documentation

Columnas de idioma y recetas

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Columnas de idioma y recetas

La mayoría de los conjuntos de datos de LeRobot incluyen una única cadena task por episodio, lo cual es suficiente para habilidades cortas con una sola instrucción, pero no es suficiente para las políticas de robots de horizonte más largo y multimodales hacia las que se dirige el campo (planificación de alto nivel, memoria, interrupciones, VQA, uso de herramientas). Para admitir esas políticas sin bifurcar el formato del conjunto de datos, LeRobot extiende LeRobotDataset con dos columnas de lenguaje opcionales y una pequeña capa de receta que convierte esas filas en muestras de entrenamiento estilo chat al vuelo.

El diseño se divide claramente en tres capas:

  1. Datos en el conjunto de datos — anotaciones de idioma almacenadas junto a los fotogramas en data/chunk-*/file-*.parquet como dos columnas opcionales (language_persistent y language_events). Los conjuntos de datos sin estas columnas mantienen su comportamiento existente.
  2. Receta — un archivo YAML que declara qué filas de anotación vincular y cómo distribuirlas como turnos de chat (role, content, imágenes opcionales, llamadas a herramientas opcionales). Las recetas son configuración pura; no se requiere Python para añadir una nueva.
  3. Formato de entrenamiento — en el momento de la muestra, RenderTrainingMessagesStep resuelve la receta frente a las anotaciones por cuadro y emite messages en estilo HF junto con archivos secundarios específicos de LeRobot (message_streams, target_message_indices) que los procesadores de política consumen.

Esta página describe cada capa por separado.

Capa 1 — columnas de idioma en el conjunto de datos

Las dos columnas opcionales se encuentran junto a los datos de fotogramas en data/chunk-*/file-*.parquet:

  • language_persistent: una lista de filas que se difunde en cada fotograma de un episodio para el estado que permanece activo, como subtask, plan y memory.
  • language_events: una lista de filas solo en el fotograma exacto en el que se emitió un evento, como interjection, vqa y llamadas a herramientas de voz.

Ambas columnas comparten la misma forma de fila (las filas de eventos omiten timestamp porque el cuadro en el que se encuentra la fila ya lo proporciona):

role: string
content: string | null
style: string | null
timestamp: float32        # persistent rows only
camera: string | null     # observation.images.* feature key, view-dependent rows only
tool_calls: list[Json] | null

El campo camera marca las filas cuyo content se basa en una vista de cámara específica. Las filas de estilos dependientes de la vista (vqa y trace) DEBEN establecer camera con la clave de característica correspondiente de observation.images.*. Las filas de cualquier otro estilo, incluido motion, que describe primitivas del marco del robot en términos articulares / cartesianos, DEBEN dejar camera como null. Los escritores de la pipeline y el validador aplican esto mediante validate_camera_field(style, camera).

meta/tasks.parquet sigue siendo la fuente canónica de la tarea. La especial receta de enlace ${task} siempre lee esa cadena de tarea y no depende de las anotaciones de idioma.

Arquitectura

El propio stack de lenguaje tiene tres módulos internos que respaldan la capa 1:

  1. lerobot.datasets.language define el esquema, el registro de estilos y column_for_style.
  2. lerobot.datasets.language_render resuelve filas y renderiza mensajes.
  3. RenderTrainingMessagesStep convierte las muestras del conjunto de datos en messages, message_streams y target_message_indices.

LeRobotDataset es agnóstico a las recetas. Transmite language_persistent y language_events cuando están presentes, y los conjuntos de datos sin anotaciones mantienen su comportamiento existente.

Capa 2 — anatomía de la receta

Las recetas son archivos YAML respaldados por TrainingRecipe y MessageTurn de lerobot.datasets.recipe. Declaran qué filas de anotación extraer (mediante bindings) y cómo componerlas en turnos de chat (messages).

messages:
  - { role: user, content: "${task}", stream: high_level }
  - { role: assistant, content: "${subtask}", stream: low_level, target: true }

Una receta también puede ramificarse en una mezcla ponderada de subrecetas. En el momento de la muestreo, se selecciona exactamente una rama de forma determinista a partir del índice de la muestra, de modo que distintos fotogramas entrenan distintos objetivos (p. ej., actualizaciones de memoria frente a ejecución de bajo nivel frente a VQA) sin ningún cableado en Python.

Semántica temporal

Los estilos persistentes están activos después de la emisión hasta que se reemplazan:

  • active_at(t, style=subtask)
  • nth_prev(style=memory, offset=1)
  • nth_next(style=subtask, offset=1)

Los estilos de eventos solo existen en su marca de tiempo exacta:

  • emitted_at(t, style=interjection)
  • emitted_at(t, style=vqa, role=user, camera=observation.images.top)
  • emitted_at(t, role=assistant, tool_name=say)

La coincidencia exacta de eventos no tiene una ventana de tolerancia, por lo que los escritores deben sellar las filas de eventos con las marcas de tiempo de los fotogramas de los datos de parquet.

Resolución dependiente de la vista

Para los estilos dependientes de la vista (vqa y trace), el resolver incorpora un filtro camera= paralelo a role= y tool_name=. Los conjuntos de datos con múltiples cámaras suelen emitir un par (vqa, user) + (vqa, assistant) por cámara en el mismo sello de tiempo; sin camera=, esos resolvers detectan dos coincidencias y lanzan un error de ambigüedad. Las recetas consumen cada cámara a través de su propia vinculación junto con un bloque de imagen correspondiente, por ejemplo:

ask_vqa_top:
  route: vqa
  bindings:
    vqa_query: "emitted_at(t, style=vqa, role=user, camera=observation.images.top)"
    vqa: "emitted_at(t, style=vqa, role=assistant, camera=observation.images.top)"
  messages:
    - role: user
      stream: high_level
      if_present: vqa_query
      content:
        - { type: image, feature: observation.images.top }
        - { type: text, text: "${vqa_query}" }
    - {
        role: assistant,
        content: "${vqa}",
        stream: high_level,
        target: true,
        if_present: vqa,
      }

Añada una subreceta de este tipo por cada cámara que registre el conjunto de datos. El marcador explícito route: vqa hace que una anotación VQA dispersa coincidente tenga prioridad sobre la selección de mezcla ponderada normal; los nombres de los componentes son puramente descriptivos.

Capa 3 — formato de entrenamiento

Las muestras renderizadas utilizan mensajes de chat en el estilo de HF junto con sidecars de LeRobot:

sample["messages"]
sample["message_streams"]
sample["target_message_indices"]

El renderer no aplica una plantilla de chat del tokenizer. Los procesadores de política deciden cómo serializar los mensajes para su backbone, lo que mantiene el mismo dataset utilizable en SmolVLA, Pi0.5 y cualquier VLM futuro que espere mensajes de chat en estilo OpenAI.

Mezclas

Las recetas de mezcla seleccionan de forma determinista una subreceta ponderada a partir del índice de la muestra. recipes/subtask_mem.yaml entrena la mezcla compacta del núcleo: predicción de subtareas de alto nivel, ejecución de bajo nivel y memoria. recipes/subtask_mem_vqa_speech.yaml es la variante más completa, que además añade respuestas de VQA y de interrupciones habladas.

recipes/subtask_joint.yaml demuestra el entrenamiento conjunto de secuencias en lugar de una mezcla ponderada. Para la misma muestra, su subtarea de asistente se supervisa con entropía cruzada de texto en el flujo low_level mientras la predicción de acciones permanece activa, coincidiendo con la configuración conjunta del paper de π0.5. Por ahora es solo para entrenamiento: el runtime aún no reconstruye este prefijo conjunto en la inferencia.

Ausencia elegante

Si ambas columnas de idioma faltan, son None o están vacías, RenderTrainingMessagesStep utiliza la cadena de tarea como supervisión de bajo nivel cuando está disponible y, en caso contrario, deja la muestra sin cambios. Para una muestra anotada, si ninguna rama de receta se aplica y no existe una tarea de respaldo, la renderización devuelve None, lo que permite que un loader reintente con otra muestra.

Update on GitHub