Webhooks
Webhooks는 MLOps 관련 기능의 기반입니다. 특정 저장소 또는 관심 있는 사용자/조직에 속한 모든 저장소에서 새로운 변경 사항을 수신할 수 있습니다. 이 가이드에서는 먼저 Webhooks를 프로그래매틱으로 관리하는 방법을 설명합니다. 그런 다음 huggingface_hub을 활용하여 Webhooks를 수신하는 서버를 만들고 Space에 배포하는 방법을 살펴봅니다.
이 가이드는 Huggingface Hub의 웹훅 개념에 익숙하다고 가정합니다. 웹훅 자체에 대해 더 자세히 알고 싶다면 먼저 이 가이드를 읽어보시기 바랍니다.
Webhook 관리
huggingface_hub을 사용하면 웹훅을 프로그래매틱으로 관리할 수 있습니다. 기존 웹훅을 나열하고, 새 웹훅을 생성하며, 웹훅을 업데이트하거나 활성화, 비활성화, 삭제할 수 있습니다. 이 섹션에서는 Hugging Face Hub의 API 함수를 사용하여 이러한 절차를 안내합니다.
Webhook 만들기
새로운 웹훅을 생성하려면 create_webhook()를 사용하고, 페이로드를 전송할 URL, 감시할 이벤트, 그리고 보안 설정을 위해 선택적으로 도메인과 시크릿을 지정합니다.
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를 전달해야 합니다.
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 payload를 담아 Job을 트리거합니다.
소스 Job의 secrets는 webhook으로 복사되지 않습니다. 트리거된 Job에 secrets(예: HF_TOKEN)가 필요하면 secrets={"HF_TOKEN": "hf_***"}로 전달하세요. update_webhook()을 사용하는 경우 job_id와 secrets를 함께 전달해야 합니다. 나열된 secrets는 저장된 값을 대체하며, 빈 문자열은 secrets를 제거하고, 다른 모든 secrets는 유지됩니다.
Hugging Face Jobs, 사용 가능한 하드웨어(CPU, GPU) 및 UV 스크립트에 대한 자세한 내용은 Jobs 문서를 참조하세요.
Webhooks 나열
구성한 모든 웹훅을 확인하려면 list_webhooks()를 사용하여 목록을 표시할 수 있습니다. 이를 통해 ID, URL, 상태를 검토하는 데 유용합니다.
from huggingface_hub import list_webhooks
# Example: Listing all webhooks
webhooks = list_webhooks()
for webhook in webhooks:
print(webhook)Webhook 업데이트
기존 webhook의 URL이나 모니터링 대상 이벤트와 같은 구성을 변경해야 하는 경우, update_webhook()을 사용하여 업데이트할 수 있습니다.
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 활성화 및 비활성화
웹훅을 삭제하지 않고 일시적으로 비활성화하려는 경우가 있을 수 있습니다. disable_webhook()을 사용하면 이를 수행할 수 있으며, 이후 enable_webhook()을 사용하여 웹훅을 다시 활성화할 수 있습니다.
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 삭제
웹훅이 더 이상 필요하지 않을 경우 delete_webhook()을 사용하여 영구적으로 삭제할 수 있습니다.
from huggingface_hub import delete_webhook
# Example: Deleting a webhook
delete_webhook("your-webhook-id")CLI에서 Webhook 관리
위에서 설명한 모든 작업은 hf 명령줄 인터페이스에서도 사용할 수 있습니다. 이는 스크립팅 및 에이전트 워크플로우에 특히 유용합니다.
# 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 가이드를 참고하세요.
Webhooks 서버
이 가이드 섹션에서 사용할 기본 클래스는 WebhooksServer()입니다. Huggingface Hub에서 웹훅을 수신할 수 있는 서버를 쉽게 구성하기 위한 클래스입니다. 이 서버는 Gradio 앱 기반으로 구축되어 있으며, 사용자에게 지침을 표시하는 UI와 웹훅을 수신하는 API를 제공합니다.
웹훅 서버의 실행 예시를 보려면 Spaces CI Bot을 확인해 보세요. 이는 Space에 PR이 열릴 때 임시 환경을 시작하는 Space입니다.
이것은 실험적 기능입니다. 이는 API를 개선하기 위해 계속 작업 중임을 의미합니다. 사전 통보 없이 향후 호환성이 깨지는 변경 사항이 도입될 수 있습니다.
huggingface_hub의 버전을 요구 사항에 고정하도록 하십시오.
엔드포인트 생성
webhook 엔드포인트를 구현하는 것은 함수를 데코레이팅하는 것만큼 간단합니다. 주요 개념을 설명하기 위해 첫 번째 예시를 살펴보겠습니다:
# 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'로 실행하세요. 다음과 같은 메시지가 표시됩니다:
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_endpoint()로 함수를 장식하면 백그라운드에서 WebhooksServer() 객체가 생성됩니다. 보시는 바와 같이 이 서버는 http://127.0.0.1:7860에서 실행되는 Gradio 앱입니다. 브라우저에서 이 URL을 열면 등록된 웹후크에 대한 설명이 포함된 랜딩 페이지가 표시됩니다.
- Gradio 앱은 내부적으로 FastAPI 서버입니다. 새로운 POST 라우트
/webhooks/trigger_training가 추가되었습니다. 이 라우트는 웹훅을 수신하고 트리거가 발생하면trigger_training함수를 실행합니다. FastAPI는 페이로드를 자동으로 파싱하여 WebhookPayload 객체로 함수에 전달합니다. 이 객체는 웹훅을 트리거한 이벤트에 대한 모든 정보를 포함하는pydantic객체입니다. - Gradio 앱은 인터넷에서 요청을 수신하기 위해 터널도 열었습니다. 여기가 흥미로운 부분입니다: https://huggingface.co/settings/webhooks에서 로컬 머신을 가리키도록 Webhook을 구성할 수 있습니다. 이는 Space에 배포하기 전에 Webhook 서버를 디버깅하고 빠르게 반복 개발하는 데 유용합니다.
- 마지막으로, 로그는 현재 서버가 시크릿으로 보호되지 않고 있음을 알려줍니다. 이는 로컬 디버깅에는 문제가 되지 않지만, 이후를 위해 염두에 두어야 합니다.
기본적으로 서버는 스크립트 실행이 끝날 때 시작됩니다. 노트북에서 실행하는 경우
decorated_function.launch()를 호출하여 서버를 수동으로 시작할 수 있습니다. 고유한 서버가 사용되므로 여러 엔드포인트가 있어도 서버를 한 번만 시작하면 됩니다.
Webhook 구성
이제 웹훅 서버가 실행 중이므로, 메시지를 수신하기 시작하도록 Webhook을 구성해야 합니다. https://huggingface.co/settings/webhooks로 이동하여 “Add a new webhook”을 클릭하고 Webhook을 구성하세요. 감시할 대상 저장소와 Webhook URL을 설정합니다. 여기서는 https://1fadb0f52d8bf825fc.gradio.live/webhooks/trigger_training입니다.

