LeRobot documentation

ポリシーの追加

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

ポリシーの追加

このガイドでは、カスタムポリシーの実装方法と、LeRobotのトレーニング、評価、デプロイメントツールとの連携方法について説明します。2つのアプローチがあります:

  • プラグイン(ツリー外) — ポリシーを独立したlerobot_policy_*パッケージとして配布します。迅速で、PRは不要、反復が容易です。実験、社内利用、または独立して公開したい場合に適しています。
  • インツリー(LeRobotへの貢献) — ポリシーを直接src/lerobot/policies/にマージします。PRが必要ですが、ポリシーをライブラリの第一級市民にできます。

プラグインルートは通常、適切な出発点です。ポリシーが安定し、ライブラリに同梱してリリースする明確な価値があることが明らかになったら、インツリーに昇格させます。

いずれにせよ、構成要素は同じです: 設定クラス、ポリシークラス、プロセッサファクトリです。このガイドの前半では、これらの共通部分について説明し、後半ではパス固有の足場(Path A、Path B)について説明します。

トーンに関する注意: robot-learningは活発に進化する分野であり、「ポリシーの姿」は新しいアーキテクチャごとに変わり得ます。ここで説明する慣例が存在するのは、lerobot-trainとlerobot-evalが、非常に異なるモデル間で均一に動作できるようにするためです。新しいポリシーがこれらに本当に適合しない場合は、その旨を提起してください(PRやissueで)。慣例は神聖不変ではありません。


ポリシーの構造

すべてのポリシーは3つの構成要素から成り立っています。以下の名称はmy_policyをプレースホルダーとして使用しています。ご自身のポリシー名に置き換えてください。この名称は重要な役割を果たします。@PreTrainedConfig.register_subclassに渡す文字列、MyPolicy.nameクラス属性、およびmake_<name>_pre_post_processorsファクトリ関数(以下でそれぞれ詳しく説明します)と一致している必要があります。

設定クラス

PreTrainedConfig を継承し、ポリシーの種類を登録します。以下はテンプレートです。ポリシーのアーキテクチャや学習要件に合わせて、パラメータやメソッドを必要に応じてカスタマイズしてください。

# configuration_my_policy.py
from dataclasses import dataclass, field
import torch
from lerobot.configs import PreTrainedConfig
from lerobot.optim import AdamWConfig
from lerobot.optim import CosineDecayWithWarmupSchedulerConfig

@PreTrainedConfig.register_subclass("my_policy")
@dataclass
class MyPolicyConfig(PreTrainedConfig):
    """Configuration class for MyPolicy.

    Args:
        n_obs_steps: Number of observation steps to use as input
        horizon: Action prediction horizon
        n_action_steps: Number of action steps to execute
        hidden_dim: Hidden dimension for the policy network
        # Add your policy-specific parameters here
    """

    dtype: torch.dtype | None = torch.bfloat16

    horizon: int = 50
    n_action_steps: int = 50
    hidden_dim: int = 256

    optimizer_lr: float = 1e-4
    optimizer_weight_decay: float = 1e-4

    def __post_init__(self):
        super().__post_init__()
        if self.n_action_steps > self.horizon:
            raise ValueError("n_action_steps cannot exceed horizon")

    def validate_features(self) -> None:
        """Validate input/output feature compatibility.

        Call this explicitly from your policy's __init__ — the base class does not.
        """
        if not self.image_features:
            raise ValueError("MyPolicy requires at least one image feature.")
        if self.action_feature is None:
            raise ValueError("MyPolicy requires 'action' in output_features.")

    def get_optimizer_preset(self) -> AdamWConfig:
        return AdamWConfig(lr=self.optimizer_lr, weight_decay=self.optimizer_weight_decay)

    def get_scheduler_preset(self):
        """Return a LRSchedulerConfig from lerobot.optim, or None."""
        return None

    @property
    def observation_delta_indices(self) -> list[int] | None:
        """Relative timestep offsets the dataset loader provides per observation.

        Return `None` for single-frame policies. For temporal policies that consume
        multiple past or future frames, return a list of offsets, e.g. `[-20, -10, 0, 10]` for
        3 past frames at stride 10 and 1 future frame at stride 10.
        """
        return None

    @property
    def action_delta_indices(self) -> list[int]:
        """Relative timestep offsets for the action chunk the dataset loader returns."""
        return list(range(self.horizon))

    @property
    def reward_delta_indices(self) -> None:
        return None

