# Webhooks

Webhooks 是 MLOps 相关功能的基础。它们允许你监听特定仓库的新变更，或监听属于特定用户/组织集合的所有仓库（不仅限于你自己的仓库，而是任意仓库）。

您可以使用它们来自动转换模型、构建社区机器人，或为您的模型、数据集、Spaces 和存储桶（以及更多内容）构建 CI/CD。Webhooks 还可以[触发 Jobs](./jobs-webhooks)，以响应仓库事件来自动化计算任务。

Webhooks 的文档如下 – 您也可以浏览我们的 **指南**，其中展示了 Webhooks 的几种可能用例：
- [每当数据集更新时，微调一个新模型（Python）](./webhooks-guide-auto-retrain)
- [使用 LLM API 在 Hub 上创建一个讨论机器人（NodeJS）](./webhooks-guide-discussion-bot)
- [创建元数据质量报告（Python）](./webhooks-guide-metadata-review)
- [使用 Jobs (CLI) 处理存储桶中的新文件](./webhooks-guide-bucket-jobs)
- 还有更多即将推出……

## 创建您的 Webhook

您可以在 Webhooks 的 [设置](https://huggingface.co/settings/webhooks) 中创建新的 Webhook 并编辑现有的 Webhook：

![Settings of an individual webhook](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-settings.png)

Webhooks 可以监控仓库更新、Pull Requests、讨论以及新评论。甚至可以创建一个 Space 来响应你的 Webhooks！

## Webhook 负载

注册 Webhook 后，系统会通过向指定目标 URL 发起 `HTTP POST` 请求来通知您新事件。负载以 JSON 格式编码。

您可以在 Webhook 设置页面的活动选项卡中查看已发送的负载历史记录，也可以重放过去的 Webhook 以便于调试：

![image.png](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-activity.png)

例如，当 Pull Request 被打开时，完整的 payload 如下所示：

```json
{
  "event": {
    "action": "create",
    "scope": "discussion"
  },
  "repo": {
    "type": "model",
    "name": "openai-community/gpt2",
    "id": "621ffdc036468d709f17434d",
    "private": false,
    "url": {
      "web": "https://huggingface.co/openai-community/gpt2",
      "api": "https://huggingface.co/api/models/openai-community/gpt2"
    },
    "owner": {
      "id": "628b753283ef59b5be89e937"
    }
  },
  "discussion": {
    "id": "6399f58518721fdd27fc9ca9",
    "title": "Update co2 emissions",
    "url": {
      "web": "https://huggingface.co/openai-community/gpt2/discussions/19",
      "api": "https://huggingface.co/api/models/openai-community/gpt2/discussions/19"
    },
    "status": "open",
    "author": {
      "id": "61d2f90c3c2083e1c08af22d"
    },
    "num": 19,
    "isPullRequest": true,
    "changes": {
      "base": "refs/heads/main"
    }
  },
  "comment": {
    "id": "6399f58518721fdd27fc9caa",
    "author": {
      "id": "61d2f90c3c2083e1c08af22d"
    },
    "content": "Add co2 emissions information to the model card",
    "hidden": false,
    // Note: when `hidden` is `true`, `content` will be undefined
    "url": {
      "web": "https://huggingface.co/openai-community/gpt2/discussions/19#6399f58518721fdd27fc9caa"
    }
  },
  "webhook": {
    "id": "6390e855e30d9209411de93b",
    "version": 3
  }
}
```

### 事件

顶层属性 `event` 始终会被指定，用于确定事件的性质。

它有两个子属性：`event.action` 和 `event.scope`。

`event.scope` 将是以下值之一：

- `"repo"` - 仓库上的全局事件。关联的 `action` 可能的值： `"create"`、`"delete"`、`"update"`、`"move"`。
- `"repo.content"` - 仓库内容上的事件，例如新的提交或标签。由于新创建的引用/提交，它也会在新的 Pull Request 上触发。对于 Buckets，它在文件被添加或删除时触发，而不是在 Git 引用上触发。关联的 `action` 始终为 `"update"`。
- `"repo.config"` - 配置相关事件：更新 Space 密钥、更新设置、更新 DOI、是否禁用等。关联的 `action` 始终为 `"update"`。
- `"discussion"` - 创建讨论或 Pull Request、更新标题或状态，以及合并。关联的 `action` 的可能取值： `"create"`、`"delete"`、`"update"`。
- `"discussion.comment"` - 创建、更新和隐藏评论。关联的 `action` 的可能取值：`"create"`、`"update"`。

未来可以添加更多作用域。为了处理未知事件，您的 webhook 处理器可以将任何针对更窄作用域的操作视为针对更宽作用域的 `"update"` 操作。

例如，如果未来添加了`"repo.config.dois"`作用域，则具有该作用域的任何事件都可以被您的 webhook 处理器视为对`"repo.config"`作用域的`"update"`操作。

### 仓库

在当前版本的 webhooks 中，顶层属性 `repo` 始终会被指定，因为事件总是可以与某个仓库相关联。例如，考虑以下值：

```json
"repo": {
	"type": "model",
	"name": "some-user/some-repo",
	"id": "6366c000a2abcdf2fd69a080",
	"private": false,
	"url": {
		"web": "https://huggingface.co/some-user/some-repo",
		"api": "https://huggingface.co/api/models/some-user/some-repo"
	},
	"headSha": "c379e821c9c95d613899e8c4343e4bfee2b0c600",
	"owner": {
		"id": "61d2000c3c2083e1c08af22d"
	}
}
```

`repo.headSha` 是仓库 `main` 分支最新提交的 sha。仅当 `event.scope` 以 `"repo"` 开头时才会发送该字段，社区事件（如讨论和评论）以及没有 Git 历史的 bucket 均不会发送。

### 代码更改

在代码变更时，仓库事件会指定顶层属性 `updatedRefs`。它是一个包含已更新引用的数组。以下是一个示例值：

```json
"updatedRefs": [
  {
    "ref": "refs/heads/main",
    "oldSha": "ce9a4674fa833a68d5a73ec355f0ea95eedd60b7",
    "newSha": "575db8b7a51b6f85eb06eee540738584589f131c"
  },
  {
    "ref": "refs/tags/test",
    "oldSha": null,
    "newSha": "575db8b7a51b6f85eb06eee540738584589f131c"
  }
]
```

新创建的引用会将 `oldSha` 设置为 `null`。已删除的引用会将 `newSha` 设置为 `null`。

您可以针对特定拉取请求、新标签或新分支上的新提交做出响应。

### 桶

[Buckets](./storage-buckets) 不是 Git 仓库：它们没有提交、分支或标签。生命周期事件（`create`、`delete`、`move` 以及可见性等配置更新）使用与其他仓库类型相同的 `"repo"` / `"repo.config"` 作用域。

文件更改使用 `"repo.content"`，但负载中有一个 `updatedFiles` 属性，而不是 `updatedRefs`。覆盖现有文件会被报告为 `"add"`。以下是一个示例负载，其中添加了一个文件并删除了另一个文件：

```json
{
  "event": {
    "action": "update",
    "scope": "repo.content"
  },
  "repo": {
    "type": "bucket",
    "name": "some-user/some-bucket",
    "id": "6366c000a2abcdf2fd69a080",
    "private": false,
    "url": {
      "web": "https://huggingface.co/buckets/some-user/some-bucket",
      "api": "https://huggingface.co/api/buckets/some-user/some-bucket"
    },
    "owner": {
      "id": "61d2000c3c2083e1c08af22d"
    }
  },
  "updatedFiles": [
    {
      "path": "data/train.txt",
      "action": "add",
      "xetHash": "55faef2f2f80cd1a087c35b729f228960739441d38073cd5aa4320751e137166",
      "size": 20
    },
    {
      "path": "data/old.txt",
      "action": "delete"
    },
    ...
  ],
  "updatedFilesTruncated": true,
  "webhook": {
    "id": "6390e855e30d9209411de93b",
    "version": 3
  }
}
```

当条目数超过 10,000 时，列表会被截断，并且 `updatedFilesTruncated` 会被设置为 `true`。在这种情况下，请列出存储桶以获取完整信息。

Buckets 没有讨论或 Pull Requests，因此您永远不会收到它们的 `"discussion"` 和 `"discussion.comment"` 事件。

如果您希望客户端直接跟踪存储桶的文件变更，而不是通过回调到您自己的服务器，存储桶还提供了一个[实时跟随流](./storage-buckets#live-follow)。

### 配置更改

当顶层属性 `event.scope` 为 `"repo.config"` 时，会指定 `updatedConfig` 属性。它是一个包含更新后配置的对象的值。以下是一个示例值：

```json
"updatedConfig": {
  "private": false
}
```

当更新后的配置键不被 webhook 支持时，该对象将为空：

```json
"updatedConfig": {}
```

目前仅支持 `private`。如果您希望此处包含更多配置键，请通过 website@huggingface.co 告知我们。

### 讨论和拉取请求

顶层属性 `discussion` 在社区事件（讨论和 Pull Requests）中指定。`discussion.isPullRequest` 属性是一个布尔值，用于指示该讨论是否也是一个 Pull Request（在 Hub 上，PR 是一种特殊类型的讨论）。以下是一个示例值：

```json
"discussion": {
	"id": "639885d811ae2bad2b7ba461",
	"title": "Hello!",
	"url": {
		"web": "https://huggingface.co/some-user/some-repo/discussions/3",
		"api": "https://huggingface.co/api/models/some-user/some-repo/discussions/3"
	},
	"status": "open",
	"author": {
		"id": "61d2000c3c2083e1c08af22d"
	},
	"isPullRequest": true,
	"changes": {
		"base": "refs/heads/main"
	}
	"num": 3
}
```

### 评论

顶层属性 `comment` 在创建（包括创建讨论时）或更新评论时指定。以下是一个示例值：

```json
"comment": {
	"id": "6398872887bfcfb93a306f18",
	"author": {
		"id": "61d2000c3c2083e1c08af22d"
	},
	"content": "This adds an env key",
	"hidden": false,
	"url": {
		"web": "https://huggingface.co/some-user/some-repo/discussions/4#6398872887bfcfb93a306f18"
	}
}
```

## Webhook 密钥

设置 Webhook 密钥有助于确保发送到您的 Webhook 处理程序 URL 的负载确实来自 Hugging Face。

如果你为 Webhook 设置了密钥，它将在每个请求中作为 `X-Webhook-Secret` HTTP 请求头发送。仅支持 ASCII 字符。

> [!TIP]
> 也可以在处理程序 URL 中直接添加密钥。例如，将其设置为查询参数：https://example.com/webhook?secret=XXX。
>
> 如果您的 Webhook 处理程序访问请求的 HTTP 标头较为复杂，这可能会有所帮助。

## 交付与重试

Webhook 负载是异步交付的，通常在 Hub 上发生事件后不久送达。顺序不保证：如果多个事件在相近的时间发生，它们可能会乱序到达。

您的处理程序应使用 `2xx` 状态码确认消息已送达。任何其他状态码都视为送达失败，与连接错误一样：系统会采用退避策略进行重试。如果您的处理速度较慢，请立即返回 `2xx` 状态码，并异步执行后续工作，以免该次送达被判定为失败。

每次交付都有一个唯一的 `Webhook-Id` HTTP 头。失败交付的重试会复用相同的 ID，因此您可以将其视为幂等性密钥，确保每个事件只处理一次。

当向 Webhook 的投递持续失败时，该 Webhook 会被自动暂停，并通过电子邮件通知其所有者。您可以排查问题，并从您的 Webhooks [设置](https://huggingface.co/settings/webhooks)中重新启用它。

## 速率限制

每个 Webhook 在 24 小时内最多可触发 1,000 次。您可以在 Webhook 设置页面的“Activity”标签页中查看使用情况。

如果需要增加 Webhook 的触发次数，请升级到 PRO、Team 或 Enterprise，并发送邮件至 website@huggingface.co 与我们联系。

## 开发您的 Webhooks

如果没有 HTTPS 端点/URL，可以尝试使用用于 webhook 测试的公共工具。这些工具会捕获（catch-all）发送到它们的所有请求，并返回 200 OK 状态码。[Beeceptor](https://beeceptor.com/) 是可用于创建临时 HTTP 端点并查看传入负载（payload）的工具之一。另一个类似的工具是 [Webhook.site](https://webhook.site/)。

此外，在开发过程中，你可以将真实的 Webhook 负载路由到本地机器上运行的代码。这是测试和调试以实现更快集成的绝佳方式。你可以通过将本地主机端口暴露到互联网来实现这一点。为了走这条路，你可以使用 [ngrok](https://ngrok.com/) 或 [localtunnel](https://theboroer.github.io/localtunnel-www/)。

## 调试 Webhooks

您可以轻松找到 Webhook 最近生成的事件。打开 Webhook 的活动选项卡，即可看到最近事件的列表。

![image.png](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/webhook-payload.png)
 
在此，您可以查看生成事件的 HTTP 状态码和负载。此外，您可以点击 `Replay` 按钮来重放这些事件！

注意：更改 Webhook 的目标 URL 或密钥后，重放事件会将负载发送到更新后的 URL。

注意：重放事件会以与原始投递相同的 `Webhook-Id` 发送。

## 常见问题

##### 我可以在组织上定义 Webhook，而不是在用户账户上定义吗？

不，目前尚不支持此功能。

##### 我如何订阅 HF 上的所有事件（或整个仓库类型的事件，例如所有模型的事件）？

目前此功能尚未向最终用户开放，但如果您发送邮件至 website@huggingface.co，我们可以为您开启此功能。

