Hub documentation

Webhooks

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Webhooks

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

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

Webhooks 的文档如下 – 您也可以浏览我们的 指南,其中展示了 Webhooks 的几种可能用例:

创建您的 Webhook

您可以在 Webhooks 的 设置 中创建新的 Webhook 并编辑现有的 Webhook:

Settings of an individual webhook

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

Webhook 负载

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

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

image.png

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

{
  "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 始终会被指定,因为事件总是可以与某个仓库相关联。例如,考虑以下值:

"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。它是一个包含已更新引用的数组。以下是一个示例值:

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

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

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

桶

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

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

{
  "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" 事件。

如果您希望客户端直接跟踪存储桶的文件变更,而不是通过回调到您自己的服务器,存储桶还提供了一个实时跟随流。

配置更改

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

"updatedConfig": {
  "private": false
}

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

"updatedConfig": {}

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

讨论和拉取请求

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

"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 在创建(包括创建讨论时)或更新评论时指定。以下是一个示例值:

"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 字符。

也可以直接在处理程序 URL 中添加密钥。例如,将其设置为查询参数:https://example.com/webhook?secret=XXX。

如果您的 Webhook 处理程序访问请求的 HTTP 标头较为复杂,这可能会有所帮助。

交付与重试

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

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

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

当向 Webhook 的投递持续失败时,该 Webhook 会被自动暂停,并通过电子邮件通知其所有者。您可以排查问题,并从您的 Webhooks 设置中重新启用它。

速率限制

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

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

开发您的 Webhooks

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

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

调试 Webhooks

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

image.png

在此,您可以查看生成事件的 HTTP 状态码和负载。此外,您可以点击 Replay 按钮来重放这些事件!

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

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

常见问题

我可以在组织上定义 Webhook,而不是在用户账户上定义吗?

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

我如何订阅 HF 上的所有事件(或整个仓库类型的事件,例如所有模型的事件)?

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

Update on GitHub