@register_subclass に渡す文字列は、MyPolicy.name(次のセクション)と一致する必要があり、ユーザーが CLI で --policy.type として指定する値です。get_optimizer_preset については、本当に別のものが必要な場合を除き、lerobot.optim の AdamW をデフォルトとしてください。PreTrainedConfig はすでに dtype: torch.dtype | None を宣言しています。ポリシーにデフォルトの精度を指定するには、torch.dtype の値(例: dtype: torch.dtype | None = torch.bfloat16)で再宣言してください。

Policyクラス

PreTrainedPolicy を継承し、2 つのクラス属性を設定します。これら 2 つは __init_subclass__ によってチェックされます。

# modeling_my_policy.py
import torch
import torch.nn as nn
from typing import Any

from lerobot.policies import PreTrainedPolicy
from lerobot.utils.constants import ACTION
from .configuration_my_policy import MyPolicyConfig

class MyPolicy(PreTrainedPolicy):
    config_class = MyPolicyConfig  # must match the string in @register_subclass
    name = "my_policy"

    def __init__(self, config: MyPolicyConfig, dataset_stats: dict[str, Any] = None):
        super().__init__(config, dataset_stats)
        config.validate_features()  # not called automatically by the base class
        self.config = config
        self.model = ...  # your nn.Module here

    def reset(self):
        """Reset per-episode state. Called by lerobot-eval at the start of each episode."""
        ...

    def get_optim_params(self) -> dict:
        """Return parameters to pass to the optimizer (e.g. with per-group lr/wd)."""
        return {"params": self.parameters()}

    def predict_action_chunk(self, batch: dict[str, torch.Tensor], **kwargs) -> torch.Tensor:
        """Return the full action chunk (B, chunk_size, action_dim) for the current observation."""
        ...

    def select_action(self, batch: dict[str, torch.Tensor], **kwargs) -> torch.Tensor:
        """Return a single action for the current timestep (called every step at inference)."""
        ...

    def forward(self, batch: dict[str, torch.Tensor]) -> tuple[torch.Tensor, dict | None]:
        """Compute the training loss.

        Returns `(loss, output_dict)`. `output_dict` may be `None`; everything in it must be
        logging-friendly Python natives (no tensors with gradients).

        `batch["action_is_pad"]` is a bool mask of shape (B, horizon) that marks
        timesteps padded because the episode ended before `horizon` steps; you
        can exclude those from your loss.
        """
        actions = batch[ACTION]
        action_is_pad = batch.get("action_is_pad")
        ...
        return loss, {"some_loss_component": some_loss_component.item()}

train/evalループによって呼び出されるメソッド:

メソッド使用例機能
reset() -> Nonelerobot-eval各エピソードの開始時に、エピソードごとの状態をクリアします。
select_action(batch, **kwargs) -> Tensorlerobot-eval次のアクション(B, action_dim)を返します。各ステップで呼び出されます。
predict_action_chunk(batch, **kwargs) -> Tensorポリシー自体アクションチャンク(B, chunk_size, action_dim)を返します。ベースクラスでは現在抽象化されており、ポリシーがチャンク化を行わない場合はNotImplementedErrorを発生させます。
forward(batch, reduction="mean") -> tuple[Tensor, dict \| None]lerobot-train(loss, output_dict) を返します。サンプルごとの重み付けをサポートする場合は、reduction="none" を受け取ってください。
get_optim_params() -> dictオプティマイザ単純なポリシーの場合はself.parameters()を返します。マルチオプティマイザーポリシーの場合は、名前付きパラメータの辞書を返します(グループごとの学習率の例については、modeling_act.pyのget_optim_paramsを参照してください)。
update() -> None (任意)lerobot-train定義されている場合、定義されている場合、各オプティマイザーステップの後に呼び出されます。EMA、ターゲットネット、リプレイバッファ(TDMPCはこれを使用)に使用します。

