LeRobot documentation
Создание docstrings
Создание docstrings
Справочник API LeRobot генерируется непосредственно из docstrings в src/lerobot/. Docstring — это не
комментарий, а опубликованная документация для данного объекта, и формат, описанный ниже, является тем, что
парсят рендерер и проверки CI.
Эта страница является контрактом. Если вы добавляете или редактируете что-либо публичное в src/lerobot/, следуйте ему.
Недокументированный публичный метод — это невидимый метод.
[[autodoc]]молча пропускает элементы, у которых нет docstring, — без предупреждений и ошибок, они просто не появляются на отрендеренной странице. Покрытие и полнота справочника API — это одна и та же проблема.
Формат в одном примере
Заголовки разделов Google, форматирование типов Hugging Face. И то, и другое, а не одно из них.
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
```
"""Ссылки на другие разделы опущены в примерах на этой странице — см. Ссылки на другие разделы для синтаксиса и объяснения, почему их нельзя отображать внутри блока кода.
Правила
Разделы
Args: · Returns: · Raises: · Yields: · Example: · Note:
В таком порядке. Никаких других заголовков разделов. Сначала — однострочное резюме, затем — необязательное свободное описание, а после — разделы.
Строка Args: обрабатывается машиной
name (`type`, *optional*, defaults to `X`):
Description, indented on its own line.Кlaus *optional*, defaults to проверяется на соответствие фактическому значению по умолчанию в сигнатуре с помощью make check-docstrings. Это не просто формальность — если указанное вами значение по умолчанию разошлось с кодом, CI
завершится с ошибкой. Для обязательных параметров полностью опускайте этот klaus:
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.Типы указываются в обратных кавычках. Используйте *optional* без defaults to, если значение по умолчанию равно None или его не стоит повторять.
Возвращает: is type-first
Одна отступная строка: сначала тип, затем двоеточие, затем описание:
Returns:
`dict[str, float]`: The action actually written to the motors after safety clipping.Yields: принимает ту же форму.
**Атрибуты**: , никогда Атрибуты:
doc-builder интерпретирует одиночное Attributes: как синоним Parameters:, из-за чего ваши атрибуты отображаются как аргументы конструктора. Это происходит без предупреждений и является ошибкой. Если атрибуты отличаются от параметров конструктора, используйте жирную форму с разделителем --:
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.
"""Обратите внимание --, а не :.
Ссылки
Используйте синтаксис скобок doc-builder: путь в квадратных скобках, заключённый в обратные кавычки. Роли Sphinx (:pymeth:, :pyattr:) не поддерживаются и отображаются на странице как обычный текст.
| Хотите | Запись |
|---|---|
| Класс в основном пакете | [Robot] |
| Метод, показать полный путь | [Robot.connect] |
| Метод, показать только имя | [~Robot.connect] |
| Вложенный путь | [~robots.Robot.connect] |
| Объект в другой библиотеке HF | [~accelerate.Accelerator] |
Символ ~ удаляет путь только из текста ссылки; сама ссылка по-прежнему указывает на полный путь.
doc-builder разрешает этот синтаксис везде на странице — в том числе внутри блоков кода с ограничителями. Именно поэтому примеры в docstring на этой странице используют обычный текст, а не перекрёстные ссылки: блок кода, содержащий такую ссылку, отобразит разрешённую ссылку, а не синтаксис, который нужно ввести. В собственных docstring вы можете свободно использовать перекрёстные ссылки; это ограничение касается только документации о синтаксисе.
Выделенные блоки
Используйте цитаты в стиле 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.Компонент <Tip> считается устаревшим в doc-builder; не добавляйте новые.
Примеры должны быть заключены в забор
Пример находится внутри блока ```python, содержащего >>>. Именно этот блок заставляет его отображаться как фрагмент кода, и именно его ищет регулярное выражение препроцессора doctest:
Example:
```python
>>> from lerobot.robots.so_follower import SO101FollowerConfig
>>> cfg = SO101FollowerConfig(port="/dev/ttyACM0")
>>> cfg.use_degrees
True
```Незакрытый
>>>всё равно будет собран — doctest находит промпты в любом месте docstring. Вы теряете только отображение, поэтому на странице это выглядит как сплошной текст. Каждому примеру нужен забор.
Каждый пример либо выполняется в CI, либо содержит # doctest: +SKIP. Всё, что связано с оборудованием, GPU или загрузкой с Hub, получает +SKIP:
Example:
```python
>>> robot.connect() # doctest: +SKIP
>>> policy = ACTPolicy.from_pretrained("lerobot/act_aloha_sim_transfer_cube_human") # doctest: +SKIP
```Добавьте файлы с запускаемыми примерами в utils/documentation_tests.txt.
Размещайте примеры на трёх-пяти реальных точках входа модуля. Примеры для тривиальных аксессоров — это шум.
Три паттерна, с которыми вы будете сталкиваться постоянно
Данные классов конфигурации
Поле конфигурации исторически документируется с помощью комментариев # над каждым полем. doc-builder не видит
инлайн-комментарии — такой класс отображается со списком всех полей, но без единого описания. Перенесите их
в блок Args: в docstring класса:
@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 = Truedoc-builder не наследует docstrings от базовых классов. Зарегистрированные классы конфигурации LeRobot часто представляют собой тонкие обёртки с множественным наследованием:
@RobotConfig.register_subclass("so101_follower") @dataclass class SOFollowerRobotConfig(RobotConfig, SOFollowerConfig): passЭтот класс отображает все поля — включая унаследованные — без каких-либо описаний, независимо от того, насколько хорошо документированы базовые классы. Блок
Args:должен находиться в конкретном классе, который указывает[[autodoc]], и он должен покрывать и унаследованные поля.
Базовый класс, затем конкретный подкласс
Абстрактный базовый класс содержит канонический контракт. Подклассы документируют только то, что отклоняется от него — семантику портов, особенности калибровки, компоновку моторов, поддерживаемые ключи функций. Не копируйте базовый контракт в каждый подкласс.
Robot, Teleoperator, Camera, MotorsBusBase, ProcessorStep и PreTrainedPolicy все следуют этой структуре.
Псевдонимы на уровне модуля
Несколько публичных имён являются псевдонимами, а не отдельными классами:
SO100FollowerConfig = SOFollowerRobotConfig SO101FollowerConfig = SOFollowerRobotConfig
[[autodoc]] разрешает псевдоним и отображает каноническое имя класса, поэтому заголовок ## SO101FollowerConfig в тексте будет показывать class lerobot.robots.so_follower.SOFollowerRobotConfig. Документируйте канонический класс один раз, а псевдонимы упоминайте в тексте страницы, а не создавайте для каждого псевдонима отдельный блок autodoc.
Чего не следует документировать
- Служебные члены. Всё, что начинается с
_, не входит в публичный API. - Аннотация типа, переформулированная в виде текста.
port (str): A string.ничего не добавляет. Укажите, для чего она предназначена. - Вендорный код из upstream.
src/lerobot/policies/molmoact2/molmoact2_hf_model/является вендорным изtransformersи уже содержит docstrings в стиле upstream. Не трогайте его — перестиллинг приведёт только к конфликтам при следующей синхронизации. Этот код исключён из API reference и из проверок docstrings.
Как это обеспечивается
| Проверка | Что он выявляет |
|---|---|
make check-docstrings | Запись Args:, не соответствующая сигнатуре; задокументированное значение по умолчанию, отличающееся от фактического |
make doctest | Примеры, которые больше не работают |
make check-doctest-list | Устаревшие или не отсортированные записи в utils/documentation_tests.txt |
ruff (правила D) | Нарушения стиля по конвенции Google |
interrogate | Доля покрытых docstring ниже текущего порога |
| doc-builder | Путь [[autodoc]], указывающий на несуществующий объект — это приводит к сбою сборки документации |
Запускайте их вместе перед созданием PR:
make check-docstrings && make doctest && pre-commit run --all-files
Затем отрендерьте страницу и действительно посмотрите на неё:
doc-builder build lerobot docs/source/ --build_dir /tmp/doc-build
Чек-лист
- У каждого публичного члена, к которому вы обращались, есть строка документации.
- Каждая запись
Args:соответствует сигнатуре, включая*optional*, defaults to. -
Returns:имеет тип-сначала на одной отступленной строке. - Без «голых»
Attributes:— используйте**Attributes**:с разделителями--. - Роли Sphinx не используются — перекрёстные ссылки оформляются как [
~module.Class.method]. - Примеры находятся внутри блока
```pythonи либо запускаются в CI, либо содержат# doctest: +SKIP. - Поля dataclass конфигурации находятся в блоке
Args:конкретного класса, а не в комментариях#. - Отрендеренная страница проверена визуально.