LeRobot documentation
Colunas de idioma e receitas
Colunas de idioma e receitas
A maioria dos conjuntos de dados do LeRobot é distribuída com uma única string task por episódio — adequado para habilidades curtas e de instrução única, mas insuficiente para as políticas de robôs de horizonte mais longo e multimodais para as quais o campo está se direcionando (planejamento de alto nível, memória, interjeições, VQA, uso de ferramentas). Para suportar essas políticas sem bifurcar o formato do conjunto de dados, o LeRobot estende o LeRobotDataset com duas colunas de linguagem opcionais e uma pequena camada de receita que transforma essas linhas em amostras de treinamento em estilo chat em tempo real.
O design se divide claramente em três camadas:
- Dados no dataset — anotações de idioma armazenadas junto aos frames em
data/chunk-*/file-*.parquetcomo duas colunas opcionais (language_persistentelanguage_events). Datasets sem essas colunas mantêm seu comportamento existente. - Receita — um arquivo YAML que declara quais linhas de anotação vincular e como organizá-las como turnos de chat (
role,content, imagens opcionais, chamadas de ferramentas opcionais). As receitas são configuração pura; não é necessário Python para adicionar uma nova. - Formato de treinamento — no momento da amostragem,
RenderTrainingMessagesStepresolve a receita em relação às anotações por quadro e emitemessagesno estilo HF, além de sidecars específicos do LeRobot (message_streams,target_message_indices) que os processadores de política consomem.
Esta página descreve cada camada em sequência.
Camada 1 — colunas de idioma no conjunto de dados
As duas colunas opcionais ficam ao lado dos dados de quadro em data/chunk-*/file-*.parquet:
language_persistent: uma lista de linhas transmitidas para todos os quadros de um episódio para o estado que permanece ativo, comosubtask,planememory.language_events: uma lista de linhas apenas no quadro exato em que um evento foi emitido, comointerjection,vqae chamadas de ferramentas de fala.
Ambas as colunas compartilham a mesma forma de linha (as linhas de evento omitem timestamp porque o quadro em que a linha está já fornece esse valor):
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
O campo camera marca linhas cujo content é fundamentado em uma visão específica de câmera. Linhas de estilos dependentes de visão (vqa e trace) DEVEM definir camera como a chave de recurso correspondente em observation.images.*. Linhas de todos os outros estilos — incluindo motion, que descreve primitivos no referencial do robô em termos articulares / cartesianos — DEVEM deixar camera como null. Os escritores do pipeline e o validador aplicam isso por meio de validate_camera_field(style, camera).
meta/tasks.parquet continua sendo a fonte canônica para a tarefa. O binding especial de receita ${task} sempre lê essa string de tarefa e não depende de anotações de idioma.
Arquitetura
A própria pilha de linguagem possui três módulos internos que sustentam a camada 1:
lerobot.datasets.languagedefine o esquema, o registro de estilos ecolumn_for_style.lerobot.datasets.language_renderresolve linhas e renderiza mensagens.RenderTrainingMessagesStepconverte amostras do conjunto de dados emmessages,message_streamsetarget_message_indices.
LeRobotDataset permanece agnóstico em relação à receita. Ele repassa language_persistent e language_events quando presentes, e conjuntos de dados sem anotações mantêm seu comportamento existente.
Camada 2 — anatomia da receita
As receitas são arquivos YAML baseados em TrainingRecipe e MessageTurn de lerobot.datasets.recipe. Elas
declaram quais linhas de anotação devem ser extraídas (via bindings) e como compô-las
em turnos de chat (messages).
messages:
- { role: user, content: "${task}", stream: high_level }
- { role: assistant, content: "${subtask}", stream: low_level, target: true }Uma receita também pode se ramificar em um blend ponderado de sub-receitas. No momento da amostragem, exatamente um ramo é selecionado deterministicamente a partir do índice da amostra, de modo que diferentes quadros treinam diferentes objetivos (por exemplo, atualizações de memória vs. execução de baixo nível vs. VQA) sem qualquer configuração em Python.
Semântica temporal
Estilos persistentes ficam ativos após a emissão até serem substituídos:
active_at(t, style=subtask)nth_prev(style=memory, offset=1)nth_next(style=subtask, offset=1)
Os estilos de eventos existem apenas em seu timestamp exato:
emitted_at(t, style=interjection)emitted_at(t, style=vqa, role=user, camera=observation.images.top)emitted_at(t, role=assistant, tool_name=say)
O correspondência exata de eventos não possui uma janela de tolerância, portanto, os escritores devem carimbar as linhas de eventos com os timestamps dos quadros dos dados parquet.
Resolução dependente da visualização
Para estilos dependentes da câmera (vqa e trace), o resolver ganha um filtro camera= paralelo a role= e tool_name=. Conjuntos de dados com múltiplas câmeras geralmente emitem um par (vqa, user) + (vqa, assistant) por câmera no mesmo timestamp; sem camera=, esses resolvers veem duas correspondências e levantam um erro de ambiguidade. As receitas consomem cada câmera por meio de seu próprio binding mais um bloco de imagem correspondente, por exemplo
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,
}Adicione uma sub-receita dessas para cada câmera que o conjunto de dados registra. O marcador explícito route: vqa faz com que uma anotação esparsa de VQA correspondente tenha precedência sobre a seleção normal de mistura ponderada; os nomes dos componentes são puramente descritivos.
Camada 3 — formato de treinamento
As amostras renderizadas usam mensagens de chat no estilo HF, além dos sidecars do LeRobot:
sample["messages"]
sample["message_streams"]
sample["target_message_indices"]O renderer não aplica um template de chat do tokenizer. Os processadores de política decidem como serializar as mensagens para o backbone correspondente, o que mantém o mesmo dataset utilizável em SmolVLA, Pi0.5 e qualquer VLM futuro que espere mensagens de chat no estilo OpenAI.
Blends
As receitas de blend selecionam deterministicamente uma sub-receita ponderada a partir do índice da amostra. recipes/subtask_mem.yaml treina o blend compacto do núcleo — previsão de subtarefas de alto nível, execução de baixo nível e memória. recipes/subtask_mem_vqa_speech.yaml é a variante mais completa, que também adiciona respostas de VQA e interjeições faladas.
recipes/subtask_joint.yaml demonstra o treinamento sequencial conjunto, em vez de uma mistura ponderada. Para a mesma amostra, seu subtask de assistente é supervisionado com cross-entropy de texto no stream low_level, enquanto a previsão de ação permanece ativa, correspondendo à configuração conjunta do paper π0.5. Por enquanto, é apenas para treinamento: o runtime ainda não reconstrói esse prefixo conjunto na inferência.
Ausência graciosa
Se ambas as colunas de idioma estiverem ausentes, forem None ou vazias, o RenderTrainingMessagesStep usa a string da tarefa como supervisão de baixo nível quando disponível e, caso contrário, deixa a amostra inalterada. Para uma amostra anotada, se nenhum ramo de receita se aplicar e não existir um fallback de tarefa, a renderização retorna None, permitindo que um loader tente outra amostra.