バッチは、lerobot.utils.constants に定義された定数をキーとするフラットな辞書です: OBS_STATE (observation.state.<motor>)、OBS_IMAGES (observation.images.<camera>)、OBS_LANGUAGE、ACTION などです。定数を再利用してください。新しいプレフィックスを独自に作成しないでください。

モデルが十分大きくなってシャード化されたマルチGPUトレーニングが必要になる場合は、FSDPのラップ単位、つまりシャード化が対象とする繰り返しブロックのクラスも宣言してください:

class MyPolicy(PreTrainedPolicy):
    ...
    _fsdp_wrap_modules = ["MyTransformerBlock"]

この1つの宣言により、--parallelism.dp_shard=Nはポリシーに対してそのまま動作します(ユーザーは--accelerator.fsdp.wrap_modulesで上書きできます)。ラップソースが指定されていない場合、シャード化された実行は設計上、起動時に失敗します。

プロセッサ関数

LeRobot は、ポリシーの前後で入力を正規化し、出力を非正規化するために PolicyProcessorPipeline を使用します。具体的な参考として、processor_act.py または processor_diffusion.py をご覧ください。

ここには特に注意してください。プロセッサは再現性に関する最も一般的な問題点です。正規化モード(IDENTITYとMEAN_STD、MIN_MAX、QUANTILES/QUANTILE10)や、どの特徴量が正規化されるかの不一致は、エラーを出さずに学習と評価が実行されますが、結果を静かに壊してしまいます。モードがチェックポイントの学習時のものに合わせていること、必要な統計情報が存在すること(例: QUANTILESにはq01/q99が必要)、そして前処理と後処理のプロセッサが整合していることを確認してください。

# processor_my_policy.py
from typing import Any
import torch

from lerobot.processor import PolicyAction, PolicyProcessorPipeline


def make_my_policy_pre_post_processors(
    config,
    dataset_stats: dict[str, dict[str, torch.Tensor]] | None = None,
) -> tuple[
    PolicyProcessorPipeline[dict[str, Any], dict[str, Any]],
    PolicyProcessorPipeline[PolicyAction, PolicyAction],
]:
    preprocessor = ...   # build your PolicyProcessorPipeline for inputs
    postprocessor = ...  # build your PolicyProcessorPipeline for outputs
    return preprocessor, postprocessor

重要 — 関数名: LeRobot は名前によってプロセッサを検出します。関数はmake_{policy_name}_pre_post_processors(@PreTrainedConfig.register_subclassに渡した文字列と一致するもの)と必ず命名してください。

オプション: チェックポイントから読み込まれたプロセッサの調整

make_{policy_name}_pre_post_processors は、プロセッサがゼロから構築される場合のみ実行されます。チェックポイントが関わる場合(ファインチューニング、再開、評価)には、LeRobot は代わりに重みの隣にシリアライズされたパイプラインを読み込み、呼び出し側のオーバーライドを適用します。

ポリシーが読み込まれたパイプラインを調整する必要がある場合は、同じモジュールに任意の第2の関数を追加してください。その関数名はmake_{policy_name}_pre_post_processors_from_pretrainedです。LeRobotは同じ命名規則でこれを検出し、汎用の読み込みの代わりに呼び出します。特別な処理を必要としないポリシーは、この関数を省略してください。

from lerobot.processor import load_pretrained_policy_processors
from lerobot.utils.constants import (
    POLICY_POSTPROCESSOR_DEFAULT_NAME,
    POLICY_PREPROCESSOR_DEFAULT_NAME,
)


def make_my_policy_pre_post_processors_from_pretrained(
    config,
    pretrained_path: str,
    *,
    revision: str | None = None,
    dataset_stats: dict[str, dict[str, torch.Tensor]] | None = None,
    dataset_meta: Any | None = None,
    preprocessor_overrides: dict[str, Any] | None = None,
    postprocessor_overrides: dict[str, Any] | None = None,
    preprocessor_config_filename: str = f"{POLICY_PREPROCESSOR_DEFAULT_NAME}.json",
    postprocessor_config_filename: str = f"{POLICY_POSTPROCESSOR_DEFAULT_NAME}.json",
) -> tuple[
    PolicyProcessorPipeline[dict[str, Any], dict[str, Any]],
    PolicyProcessorPipeline[PolicyAction, PolicyAction],
]:
    preprocessor, postprocessor = load_pretrained_policy_processors(
        pretrained_path,
        revision=revision,
        preprocessor_overrides=preprocessor_overrides,
        postprocessor_overrides=postprocessor_overrides,
        preprocessor_config_filename=preprocessor_config_filename,
        postprocessor_config_filename=postprocessor_config_filename,
    )
    ...  # reconcile the loaded pipelines with the current `config`
    return preprocessor, postprocessor

