LeRobot documentation

Rédaction de docstrings

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

and get access to the augmented documentation experience

to get started

Rédaction de docstrings

La référence de l’API de LeRobot est générée directement à partir des docstrings dans src/lerobot/. Une docstring n’est pas un commentaire — c’est la documentation publiée pour cet objet, et le format ci-dessous est celui que le renderer et les vérifications CI analysent.

Cette page est le contrat. Si vous ajoutez ou modifiez quoi que ce soit de public dans src/lerobot/, suivez-le.

Une méthode publique non documentée est une méthode invisible. [[autodoc]] ignore silencieusement les membres qui n’ont pas de docstring — sans avertissement, sans erreur, ils tout simplement n’apparaissent pas sur la page rendue. La couverture et la complétude de la référence API sont le même problème.

Le format dans un exemple

En-têtes de section Google, formatage de type Hugging Face. Les deux, pas l'un ou l'autre.

def send_action(self, action: RobotAction, rate_hz: float = 30.0) -> RobotAction:
    """Command the robot to move to a target joint configuration.

    Values are clipped by the configured maximum relative target before reaching the motors, so the
    returned action may differ from the requested one.

    Args:
        action (`dict[str, float]`):
            Target values keyed by motor name, e.g. `{"shoulder_pan.pos": 0.0}`. Keys must match the
            robot's action features.
        rate_hz (`float`, *optional*, defaults to `30.0`):
            Control loop frequency.

    Returns:
        `dict[str, float]`: The action actually written to the motors after safety clipping.

    Raises:
        DeviceNotConnectedError: If the robot has not been connected.

    Example:
        ```python
        >>> from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
        >>> robot = SO101Follower(SO101FollowerConfig(port="/dev/ttyACM0"))  # doctest: +SKIP
        >>> robot.connect()  # doctest: +SKIP
        >>> robot.send_action({"shoulder_pan.pos": 0.0})  # doctest: +SKIP
        ```
    """

Les références croisées sont omises dans les exemples de cette page — voir Références croisées pour leur syntaxe et la raison pour laquelle elles ne peuvent pas être affichées dans un bloc de code.

Règles

Sections

Args: · Returns: · Raises: · Yields: · Example: · Note:

Dans cet ordre. Aucune autre en-tête de section. Un résumé en une ligne vient en premier, puis une description libre facultative, puis les sections.

La ligne Args: est analysée par la machine

name (`type`, *optional*, defaults to `X`):
    Description, indented on its own line.

La clause *optional*, defaults to est vérifiée par rapport à la valeur par défaut réelle de la signature par make check-docstrings. Elle n’est pas décorative — si vous indiquez une valeur par défaut qui a divergé du code, la CI échoue. Omettez entièrement la clause pour les paramètres obligatoires :

    Args:
        port (`str`):
            Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
        max_relative_target (`float | dict[str, float]`, *optional*):
            Caps the magnitude of the relative positional target vector. `None` disables clipping.
        use_degrees (`bool`, *optional*, defaults to `True`):
            Keep `True` for backward compatibility with existing policies and datasets.

Types go in backticks. Use *optional* with no defaults to when the default is None or is otherwise not worth restating.

Retourne : est de type premier

Une ligne indentée, le type d'abord, puis un deux-points, puis la description :

    Returns:
        `dict[str, float]`: The action actually written to the motors after safety clipping.

Yields: prend la même forme.

**Attributs** : , jamais Attributs :

doc-builder interprète un simple Attributes: comme un synonyme de Parameters:, de sorte que vos attributs sont rendus comme des arguments du constructeur. Ce comportement est silencieux et incorrect. Chaque fois que les attributs diffèrent des paramètres du constructeur, utilisez la forme en gras avec un séparateur -- :

class Robot(abc.ABC):
    """The base abstract class for all LeRobot-compatible robots.

    **Attributes**:
        - **config_class** (`type[RobotConfig]`) -- The expected configuration class for this robot.
        - **name** (`str`) -- The unique robot name used to identify this robot type.
    """

Note --, et non :.

Références croisées

Utilisez la syntaxe des crochets de doc-builder : un chemin entre crochets et guillemets bas. Les rôles Sphinx (:pymeth:, :pyattr:) ne sont pas pris en charge et s’affichent en texte littéral sur la page.

SouhaitezÉcrire
Classe du package principal[Robot]
Méthode, afficher le chemin complet[Robot.connect]
Méthode, afficher le nom brut[~Robot.connect]
Chemin imbriqué[~robots.Robot.connect]
Objet dans une autre bibliothèque HF[~accelerate.Accelerator]

Le ~ supprime le chemin uniquement du texte du lien ; le lien pointe toujours vers le chemin complet.

doc-builder résout cette syntaxe partout dans une page — y compris à l’intérieur des blocs de code délimités. C’est pourquoi les exemples de docstring sur cette page utilisent du texte simple plutôt que des références croisées : un bloc de code en contenant une afficherait le lien résolu au lieu de la syntaxe à saisir. Dans vos propres docstrings, utilisez les références croisées librement ; cette restriction ne concerne que la documentation sur la syntaxe.

Encadrés

Utilisez des citations de bloc de style GitHub :

> [!TIP]
> Call this once at startup — it takes about two seconds.

> [!WARNING]
> Torque is disabled on disconnect. The arm will drop if it is holding a load.

Le composant <Tip> est obsolète selon doc-builder ; n’en ajoutez pas de nouveaux.

Les exemples doivent être encadrés

