# Araçlar

LeRobot, politikalar içinde **araç çağrılarını** destekler — asistan mesajları, çalışma zamanının gerçek bir uygulamaya (TTS, denetleyici, kayıt tutucu, …) yönlendirdiği `say(text="OK, starting now")` gibi yapılandırılmış çağrılar üretebilir.

Bu sayfa şunları kapsar:

1. Araç kataloğunun bulunduğu yer.
2. Etiketleme hattının araç çağrısı atomlarını nasıl ürettiği.
3. Kendi aracınızı nasıl eklersiniz.

## Araçların nerede beyan edildiği

İki katman.

**Katalog** — OpenAI tarzı işlev şemalarının listesi — her veri setinde `meta/info.json["tools"]` konumundadır. Örnek:

```json
{
  "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"]
        }
      }
    }
  ]
}
```

Veri seti meta verisi erişimcisi üzerinden okuyun:

```python
from lerobot.datasets.dataset_metadata import LeRobotDatasetMetadata

meta = LeRobotDatasetMetadata(repo_id="pepijn/super_poulain_final_annotations")
tools = meta.tools     # list[dict] — OpenAI tool schemas
```

Veri setinin `info.json` dosyası herhangi bir araç bildirmiyorsa, `meta.tools` `lerobot.datasets.language` modülündeki `DEFAULT_TOOLS` değerini döndürür — şu anda kanonik `say` şemasına sahip tek girişli bir liste. Bu sayede etiketlenmemiş veri setleri ve sohbet şablonu kullanıcıları herhangi bir yapılandırma gerektirmeden çalışmaya devam eder:

```python
prompt_str = tokenizer.apply_chat_template(
    sample["messages"],
    tools=meta.tools,                 # works either way
    add_generation_prompt=False,
    tokenize=False,
)
```

**Uygulamalar** — çalıştırılabilir Python — `src/lerobot/tools/` altında, her araç için bir dosya olarak yer alacak. Çalışma zamanı yönlendirici ve kanonik `say` uygulaması (Kyutai'nin pocket-tts'ini saran) burada açıklanan katalog katmanının bir parçası değildir; bugün bu katman yalnızca şema depolamasını ve `DEFAULT_TOOLS` yedek sabitini içerir.

## Satır başına araç _çağrıları_

Yukarıdaki katalog _neyin çağrılabilir olduğunu_ açıklar. Gerçek _çağrı_ — fonksiyon adı ve argüman değerleri — `language_events` içindeki asistan atomlarında satır bazında saklanır:

```python
{
  "role": "assistant",
  "content": null,
  "style": null,
  "timestamp": 12.4,
  "camera": null,
  "tool_calls": [
    { "type": "function",
      "function": { "name": "say", "arguments": { "text": "On it." } } }
  ]
}
```

Recipes, bunları `tool_calls_from` aracılığıyla işlenmiş mesajlara yerleştirir:

```yaml
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,
      }
```

Modelin eğitim hedefi, hem plan metnini _ve_ `say` araç çağrısını içeren tek bir asistan turudur. Çıkarım sırasında çalışma zamanı, üretilen metni yapılandırılmış `tool_calls` biçimine geri ayrıştırır ve eşleşen uygulamaya yönlendirir.

## Kendi aracınızı nasıl eklersiniz

> **Not:** Aşağıdaki 2. ve 3. adımlar, bugün dağıtılan katalog katmanının bir parçası olmayan çalışma zamanı katmanını (`src/lerobot/tools/`, `Tool` protokolü, `TOOL_REGISTRY`, `get_tools(meta)`) tanımlar; bu modüller henüz ağaçta mevcut değil. Modelin çağrıyı _oluşturmayı_ öğrenebilmesi için aracın sohbet şablonuna `meta.tools` üzerinden görünür hale gelmesi yalnızca 1. adım ile yeterlidir; çağrının çıkarım sırasında çalıştırılması ise çalışma zamanı katmanını gerektirir.

Üç adım. Somut örnek: politikanın düzenli kontrol döngüsünün dışında ek bir gözlem yakalamak için çağırabileceği bir `record_observation` aracı.

### Adım 1 — şemayı tanımlayın

Etiketleme hattını çalıştırmadan _önce_, dosyayı doğrudan disk üzerinde düzenleyerek `meta/info.json["tools"]` altında bir giriş ekleyin (korunacaktır).

```json
{
  "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"]
        }
      }
    }
  ]
}
```

Şema, OpenAI'nin fonksiyon çağırma (function-calling) sözleşmesini tam olarak takip eder, bu sayede sohbet şablonu onu yerel olarak (natively) işleyebilir.

### Adım 2 — çağrıyı uygulayın

`src/lerobot/tools/record_observation.py` dosyasını oluşturun:

```python
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"
```

Araç başına bir dosya, bağımlılıkların izole kalmasını sağlar — `record_observation` `pillow` çekebilirken `say` `pocket-tts` çeker. Yalnızca ihtiyaç duydukları araçları kuran kullanıcılar, ağır dolaylı bağımlılıklardan kaçınır.

### Adım 3 — kaydedin

`src/lerobot/tools/registry.py` dosyasına ekleyin:

```python
from .record_observation import RecordObservationTool

TOOL_REGISTRY["record_observation"] = RecordObservationTool
```

Bu kadar. Çalışma zamanında `get_tools(meta)`, `meta.tools` içindeki her şemayı arar, eşleşen kayıtlı sınıfı örnekler ve yönlendiricinin (dispatcher) yönlendirebileceği bir ad → örnek sözlüğü döndürür.

Bir aracın _uygulamasını yazmadan_ kullanmak istiyorsanız (örneğin yalnızca eğitim zamanı sohbet şablonu biçimlendirmesi için), yalnızca 1. adım yeterlidir — model yine de çağrıyı _üretmeyi_ öğrenir. 2. ve 3. adımlar, çağrının çıkarım sırasında gerçekten _çalıştırılması_ için gereklidir.