動作する例については、processor_evo1.py(正規化統計の再パディング)、processor_groot.py(生の上流チェックポイントの処理)、processor_molmoact2.py(オーバーライドキーの名前変更)を参照してください。

アクション(想像されたフレーム、サブタスク、ボックス)に加えて予測を返す

ポリシーは、実行するアクションのほかに、期待または推定される情報(例えば、ワールドモデルが想像したフレーム、予測されたサブタスク、バウンディングボックスなど)を返す場合があります。そのため、--display_data を使用すると、Rerun または Foxglove でそれらをライブ表示できます。select_action および predict_action_chunk はバッチを受け取り、生のアクションテンソル(すべてのポリシーのデフォルト)または PolicyOutput(lerobot.lerobot_types)を返します。PolicyOutput は入力バッチと同様にキー付けされたバッチであり、アクションは "action" 配下、PolicyPrediction は "prediction" 配下に格納されます。予測はアクションと同様にバッチ化され、環境ごとに1つの値を持ち、各エントリは参照する内容に基づいてキー付けされます。

  • observation: 予測される将来の観測値。観測キーごと("observation.images.top" -> [B, C, H, W] のフレーム)。prediction.images.top として表示されます。
  • language: 環境ごとに1文字列、アノテーションスタイル("subtask"、"plan"、"memory")で指定します。アノテーションパイプラインの言語カラムのスタイルです。prediction.subtask として表示されます。
  • boxes: 観察画像のキーごとに、アノテーション VQA スキーマ ({"detections": [{"label", "bbox": [x1, y1, x2, y2]}]}、画像の比率 0 から 1) に従って、環境ごとに 1 つの bbox 回答が描画されます。

呼び出し側はpolicy_output_to_transitionで2つの戻り値の型を正規化し、PolicyOutputをプロセッサが使用するEnvTransitionに変換します。そのため、予測を行うポリシーのみが変更されます。ビューアでは最初の環境を表示しています。

from lerobot.utils.constants import ACTION, PREDICTION


class MyPolicy(PreTrainedPolicy):
    def select_action(self, batch, **kwargs) -> Tensor | PolicyOutput:
        if not self._action_queue:
            chunk, extras = self.model.sample(batch)
            self._action_queue.extend(chunk.transpose(0, 1))
            if self.config.return_prediction:  # a config field of your choosing
                # The prediction goes with the step that computed it; the others return a bare action.
                prediction = {
                    "observation": {"observation.images.top": extras.next_frames},  # [B, C, H, W]
                    "language": {"subtask": extras.subtasks},  # list[str], one per env
                    "boxes": {
                        "observation.images.top": [
                            {"detections": [{"label": "cube", "bbox": xyxy}]} for xyxy in extras.cube_xyxy
                        ]
                    },
                }
                return {ACTION: self._action_queue.popleft(), PREDICTION: prediction}
        return self._action_queue.popleft()
  • 予測は、このステップの値を保持します。チャンクにまたがるもの(想像上のクリップなど)は、部分ごとに返されます。各ステップは、そのステップが対応するアクションに一致する部分を返します。
  • 各エントリは、再度返されるまで表示され続けます。カメラのボックスをクリアするには、空のdetectionsを返します。
  • 予測はポリシーの構成でオプトイン方式であり、無効化されている場合はコストがかかりません。
  • 予測はアクションを変更せず、postprocessor を通るのはアクションのみです。ポリシーを制御すべきテキスト(次のサブタスクなど)は、generate_text(下記)を通じて処理されます。

テキスト対応ポリシー

