LeRobot documentation
도구
도구
LeRobot는 정책에서 도구 호출을 지원합니다. 어시스턴트 메시지는 say(text="OK, starting now")와 같은 구조화된 호출을 출력할 수 있으며, 런타임은 이를 실제 구현(TTS, 컨트롤러, 로거 등)으로 전달합니다.
이 페이지에서 다루는 내용:
- tool catalog이 저장되는 위치입니다.
- How the annotation pipeline produces tool-call atoms.
- 자신의 도구를 추가하는 방법
도구가 선언되는 위치
두 개의 레이어.
카탈로그 — OpenAI 스타일의 함수 스키마 목록 — 은 각 데이터셋의 meta/info.json["tools"]에 있습니다. 예시:
{
"features": { "...": "..." },
"tools": [
{
"type": "function",
"function": {
"name": "say",
"description": "Speak a short utterance to the user via the TTS executor.",
"parameters": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "The verbatim text to speak."
}
},
"required": ["text"]
}
}
}
]
}dataset 메타데이터 접근자를 통해 읽으세요:
from lerobot.datasets.dataset_metadata import LeRobotDatasetMetadata
meta = LeRobotDatasetMetadata(repo_id="pepijn/super_poulain_final_annotations")
tools = meta.tools # list[dict] — OpenAI tool schemas데이터셋의 info.json에 도구가 선언되어 있지 않으면, meta.tools은 lerobot.datasets.language의 DEFAULT_TOOLS를 반환합니다. 현재 이는 정형화된 say 스키마를 가진 단일 항목 목록입니다. 따라서 주석이 없는 데이터셋과 채팅 템플릿 사용자는 어떤 설정 없이도 계속 작동합니다:
prompt_str = tokenizer.apply_chat_template(
sample["messages"],
tools=meta.tools, # works either way
add_generation_prompt=False,
tokenize=False,
)구현 — 실행 가능한 Python — 은 src/lerobot/tools/ 아래에 위치하며, 도구별로 하나의 파일로 구성됩니다. 런타임 디스패처와 정형화된 say 구현(Kyutai의 pocket-tts를 래핑)은 여기 설명하는 카탈로그 레이어의 일부가 아닙니다. 현재 이 레이어는 스키마 저장소와 DEFAULT_TOOLS 폴백 상수만 제공합니다.
행별 도구 호출
위 카탈로그는 호출할 수 있는 것을 설명합니다. 실제 호출 — 함수 이름과 인자 값 — 은 language_events의 어시스턴트 원자에서 행별로 저장됩니다:
{
"role": "assistant",
"content": null,
"style": null,
"timestamp": 12.4,
"camera": null,
"tool_calls": [
{ "type": "function",
"function": { "name": "say", "arguments": { "text": "On it." } } }
]
}Recipes는 tool_calls_from을 통해 렌더링된 메시지에 이를 삽입합니다:
user_interjection_response:
bindings:
speech: "emitted_at(t, role=assistant, tool_name=say)"
messages:
- { role: user, content: "${task}", stream: high_level }
- {
role: assistant,
content: "${current_plan}",
stream: high_level,
target: true,
tool_calls_from: speech,
}모델의 학습 대상은 계획 텍스트와 그리고 say 도구 호출을 모두 포함하는 하나의 어시스턴트 턴입니다. 추론 시 런타임은 생성된 텍스트를 구조화된 tool_calls로 다시 파싱하여 해당 구현으로 분기합니다.
자체 도구 추가 방법
참고: 아래 단계 2와 3은 런타임 레이어(
src/lerobot/tools/,Tool프로토콜,TOOL_REGISTRY,get_tools(meta))를 설명하며, 이는 현재 제공되는 카탈로그 레이어의 일부가 아닙니다. 해당 모듈은 아직 트리에 존재하지 않습니다. 단계 1만으로도meta.tools를 통해 채팅 템플릿에서 도구를 볼 수 있게 되어 모델이 호출을 생성하도록 학습할 수 있습니다. 추론 시 호출을 실행하려면 런타임 레이어가 필요합니다.
세 단계입니다. 구체적인 예시: 정책이 호출하여 정규 제어 루프 외부에서 추가 관측을 캡처할 수 있는 record_observation 도구입니다.
1단계 — 스키마 선언
meta/info.json["tools"] 아래에 항목을 추가하려면, 어노테이션 파이프라인을 실행하기 전에 디스크에서 파일을 직접 편집하세요(이 항목은 유지됩니다).
{
"tools": [
{ "type": "function", "function": { "name": "say", "...": "..." } },
{
"type": "function",
"function": {
"name": "record_observation",
"description": "Capture a high-resolution still image for the user.",
"parameters": {
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "Short label for the saved image."
}
},
"required": ["label"]
}
}
}
]
}schema는 OpenAI의 function-calling 규약을 정확히 따르므로, chat template가 이를 네이티브로 렌더링할 수 있습니다.
2단계 — 호출 구현
src/lerobot/tools/record_observation.py를 생성합니다:
from .base import Tool
from typing import Any
RECORD_OBSERVATION_SCHEMA: dict[str, Any] = { "...": "..." } # mirrors the JSON above
class RecordObservationTool:
name = "record_observation"
schema = RECORD_OBSERVATION_SCHEMA
def __init__(self, schema: dict | None = None, output_dir: str = "."):
self.output_dir = output_dir
def call(self, arguments: dict) -> str:
label = arguments["label"]
# ... save the latest camera frame to <output_dir>/<label>.png ...
return f"saved {label}.png"도구별로 파일을 분리하면 의존성이 격리됩니다. record_observation은 pillow를 가져올 수 있고, say는 pocket-tts를 가져옵니다. 필요한 도구만 설치하는 사용자는 무거운 전이 의존성을 피할 수 있습니다.
3단계 — 등록
src/lerobot/tools/registry.py에 추가:
from .record_observation import RecordObservationTool
TOOL_REGISTRY["record_observation"] = RecordObservationTool그것으로 끝입니다. 런타임에 get_tools(meta)는 meta.tools에서 각 스키마를 조회하고, 일치하는 등록된 클래스를 인스턴스화한 후, 디스패처가 라우팅할 수 있는 이름 → 인스턴스 딕셔너리를 반환합니다.
구현을 작성하지 않고 도구를 사용하려는 경우(예: 학습 시 chat-template 포맷팅만 수행하는 경우) 1단계만으로도 충분합니다. 모델은 여전히 호출을 생성하도록 학습됩니다. 2단계와 3단계는 추론 시 실제로 호출을 실행해야 할 때만 필요합니다.
Update on GitHub