그리고 끝입니다! 이제 대상 저장소를 업데이트(예: 커밋을 push)하여 해당 webhook을 트리거할 수 있습니다. Webhook의 Activity 탭을 확인하여 트리거된 이벤트를 살펴보세요. 이제 작동하는 설정을 갖추었으므로 테스트하고 빠르게 반복할 수 있습니다. 코드를 수정하고 서버를 다시 시작하면 공개 URL이 변경될 수 있습니다. 필요 시 Hub에서 webhook 구성을 업데이트하세요.
Space에 배포
작동하는 webhook 서버를 갖추셨으니, 이제 이를 Space에 배포하는 것이 목표입니다. https://huggingface.co/new-space로 이동하여 Space를 생성하세요. 이름을 지정하고 Gradio SDK를 선택한 후 “Create Space”를 클릭합니다. 코드를 app.py라는 파일로 Space에 업로드하세요. Space가 자동으로 시작됩니다. Spaces에 대한 자세한 내용은 이 가이드를 참고하세요.
웹훅 서버가 이제 공개 Space에서 실행되고 있습니다. 대부분의 경우, 시크릿으로 이를 보호하는 것이 좋습니다. Space 설정 > “Repository secrets” 섹션 > “Add a secret”으로 이동하여 WEBHOOK_SECRET 환경 변수를 원하는 값으로 설정하세요. Webhooks settings로 돌아가서 웹훅 구성에 시크릿을 설정합니다. 이제 올바른 시크릿을 가진 요청만 서버에 의해 허용됩니다.
이제 준비가 끝났습니다! 이제 Space가 Hub에서 웹훅을 수신할 수 있습니다. Space를 무료 ‘cpu-basic’ 하드웨어에서 실행하는 경우, 48시간 동안 비활성 상태가 되면 종료됩니다. 영구적인 Space가 필요하면 업그레이드된 하드웨어로 설정하는 것을 고려해 보세요.
고급 사용
위 가이드에서는 WebhooksServer()를 설정하는 가장 빠른 방법을 설명했습니다. 이 섹션에서는 이를 더 자세히 커스터마이징하는 방법을 살펴보겠습니다.
여러 엔드포인트
같은 서버에 여러 엔드포인트를 등록할 수 있습니다. 예를 들어, 학습 작업을 트리거하는 엔드포인트 하나와 모델 평가를 트리거하는 엔드포인트 하나를 두고 싶을 수 있습니다. 여러 @webhook_endpoint 데코레이터를 추가하여 이를 수행할 수 있습니다:
# 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
...두 개의 엔드포인트를 생성합니다:
(...) 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() 객체를 직접 생성할 수도 있습니다. 이는 서버의 랜딩 페이지를 커스터마이즈하려는 경우에 유용합니다. 기본값을 덮어쓰는 Gradio UI를 전달하여 이를 수행할 수 있습니다. 예를 들어, 사용자를 위한 지침을 추가하거나 웹훅을 수동으로 트리거하기 위한 양식을 추가할 수 있습니다. WebhooksServer()를 생성할 때 add_webhook() 데코레이터를 사용하여 새로운 웹훅을 등록할 수 있습니다.
다음은 완전한 예시입니다:
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()- Gradio blocks를 사용하여 사용자 정의 UI를 정의합니다. 이 UI는 서버의 랜딩 페이지에 표시됩니다.
- 커스텀 UI와 시크릿을 사용하여 WebhooksServer() 객체를 생성합니다. 시크릿은 선택 사항이며
WEBHOOK_SECRET환경 변수로 설정할 수 있습니다. - 명시적인 이름을 지정하여 웹훅을 등록합니다. 이렇게 하면
/webhooks/say_hello에 엔드포인트가 생성됩니다. - 암시적 이름으로 웹훅을 등록합니다. 이렇게 하면
/webhooks/goodbye에 엔드포인트가 생성됩니다. - 서버를 시작합니다. 스크립트 끝에서 서버가 자동으로 시작되므로 이 단계는 선택 사항입니다.