Language policies は、2 つの processor ステップ間でレシピのレンダリングを共有します:

  • RenderTrainingMessagesStepは、データセットの言語アノテーションをレンダリングされたメッセージに変換します。
  • RenderRuntimeMessagesStepは、ユーザーのプロンプトをレンダリングされたメッセージに変換します。

ポリシー固有のプロセッサが、チャット形式の整形とトークン化を適用します。

ポリシー設定には、解決済みのrecipe: TrainingRecipe | None(lerobot.datasets.recipeから)が保存されます。任意のrecipe_pathを指定するとYAMLレシピを読み込むことができ、プロセッサを構築する前に解決してください。解決済みのレシピはレシピベースのトレーニングを有効にし、Noneの場合にはトレーニングレンダラーは何もしなくなります。デプロイメントがローカルのYAMLパスに依存しないように、解決済みのレシピを設定とプロセッサにシリアライズしてください。レシピベースのレンダリングには、レシピが現在lerobot.datasetsの下に存在するため、datasetエクストラが必要です。

…

input_steps = [
    RenderRuntimeMessagesStep(config.recipe),
    RenderTrainingMessagesStep(config.recipe),
    # observation transforms
    # policy-native roles, image placement, chat template, and tokenization
    # device placement
]

同じパイプラインが学習と推論の両方で保存および読み込まれます。ランタイムレンダリングは、明示的なquery_kindに対してのみ実行されます。学習時のレンダリングではランタイムクエリをスキップし、レシピが設定されている場合は、生のアノテーションまたはアクションターゲットを持つサンプルを処理します。通常の観察のみを含む入力は何も処理されずにそのまま通過します。アクションテンソルなしで、アノテーション付きのテキストのみによる学習がサポートされています。アノテーションなしの学習では、タスクのフォールバックを有効にするためにアクションターゲットが必要です。

共有ファクトリはプロセッサの構築または読み込みのみを行います。言語レシピのファインチューニングでは、アクティブな設定とデータセットの統計情報からそれらを構築するため、保存されたプロセッサが新しいレシピを上書きすることはできません。再開と推論では、レシピと統計情報を含む保存されたパイプラインを読み込みます。非言語のトレーニングは、既存の構築およびチェックポイント読み込みの動作を維持します。 新規ファクトリは、正規化および相対アクションの設定を自身で導出します。 新規ファクトリは設定されたデバイスを使用し、既存のデータセットバッチ前処理ではトレーニング用のリネームマップが適用されます。

messages_renderedには、ネイティブなチャット形式化やトークン化を行う前の、レシピ展開済みのセマンティックメッセージが含まれています。トレーニング用のサイドカーは、この同じリストをインデックスしています。メッセージのヘルパーはlerobot.utils.languageにあります。

インタラクティブなロールアウトでは、query_kindとquery_textが追加されます。ランタイムのレンダリングは以下をサポートしています:

  • vqa: 呼び出し元の質問をユーザーメッセージとして保持します。
  • next_subtask: ${subtask}を監督するアシスタントのターンを含まない範囲まで、チェックポイントのレシピをレンダリングします。

その後、ポリシーは既存のポリシーAPIを通じてデコーダーを公開します:

class MyPolicy(PreTrainedPolicy):
    def supports_text_generation(self) -> bool:
        return True

    def generate_text(self, batch) -> str:
        token_ids = self.model.generate(**batch)
        return self.tokenizer.decode(token_ids, skip_special_tokens=True)

generate_text は、モデルに渡せる状態のプロセッサ出力を消費します。呼び出し元のプロンプトを再構築したり、再トークナイズしたりしてはいけません。学習中、ポリシーネイティブのトークナイザーは target_message_indices を使用して、選択されたアシスタントのスパンのみを教師信号として使用します。レシピを言語ポリシーの config に保存し、チェックポイントとともにシリアライズされるようにしてください。これにより、デプロイ時に学習で使用されたプロンプトを再構築できます。


パスA: ツリー外プラグイン

ポリシーを最も素早くリリースする方法は、それをスタンドアロンのPythonディストリビューションとしてパッケージ化し、LeRobotと並べてインストールすることです。PRは不要で、リリースサイクルを完全に管理でき、独自のネームスペースでPyPIに公開できます。

パッケージ構成

