# Webhooks

WebhooksはMLOps関連の機能の基盤です。特定のリポジトリ、またはフォローしたい特定のユーザー/組織に属するすべてのリポジトリでの変更を監視できます。本ガイドでは、まずWebhookをプログラムで管理する方法を説明します。その後、`huggingface_hub`を活用してWebhookを監視するサーバーを作成し、Spaceにデプロイする方法を確認します。

このガイドでは、Huggingface Hub の Webhook の概念に精通していることを前提としています。Webhook 自体について詳しく知るには、まずこの [ガイド](https://huggingface.co/docs/hub/webhooks) をお読みください。

## Webhookの管理

`huggingface_hub` を使用すると、Webhook をプログラムで管理できます。既存の Webhook を一覧表示し、新しい Webhook を作成し、更新、有効化、無効化、削除を行うことができます。このセクションでは、Hugging Face Hub の API 関数を用いた手順について説明します。

### Webhookの作成

新しいWebhookを作成するには、[create_webhook()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.create_webhook)を使用し、ペイロードを送信するURL、監視するイベント、およびセキュリティのためにオプションでドメインとシークレットを指定します。

```python
from huggingface_hub import create_webhook

# Example: Creating a webhook
webhook = create_webhook(
    url="https://webhook.site/your-custom-url",
    watched=[{"type": "user", "name": "your-username"}, {"type": "org", "name": "your-org-name"}],
    domains=["repo", "discussion"],
    secret="your-secret"
)
```

Webhookは、ペイロードをURLに送信する代わりに、Hugging faceのインフラストラクチャ上でJobを実行するトリガーとしても機能します。この場合、ソースとなるJobのIDを渡す必要があります。

```python
from huggingface_hub import create_webhook

# Example: Creating a webhook that triggers a Job
webhook = create_webhook(
    job_id=job_id,
    watched=[{"type": "user", "name": "your-username"}, {"type": "org", "name": "your-org-name"}],
    domains=["repo", "discussion"],
    secret="your-secret"
)
```

Webhookは、環境変数`WEBHOOK_PAYLOAD`にWebhookペイロードを含む形でJobをトリガーします。ソースJobのシークレットはWebhookにコピーされません。トリガーされたJobがシークレット（例: `HF_TOKEN`）を必要とする場合は、`secrets={"HF_TOKEN": "hf_***"}`で渡してください。[update_webhook()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.update_webhook)を使用する場合は、`secrets`とともに`job_id`を渡す必要があります。リストされたシークレットは保存された値を置き換え、空の文字列はシークレットを削除し、その他のすべてのシークレットは保持されます。Hugging Face Jobs、利用可能なハードウェア（CPU、GPU）、およびUVスクリプトの詳細については、[Jobsのドキュメント](./jobs)を参照してください。

### Webhookのリスト表示

設定済みのすべてのWebhookを確認するには、[list_webhooks()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.list_webhooks)で一覧表示できます。これにより、ID、URL、ステータスをレビューするのに役立ちます。

```python
from huggingface_hub import list_webhooks

# Example: Listing all webhooks
webhooks = list_webhooks()
for webhook in webhooks:
    print(webhook)
```

### Webhookの更新

既存のWebhookのURLや監視対象イベントなどの設定を変更する必要がある場合は、[update_webhook()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.update_webhook)を使用して更新できます。

```python
from huggingface_hub import update_webhook

# Example: Updating a webhook
updated_webhook = update_webhook(
    webhook_id="your-webhook-id",
    url="https://new.webhook.site/url",
    watched=[{"type": "user", "name": "new-username"}],
    domains=["repo"]
)
```

### Webhookの有効化と無効化

Webhookを削除せずに一時的に無効にしたい場合があります。これは[disable_webhook()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.disable_webhook)を使用して行い、後で[enable_webhook()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.enable_webhook)によって再度有効にできます。

```python
from huggingface_hub import enable_webhook, disable_webhook

# Example: Enabling a webhook
enabled_webhook = enable_webhook("your-webhook-id")
print("Enabled:", enabled_webhook)

# Example: Disabling a webhook
disabled_webhook = disable_webhook("your-webhook-id")
print("Disabled:", disabled_webhook)
```

### Webhookの削除

Webhookが不要になった場合、[delete_webhook()](/docs/huggingface_hub/main/ja/package_reference/hf_api#huggingface_hub.HfApi.delete_webhook)を使用して恒久的に削除できます。

```python
from huggingface_hub import delete_webhook

# Example: Deleting a webhook
delete_webhook("your-webhook-id")
```

### CLIからのWebhookの管理

上記のすべての操作は、`hf` コマンドラインインターフェースからも利用できます。スクリプトやエージェント型ワークフローにおいて特に便利です。

```bash
# List all webhooks
>>> hf webhooks ls

# Get details about a specific webhook
>>> hf webhooks info <webhook_id>

# Create a webhook that pings a URL
>>> hf webhooks create --url https://example.com/hook --watch model:bert-base-uncased --domain repo

# Create a webhook that triggers a Job
>>> hf webhooks create --job-id <job_id> --watch user:julien-c

# Create a webhook that triggers a Job with your HF token as a secret
>>> hf webhooks create --job-id <job_id> --watch bucket:my-org/my-bucket --secrets HF_TOKEN

# Update an existing webhook
>>> hf webhooks update <webhook_id> --url https://new-url.com/hook --watch model:bert-base-uncased --domain repo

# Enable / disable a webhook
>>> hf webhooks enable <webhook_id>
>>> hf webhooks disable <webhook_id>

# Delete a webhook (with confirmation prompt)
>>> hf webhooks delete <webhook_id>
```

`--watch` オプションは `type:name` という形式を使用します。ここで type は `model`、`dataset`、`space`、`org`、または `user` のいずれかです。複数回指定することで、複数のアイテムを監視できます。すべてのオプションの一覧については、`hf webhooks <command> --help` を実行してください。詳細については、[CLI ガイド](./cli#hf-webhooks)を参照してください。

## Webhooks サーバー

このガイドのセクションで使用するベースクラスは[WebhooksServer()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhooksServer)です。これは、Huggingface HubからのWebhookを受信できるサーバーを簡単に設定するためのクラスです。サーバーは[Gradio](https://gradio.app/)アプリに基づいており、あなたやユーザーへの手順を表示するためのUIと、WebhookをリッスンするためのAPIを備えています。

> [!TIP]
> Webhookサーバーの動作例を確認するには、[Spaces CI Bot](https://huggingface.co/spaces/spaces-ci-bot/webhook)をご覧ください。これは、Spaceに対してPRが作成された際にエフェメラル環境を起動するSpaceです。

> [!WARNING]
> これは[実験的な機能](../package_reference/environment_variables#hfhubdisableexperimentalwarning)です。つまり、APIの改善を継続的に進めている段階です。事前の通知なしに、将来破壊的変更が導入される可能性があります。`huggingface_hub`のバージョンをrequirementsに固定してください。

### エンドポイントを作成する

Webhookエンドポイントの実装は、関数にデコレータを付与するだけで済みます。主要な概念を説明するために、まず最初の例を見てみましょう：

```python
# app.py
from huggingface_hub import webhook_endpoint, WebhookPayload

@webhook_endpoint
async def trigger_training(payload: WebhookPayload) -> None:
    if payload.repo.type == "dataset" and payload.event.action == "update":
        # Trigger a training job if a dataset is updated
        ...
```

このスニペットを`'app.py'`という名前のファイルに保存し、`'python app.py'`で実行してください。次のようなメッセージが表示されるはずです:

```text
Webhook secret is not defined. This means your webhook endpoints will be open to everyone.
To add a secret, set `WEBHOOK_SECRET` as environment variable or pass it at initialization:
        `app = WebhooksServer(webhook_secret='my_secret', ...)`
For more details about webhook secrets, please refer to https://huggingface.co/docs/hub/webhooks#webhook-secret.
Running on local URL:  http://127.0.0.1:7860
Running on public URL: https://1fadb0f52d8bf825fc.gradio.live

This share link expires in 72 hours. For free permanent hosting and GPU upgrades (NEW!), check out Spaces: https://huggingface.co/spaces

Webhooks are correctly setup and ready to use:
  - POST https://1fadb0f52d8bf825fc.gradio.live/webhooks/trigger_training
Go to https://huggingface.co/settings/webhooks to setup your webhooks.
```

お見事！Webhookサーバーを起動しました！何が起きたのかを詳しく見ていきましょう：

1. 関数を[webhook_endpoint()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.webhook_endpoint)でデコレートすると、バックグラウンドで[WebhooksServer()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhooksServer)オブジェクトが作成されます。
ご覧のとおり、このサーバーはhttp://127.0.0.1:7860で実行されているGradioアプリです。このURLをブラウザで開くと、登録されたWebhookに関する説明が記載されたランディングページが表示されます。
2. Gradio アプリは、内部では FastAPI サーバーとして動作します。新しい POST ルート `/webhooks/trigger_training` が追加されました。
これは、Webhookをリッスンし、トリガーされた際に`trigger_training`関数を実行するルートです。FastAPIはペイロードを自動的にパースし、[WebhookPayload](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhookPayload)オブジェクトとして関数に渡します。これは、Webhookをトリガーしたイベントに関するすべての情報を含む`pydantic`オブジェクトです。
3. Gradio アプリは、インターネットからのリクエストを受信するためにトンネルも開いていました。ここが興味深い部分です。
https://huggingface.co/settings/webhooks で、ローカルマシンを指す Webhook を設定します。これにより、Webhook サーバーのデバッグや、Space へのデプロイ前に迅速な反復開発が可能になります。
4. 最後に、ログには、サーバーが現在シークレットによって保護されていないことも示されています。これは
ローカルでのデバッグですが、後で念頭に置いておく必要があります。

> [!WARNING]
> デフォルトでは、スクリプトの末尾でサーバーが起動します。ノートブックで実行している場合は、`decorated_function.launch()`を呼び出すことでサーバーを手動で起動できます。ユニークなサーバーが使用されるため、エンドポイントが複数あっても、サーバーは一度だけ起動すれば十分です。

### Webhookを設定する

Webhookサーバーが実行できるようになったので、次はメッセージの受信を開始するためにWebhookを設定します。https://huggingface.co/settings/webhooks に移動し、「Add a new webhook」をクリックしてWebhookを設定してください。監視対象のリポジトリとWebhook URLを設定します。ここでは`https://1fadb0f52d8bf825fc.gradio.live/webhooks/trigger_training`です。

これで完了です! 対象リポジトリを更新する(例: コミットをプッシュする)ことで、そのWebhookをトリガーできます。WebhookのActivityタブを確認すると、トリガーされたイベントが表示されます。動作するセットアップが整ったので、テストと迅速な反復開発を行えます。コードを変更してサーバーを再起動すると、パブリックURLが変わる可能性があります。必要に応じて、Hub上のWebhook設定を更新してください。

### スペースにデプロイ

動作する Webhook サーバーが用意できたので、次は Space にデプロイします。https://huggingface.co/new-space にアクセスして Space を作成してください。名前を付け、Gradio SDK を選択し、「Create Space」をクリックします。コードを `app.py` というファイル名で Space にアップロードしてください。Space は自動的に起動します。Spaces に関する詳細は、この [ガイド](https://huggingface.co/docs/hub/spaces-overview) を参照してください。

Webhookサーバーは現在、パブリックなSpaceで実行されています。ほとんどの場合、シークレットで保護することをお勧めします。Spaceの設定 > 「Repository secrets」セクション > 「Add a secret」に移動します。`WEBHOOK_SECRET`環境変数に、任意の値を設定してください。[Webhooks settings](https://huggingface.co/settings/webhooks)に戻り、Webhookの設定でシークレットを設定します。これにより、サーバーは正しいシークレットを持つリクエストのみを受け付けるようになります。

これで完了です! SpaceはHubからのWebhookを受信する準備が整いました。なお、Spaceを無料の'cpu-basic'ハードウェアで実行する場合、48時間の非アクティブ状態後にシャットダウンされます。永続的なSpaceが必要な場合は、[アップグレードされたハードウェア](https://huggingface.co/docs/hub/spaces-gpus#hardware-specs)に設定することを検討してください。

### 高度な使用方法

上記のガイドでは、[WebhooksServer()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhooksServer)をセットアップする最も素早い方法について説明しました。このセクションでは、さらにカスタマイズする方法を見ていきます。

#### 複数のエンドポイント

同じサーバーに複数のエンドポイントを登録できます。例えば、トレーニングジョブをトリガーするエンドポイントと、モデル評価をトリガーするエンドポイントをそれぞれ用意したい場合があります。これは、複数の`@webhook_endpoint`デコレーターを追加することで実現できます。

```python
# app.py
from huggingface_hub import webhook_endpoint, WebhookPayload

@webhook_endpoint
async def trigger_training(payload: WebhookPayload) -> None:
    if payload.repo.type == "dataset" and payload.event.action == "update":
        # Trigger a training job if a dataset is updated
        ...

@webhook_endpoint
async def trigger_evaluation(payload: WebhookPayload) -> None:
    if payload.repo.type == "model" and payload.event.action == "update":
        # Trigger an evaluation job if a model is updated
        ...
```

これにより、2つのエンドポイントが作成されます:

```text
(...)
Webhooks are correctly setup and ready to use:
  - POST https://1fadb0f52d8bf825fc.gradio.live/webhooks/trigger_training
  - POST https://1fadb0f52d8bf825fc.gradio.live/webhooks/trigger_evaluation
```

#### カスタムサーバー

より柔軟性を高めるには、[WebhooksServer()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhooksServer)オブジェクトを直接作成することもできます。これは、サーバーのランディングページをカスタマイズしたい場合に便利です。[Gradio UI](https://gradio.app/docs/#blocks)を渡すことで、デフォルトのUIを上書きできます。例えば、ユーザー向けの説明を追加したり、Webhookを手動でトリガーするためのフォームを追加したりできます。[WebhooksServer()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhooksServer)を作成する際、`add_webhook()`デコレーターを使用して新しいWebhookを登録できます。

以下は完全な例です:

```python
import gradio as gr
from fastapi import Request
from huggingface_hub import WebhooksServer, WebhookPayload

# 1. Define  UI
with gr.Blocks() as ui:
    ...

# 2. Create WebhooksServer with custom UI and secret
app = WebhooksServer(ui=ui, webhook_secret="my_secret_key")

# 3. Register webhook with explicit name
@app.add_webhook("/say_hello")
async def hello(payload: WebhookPayload):
    return {"message": "hello"}

# 4. Register webhook with implicit name
@app.add_webhook
async def goodbye(payload: WebhookPayload):
    return {"message": "goodbye"}

# 5. Start server (optional)
app.launch()
```

1. Gradio blocksを使用してカスタムUIを定義します。このUIは、サーバーのランディングページに表示されます。
2. カスタムUIとシークレットを指定して[WebhooksServer()](/docs/huggingface_hub/main/ja/package_reference/webhooks_server#huggingface_hub.WebhooksServer)オブジェクトを作成します。シークレットは任意であり、以下で設定できます
環境変数`WEBHOOK_SECRET`
3. 明示的な名前を指定してWebhookを登録します。これにより、`/webhooks/say_hello`にエンドポイントが作成されます。
4. 暗黙的な名前でWebhookを登録します。これにより、`/webhooks/goodbye`にエンドポイントが作成されます。
5. サーバーを起動します。これはオプションです。スクリプトの末尾でサーバーが自動的に起動されるためです。

