LeRobot documentation

Столбцы и рецепты языков

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.7.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Столбцы и рецепты языков

Большинство датасетов LeRobot поставляются с одной строкой task на эпизод — этого достаточно для коротких навыков с одной инструкцией, но этого мало для долгосрочных мультимодальных политик роботов, к которым движется область (высокоуровневое планирование, память, вставки, VQA, использование инструментов). Чтобы поддерживать такие политики без разветвления формата датасета, LeRobot расширяет LeRobotDataset двумя необязательными языковыми столбцами и небольшим слоем рецептов, который на лету превращает эти строки в обучающие примеры в формате чата.

Дизайн чётко разделяется на три уровня:

  1. Данные в наборе данных — языковые аннотации, хранящиеся рядом с кадрами в data/chunk-*/file-*.parquet в виде двух необязательных столбцов (language_persistent и language_events). Наборы данных без этих столбцов сохраняют свое существующее поведение.
  2. Рецепт — это YAML-файл, в котором описывается, какие строки аннотаций привязать и как разложить их в виде реплик чата (role, content, необязательные изображения, необязательные вызовы инструментов). Рецепты — это чистая конфигурация; для добавления нового не требуется писать код на Python.
  3. Формат обучения — на этапе выборки RenderTrainingMessagesStep сопоставляет рецепт с аннотациями для каждого кадра и формирует messages в стиле HF, а также специфичные для LeRobot вспомогательные поля (message_streams, target_message_indices), которые используются процессорами политики.

На этой странице последовательно описывается каждый слой.

Слой 1 — языковые столбцы в наборе данных

Два необязательных столбца находятся рядом с данными кадров в data/chunk-*/file-*.parquet:

  • language_persistent: список строк, транслируемых во все кадры эпизода для состояния, которое остаётся активным, например subtask, plan и memory.
  • language_events: список строк только в том кадре, где было сгенерировано событие, например interjection, vqa и вызовы инструментов речи.

Обе колонки имеют одинаковую форму строк (строки событий пропускают timestamp, так как кадр, на котором находится строка, уже предоставляет его):

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

Поле camera помечает строки, чьё content привязано к конкретному виду камеры. Строки стилей, зависящих от вида (vqa и trace), ОБЯЗАНЫ устанавливать camera в соответствующий ключ фичи observation.images.*. Строки всех остальных стилей — включая motion, который описывает примитивы в системе координат робота в терминах суставов / декартовых координат, — ОБЯЗАНЫ оставлять camera равным null. Пайплайны записи и валидатор обеспечивают соблюдение этого правила с помощью validate_camera_field(style, camera).

meta/tasks.parquet остаётся каноническим источником для задачи. Специальная привязка рецепта ${task} всегда читает строку этой задачи и не зависит от языковых аннотаций.

Архитектура

Сам стек языка имеет три внутренних модуля, обеспечивающих работу первого уровня:

  1. lerobot.datasets.language определяет схему, реестр стилей и column_for_style.
  2. lerobot.datasets.language_render разрешает строки и рендерит сообщения.
  3. RenderTrainingMessagesStep преобразует примеры из набора данных в messages, message_streams и target_message_indices.

LeRobotDataset не зависит от рецепта. Если language_persistent и language_events присутствуют, он передаёт их дальше, а для наборов данных без аннотаций сохраняется существующее поведение.

Слой 2 — анатомия рецепта

Рецепты — это файлы YAML, основанные на TrainingRecipe и MessageTurn из lerobot.datasets.recipe. Они объявляют, какие строки аннотаций извлекать (через bindings) и как собирать их в ходы чата (messages).

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

Рецепт также может разветвляться на взвешенный бленд под-рецептов. Во время выборки ровно одна ветвь детерминированно выбирается на основе индекса выборки, поэтому разные кадры обучают разные цели (например, обновления памяти, низкоуровневое выполнение или VQA) без какой-либо настройки на Python.

Временная семантика

Стили с постоянным действием остаются активными после их применения, пока не будут заменены:

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

Стили событий существуют только в их точном временном значении:

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

Точное сопоставление событий не предусматривает допустимого временного окна, поэтому авторы должны проставлять в строках событий метки времени кадров из данных parquet.

Разрешение, зависящее от точки обзора

Для стилей, зависящих от камеры (vqa и trace), у резолвера появляется фильтр camera=, параллельный role= и tool_name=. Датасеты с несколькими камерами обычно выдают по одной паре (vqa, user) + (vqa, assistant) на каждую камеру с одинаковым временным меткой; без camera= эти резолверы видят два совпадения и выбрасывают ошибку неоднозначности. Рецепты используют каждую камеру через собственное связывание и соответствующий блок изображения, например

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,
      }

Добавьте по одному такому под-рецепту для каждой камеры, которую фиксирует набор данных. Явный маркер route: vqa обеспечивает приоритет соответствующей разреженной VQA-аннотации над обычным выбором взвешенного смешения; имена компонентов носят исключительно описательный характер.

Слой 3 — формат обучения

Отображаемые примеры используют сообщения чата в стиле HF и вспомогательные данные LeRobot:

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

Рендерер не применяет шаблон чата токенизатора. Процессоры политики определяют, как сериализовать сообщения для их базовой модели, что позволяет использовать один и тот же датасет в SmolVLA, Pi0.5 и любых будущих VLM, ожидающих сообщения в формате OpenAI.

Смеси

Blend-рецепты детерминированно выбирают один взвешенный под-рецепт по индексу образца. recipes/subtask_mem.yaml обучает компактный основной blend — предсказание подзадач высокого уровня, выполнение низкого уровня и память. recipes/subtask_mem_vqa_speech.yaml — более полный вариант, который также добавляет ответы на VQA и устные вставки.

recipes/subtask_joint.yaml демонстрирует совместное обучение последовательности, а не взвешенное смешивание. Для одного и того же примера его подзадача ассистента контролируется с помощью текстовой кросс-энтропии на потоке low_level, при этом предсказание действий остаётся активным, что соответствует совместной конфигурации из статьи π0.5. На данный момент это режим только для обучения: рантайм пока не перестраивает этот совместный префикс при инференсе.

Отсутствие без сбоев

Если обе языковые колонки отсутствуют, равны None или пусты, RenderTrainingMessagesStep использует строку задачи как низкоуровневое управление, если она доступна, а в противном случае оставляет образец без изменений. Для размеченного образца, если ни одна ветка рецепта не применяется и нет запасного варианта задачи, рендеринг возвращает None, что позволяет загрузчику повторить попытку с другим образцом.

Update on GitHub