lerobot_policy_プレフィックス(重要!)にポリシー名を続けて、パッケージを作成します:

lerobot_policy_my_policy/
├── pyproject.toml
└── src/
    └── lerobot_policy_my_policy/
        ├── __init__.py
        ├── configuration_my_policy.py
        ├── modeling_my_policy.py
        └── processor_my_policy.py

pyproject.toml

[project]
name = "lerobot_policy_my_policy"
version = "0.1.0"
dependencies = [
    # your policy-specific dependencies
]
requires-python = ">= 3.12"

[build-system]
build-backend = # your-build-backend
requires = # your-build-system

パッケージ __init__.py

パッケージの__init__.pyでクラスを公開し、lerobotが欠落している場合に備えてガードを設けてください。

# __init__.py
"""Custom policy package for LeRobot."""

try:
    import lerobot  # noqa: F401
except ImportError:
    raise ImportError(
        "lerobot is not installed. Please install lerobot to use this policy package."
    )

from .configuration_my_policy import MyPolicyConfig
from .modeling_my_policy import MyPolicy
from .processor_my_policy import make_my_policy_pre_post_processors

__all__ = [
    "MyPolicyConfig",
    "MyPolicy",
    "make_my_policy_pre_post_processors",
]

インストールと使用

cd lerobot_policy_my_policy
pip install -e .

# Or install from PyPI if published
pip install lerobot_policy_my_policy

インストール後、ポリシーは自動的にLeRobotの学習および評価ツールと統合されます:

lerobot-train \
    --policy.type my_policy \
    --dataset.repo_id lerobot/pusht \
    --env.type pusht \
    --steps 200000 \
    --policy.push_to_hub false

パスB: インツリーへの貢献

ポリシーが安定し、ライブラリに同梱する明確な価値がある場合、LeRobot に直接マージできます。まず一般的なコントリビューションガイドとPR テンプレートをお読みください。すべての PR が満たすべきテスト/品質の要件(pre-commit run -a、pytest、コミュニティレビューのルールなど)が記載されています。以下は、その上に重ねるポリシー固有のレイヤーです。

ツリー内レイアウト

src/lerobot/policies/my_policy/
├── __init__.py                    # re-exports config + modeling + processor factory
├── configuration_my_policy.py     # MyPolicyConfig + @register_subclass
├── modeling_my_policy.py          # MyPolicy(PreTrainedPolicy)
├── processor_my_policy.py         # make_my_policy_pre_post_processors
└── README.md                      # symlink → ../../../../docs/source/policy_my_policy_README.md

2点補足します:

  • ソースの隣にあるREADME.mdは、docs/source/policy_<name>_README.mdへのシンボリックリンクです。実際のファイルはdocs/の下に存在します。既存のポリシー(act、smolvla、diffusion など)はすべてこの方式を採用しています。これらのシンボリックリンクのいずれかをコピーしてください。ポリシーのREADMEは慣例的に最小限の内容、すなわち論文へのリンクとBibTeX引用情報となっています。
  • ユーザー向けのチュートリアル(インストール方法、学習方法、ハイパーパラメータ、ベンチマークの数値など)は、docs/source/<my_policy>.mdx に別途配置され、_toctree.yml の “Policies” 配下に登録されています。

ファイル名は重要な役割を果たしています。ファクトリは名前による遅延インポートを実行し、プロセッサはmake_<policy_name>_pre_post_processorsという規約によって検出されます。

配線

ポリシーについて認識させる必要があるのは2つの場所です。すべて名前を指定してください。

  1. policies/__init__.py — MyPolicyConfigを再エクスポートし、__all__に追加します。このインポートがポリシーを登録します。@PreTrainedConfig.register_subclass("my_policy")が実行され、以降ファクトリが規約に基づいてすべてを解決します。モデリングクラスを再エクスポートしないでください。ファクトリを通じて遅延ロードされるためです(import lerobotが高速に保たれます)。
  2. templates/lerobot_modelcard_template.md とルートディレクトリの README.md — このテンプレートは、ポリシーで学習したすべてのチェックポイントのモデルカードに、学習終了時のパブリッシャーによってレンダリングされます。ポリシーの1行の説明を model_name の各ブランチに追加し、policy_docs でマッピングしてカードから MDX ガイドにリンクできるようにし、必要に応じて diagrams にアーキテクチャの画像を追加します。その後、ルートディレクトリの README.md のモデルテーブルに、適切なカテゴリの下でポリシーを追加し、ドキュメントページへのリンクを設定します。