Un exemple se trouve dans un bloc ```python contenant >>>. C’est la clôture qui le fait afficher comme un bloc de code, et c’est ce que la regex du préprocesseur doctest recherche :

    Example:
        ```python
        >>> from lerobot.robots.so_follower import SO101FollowerConfig
        >>> cfg = SO101FollowerConfig(port="/dev/ttyACM0")
        >>> cfg.use_degrees
        True
        ```

Un >>> non encadré est toujours collecté — doctest trouve les invites n’importe où dans une docstring. Ce que vous perdez, c’est le rendu, ce qui se présente donc comme un bloc de texte sur la page. Chaque exemple a besoin de l’encadrement.

Chaque exemple est soit exécuté en CI, soit porte la balise # doctest: +SKIP. Tout ce qui concerne le matériel, un GPU ou des téléchargements depuis le Hub reçoit la balise +SKIP :

    Example:
        ```python
        >>> robot.connect()  # doctest: +SKIP
        >>> policy = ACTPolicy.from_pretrained("lerobot/act_aloha_sim_transfer_cube_human")  # doctest: +SKIP
        ```

Ajoutez les fichiers contenant des exemples exécutables à utils/documentation_tests.txt.

Placez des exemples sur les trois à cinq points d’entrée réels d’un module. Les exemples sur des accesseurs triviaux sont du bruit.

Trois motifs que vous rencontrerez constamment

Config dataclasses

Les champs de configuration sont historiquement documentés par des commentaires # au-dessus de chaque champ. doc-builder ne peut pas voir les commentaires en ligne — une telle classe s’affiche avec tous les champs listés et sans aucune description. Déplacez-les dans un bloc Args: de la docstring de la classe :

@dataclass
class SOFollowerConfig:
    """Configuration for SO-family follower arms.

    Args:
        port (`str`):
            Serial port the arm is connected to, e.g. `/dev/ttyACM0`.
        max_relative_target (`float | dict[str, float]`, *optional*):
            Caps the magnitude of the relative positional target vector. A scalar applies to all motors;
            a dict maps motor name to a per-motor cap. `None` disables clipping.
        use_degrees (`bool`, *optional*, defaults to `True`):
            Keep `True` for backward compatibility with existing policies and datasets.
    """

    port: str
    max_relative_target: float | dict[str, float] | None = None
    use_degrees: bool = True

doc-builder n’hérite pas des docstrings des classes de base. Les classes de configuration enregistrées de LeRobot sont souvent de simples shims d’héritage multiple :

@RobotConfig.register_subclass("so101_follower")
@dataclass
class SOFollowerRobotConfig(RobotConfig, SOFollowerConfig):
    pass

Cette classe affiche chaque champ — y compris ceux hérités — sans aucune description, quelle que soit la qualité de la documentation des classes de base. Le bloc Args: doit se trouver sur la classe concrète nommée par [[autodoc]], et il doit couvrir également les champs hérités.

Classe de base, puis sous-classe concrète

La classe de base abstraite porte le contrat canonique. Les sous-classes documentent uniquement les écarts — sémantique du port, particularités de calibration, disposition des moteurs, clés de fonctionnalités prises en charge. Ne copiez pas le contrat de base dans chaque sous-classe.

Robot, Teleoperator, Camera, MotorsBusBase, ProcessorStep et PreTrainedPolicy suivent tous cette forme.

Alias au niveau du module

Plusieurs noms publics sont des alias plutôt que des classes distinctes :

SO100FollowerConfig = SOFollowerRobotConfig
SO101FollowerConfig = SOFollowerRobotConfig

[[autodoc]] résout l’alias et affiche le nom de classe canonique, de sorte qu’un en-tête ## SO101FollowerConfig affichera class lerobot.robots.so_follower.SOFollowerRobotConfig dans le corps du texte. Documentez la classe canonique une seule fois et mentionnez les alias dans le texte de la page plutôt que de donner à chaque alias son propre bloc autodoc.

Ce qu'il ne faut pas documenter

  • Membres privés. Tout ce qui commence par _ ne fait pas partie de l'API publique.
  • La réécriture de l’annotation de type sous forme de prose. port (str): A string. n’apporte rien. Indiquez à quoi elle sert.
  • Code en amont intégré. src/lerobot/policies/molmoact2/molmoact2_hf_model/ est intégré depuis transformers et contient déjà des docstrings au style amont. Laissez-le tel quel — le reformater ne ferait que créer des conflits lors de la prochaine synchronisation. Il est exclu de la référence API et des vérifications de docstrings.

Comment cela est appliqué

VérifierCe qu'il détecte
make check-docstringsUne entrée Args: qui ne correspond pas à la signature ; une valeur par défaut documentée qui a divergé de la valeur réelle
make doctestExemples qui ne fonctionnent plus
make check-doctest-listEntrées obsolètes ou non triées dans utils/documentation_tests.txt
ruff (règles D)Violations du style de convention Google
interrogateCouverture des docstrings inférieure au seuil actuel
doc-builderUn chemin [[autodoc]] qui pointe vers quelque chose qui n’existe pas — cela casse la construction de la documentation

Exécutez-les ensemble avant d’ouvrir une PR :

make check-docstrings && make doctest && pre-commit run --all-files

Puis, affichez la page et examinez-la réellement :

doc-builder build lerobot docs/source/ --build_dir /tmp/doc-build

Liste de contrôle

  • Chaque membre public que vous avez modifié possède une docstring.
  • Chaque entrée Args: correspond à la signature, y compris la clause *optional*, defaults to.
  • Returns: est de type premier sur une ligne indentée.
  • Pas d'Attributes: nu — utilisez **Attributes**: avec des séparateurs --.
  • Pas de rôles Sphinx — les références croisées utilisent [~module.Class.method].
  • Les exemples sont dans un bloc ```python et sont soit exécutés en CI, soit marqués # doctest: +SKIP.
  • Les champs de la dataclass de configuration sont dans un bloc Args: sur la classe concrète, pas des commentaires #.
  • La page rendue a été vérifiée visuellement.
Update on GitHub