構造が似ている既存のポリシーをミラーリングしてください。差分はわずかなものです。

重い / オプションの依存関係

ほとんどのポリシーには、重いバックボーン(transformers、diffusers、特定のVLM SDK)が必要です。既存のものが利用可能な場合は、ツリー内でアーキテクチャを再実装するのではなく、transformersやdiffusersなどから読み込むことを優先してください。

慣例は2段階のゲーティングです: モジュールの先頭でTYPE_CHECKINGによるガード付きインポートを行い、コンストラクタ内でrequire_packageによるランタイムチェックを実行します。modeling_diffusion.pyが標準的な参照例です:

from typing import TYPE_CHECKING
from lerobot.utils.import_utils import _diffusers_available, require_package

if TYPE_CHECKING or _diffusers_available:
    from diffusers.schedulers.scheduling_ddim import DDIMScheduler
else:
    DDIMScheduler = None  # keeps the symbol bindable at import time

class DiffusionPolicy(PreTrainedPolicy):
    def __init__(self, config):
        require_package("diffusers", extra="diffusion")
        super().__init__(config)
        ...

このように:

  • import lerobot.policiesは、追加のインストールなしでも引き続き動作します(シンボルは単にNoneにバインドされるだけです)。
  • 型チェッカーは実際のシンボルを確認します。
  • 追加の依存関係なしでポリシーをインスタンス化すると、pip install 'lerobot[diffusion]' を示す明確な ImportError が発生します。

[project.optional-dependencies] に一致する extra を pyproject.toml に追加し、all extra に含めて、pip install 'lerobot[all]' で引き続きすべてがインストールされるようにしてください。

モデルファイルのコピーを避けて — サブクラス化してください

ポリシーがtransformersに既に存在するバックボーンを変更する必要がある場合(カスタム条件付け、追加の入力、サブモジュールの差し替えなど)、そのmodeling_*.pyのコピーをベンダーに含めないでください。代わりに、最小限の上流ユニットをサブクラス化し、変更点のみをオーバーライドしてください。pi_gemma.pyが標準的な参照例です。このファイルは、約2,000行のモデリングファイルをフォークするのではなく、GemmaModel/PaliGemmaModelをサブクラス化してデコーダーレイヤーのforwardをオーバーライドすることで、PaliGemma/GemmaにAdaRMS条件付けを注入し、約370行で実現しています。ロード済みのネイティブモデルに対するモデルの手術(レイヤーの切り詰め、トークナイザーの拡張、隠れ状態のキャプチャなど)も問題ありません(動作する例としてevo1/internvl3_embedder.py、eo1/modeling_eo1.py、groot/groot_n1_7.pyを参照してください)。コピーされたモデリングファイルを含むPRが提出された場合、レビュアーはこのパターンを要求します。唯一許容される例外は、transformersに全く存在しないモデルです。

ベンチマークと公開されたチェックポイント

新しいポリシーは、動作するチェックポイントと、再現可能な少なくとも1つの数値が同梱されている場合、はるかにレビューしやすく、はるかに有用になります。

ツリー内のベンチマークを少なくとも1つ選択してください。 LeRobotには、ベンチマークごとのDockerイメージ(LIBERO、LIBERO-plus、Meta-World、RoboTwin 2.0、RoboCasa365、RoboCerebra、RoboMME、VLABenchなど)が付属するシミュレーションベンチマークが含まれています。ポリシーのモダリティに合ったものを選択してください。VLAは通常LIBEROまたはVLABench、画像のみのBCはLIBEROまたはMeta-Worldが適しています。完全なリストは、ドキュメントのサイドバーにあるBenchmarksの下にあります。

チェックポイントとプロセッサを、lerobot/<policy>_<benchmark>(書き込み権限がない場合は、自分の名前空間にしてください。メンテナーがミラーリングできます)に Hub へプッシュします。最も簡単な方法は、--policy.repo_id=<namespace>/<repo> と --policy.push_to_hub=true を指定して学習を実行することです。lerobot-train は、実行終了時にモデル、両方のプロセッサ、およびモデルカードを公開します。既存のチェックポイントを後から公開する場合は、その pretrained_model/ ディレクトリをアップロードします(例: hf upload)、またはシャーディング形式のチェックポイントには lerobot-convert-dcp --push_to_hub=... を使用します。

ポリシーのMDXに結果を報告し、lerobot-evalのコマンドとハードウェアを正確に記載して、誰でも再実行できるようにします:

## Results

Evaluated on LIBERO with `lerobot/<policy>_libero`:

| Suite          | Success rate | n_episodes |
| -------------- | -----------: | ---------: |
| libero_spatial |        87.5% |         50 |
| libero_object  |        93.0% |         50 |
| libero_goal    |        81.5% |         50 |
| libero_10      |        62.0% |         50 |
| **average**    |    **81.0%** |        200 |

Reproduce: `lerobot-eval --policy.path=lerobot/<policy>_libero --env.type=libero --env.task=libero_spatial --eval.n_episodes=50` (1× A100 40 GB).

安定した成功率の推定を得るには、スイートごとにn_episodes ≥ 50を使用してください。

ポリシーが実ロボットのみで、シミュレーションのベンチマークが適用されない場合は、シミュレーション評価を以下に置き換えてください: Hub上の公開トレーニングデータセット、lerobot-trainコマンド、チェックポイント、およびlerobot-rollout --policy.path=...による10エピソード以上の実ロボットでの成功率。

PRチェックリスト

一般的な期待値は、CONTRIBUTING.mdおよびPRテンプレートに記載されています。それらに加えて、レビュアーは以下を確認します。

  • MyPolicy と MyPolicyConfig は上記の範囲をカバーしています。__init_subclass__ はクラスを受け取ります。
  • policies/__init__.py は設定を再エクスポートします(これによりポリシーが登録され、ファクトリが命名規則に基づいてモデリング/プロセッサを解決します)。
  • make_my_policy_pre_post_processors は命名規則に従っています。
  • オプションの依存関係は、[project.optional-dependencies]エクストラとTYPE_CHECKING + require_packageガードの背後に配置されています。
  • tests/policies/ を更新しました。後方互換性のための成果物をコミットし、ポリシー固有のテストを追加しました。
  • src/lerobot/policies/<name>/README.md を docs/source/policy_<name>_README.md にシンボリックリンクし、ユーザー向けの docs/source/<name>.mdx を作成して _toctree.yml に追加します。
  • lerobot-train --policy.type my_policy ... が、少なくとも数ステップのエンドツーエンド実行を行い、lerobot-eval または lerobot-rollout によってロードして実行できるチェックポイントを保存すること。
  • templates/lerobot_modelcard_template.md には、説明の項目と、ポリシー用の policy_docs リンクが含まれています。
  • ルートの README.md 内のモデルのテーブルには、あなたのポリシーが適切なカテゴリにリストされ、ドキュメントページへのリンクが設定されています。
  • ポリシーのMDXに、公開されたチェックポイント(simベンチマーク、または実ロボットデータセット+チェックポイント)を用いた再現可能なベンチマーク評価が少なくとも1つ含まれていること。

クリーンなPRを最も早く作成するには、既存のポリシーの中で自分のものに最も近いディレクトリをコピーし、名前を変更して、メソッド単位で内容を置き換えることです。すべてが磨き上げられるまで待たず、早めにドラフトPRを開いて、私たちと反復しながら進めてください。レビュアーは、完全にマージされたブランチよりも、未完成のブランチに対してフィードバックをもらうことを好みます。


例とコミュニティの貢献

これらのポリシー実装の例をご覧ください:

LeRobot に新しいポリシーをもたらしてくださったことに感謝いたします。main に取り込まれるすべてのアーキテクチャ、そしてコミュニティによって公開されるすべてのプラグインは、次の利用者のためにライブラリをより実用的にし、ロボット学習の進む方向をよりよく反映するものになります。皆様の今後のリリースを楽しみにしております。🤗

Update on GitHub