Hugging Face's logo
加入 Hugging Face 社区

并获得增强文档体验

开始使用

Webhook 指南:为模型和数据集设置自动元数据质量审查

Webhook 现已公开可用!

本指南将引导您创建一个系统,该系统可以对 Hub 上用户或组织模型或数据集的更改做出反应,并为更改的存储库创建“元数据审查”。

我们正在构建什么以及为什么?

在我们深入探讨此特定工作流程中涉及的技术细节之前,我们将快速概述我们正在创建的内容以及原因。

模型卡片数据集卡片 是记录机器学习模型和数据集的基本工具。Hugging Face Hub 使用包含 YAML 标头块的 README.md 文件来生成模型和数据集卡片。此 YAML 部分定义了与模型或数据集相关的元数据。例如

---
language: 
  - "List of ISO 639-1 code for your language"
  - lang1
  - lang2
tags:
- tag1
- tag2
license: "any valid license identifier"
datasets:
- dataset1
---

此元数据包含有关模型或数据集的基本信息,供潜在用户使用。例如,许可证定义了可以使用模型或数据集的条款。Hub 用户还可以使用 YAML 元数据中定义的字段作为筛选器,以识别符合特定条件的模型或数据集。

由于此块中定义的元数据对于我们模型和数据集的潜在用户至关重要,因此我们必须完成此部分。在团队或组织环境中,将模型和数据集推送到 Hub 的用户对此 YAML 元数据块的重要性可能了解程度不同。虽然团队中的某个人可以承担审查此元数据的责任,但我们也可以进行一些自动化操作来帮助我们解决此问题。结果将是在 Hub 上存储库发生更改时自动发布或更新的元数据审查报告。对于我们的元数据质量,此系统的工作方式类似于 CI/CD

Metadata review

您还可以找到一个示例审查 此处

使用 Hub 客户端库创建模型审查卡片

huggingface_hub 是一个 Python 库,允许您与 Hub 交互。我们可以使用此库从 Hub 下载模型和数据集卡片,使用 DatasetCard.loadModelCard.load 方法。特别是,我们将使用这些方法加载一个 Python 字典,其中包含在模型或数据集卡片的 YAML 中定义的元数据。我们将创建一个小的 Python 函数来包装这些方法并进行一些异常处理。

from huggingface_hub import DatasetCard, ModelCard
from huggingface_hub.utils import EntryNotFoundError 

def load_repo_card_metadata(repo_type, repo_name):
    if repo_type == "dataset":
        try:
            return DatasetCard.load(repo_name).data.to_dict()
        except EntryNotFoundError:
            return {}
    if repo_type == "model":
        try:
            return ModelCard.load(repo_name).data.to_dict()
        except EntryNotFoundError:
            return {}

此函数将返回一个 Python 字典,其中包含与存储库关联的元数据(如果元数据不存在,则返回一个空字典)。

{'license': 'afl-3.0'}

创建我们的元数据审查报告

一旦我们拥有一个包含与存储库关联的元数据的 Python 字典,我们将为我们的元数据审查创建一个“成绩单”。在此特定实例中,我们将通过定义一些我们希望具有值的元数据字段来审查我们的元数据。例如,我们可能希望确保始终已填写 license 字段。为了评估我们的元数据,我们将计算所需字段中存在哪些元数据字段,并根据我们希望看到值的必需元数据字段的覆盖率返回百分比分数。

由于我们有一个包含元数据的 Python 字典,因此我们可以循环遍历此字典以检查我们所需的键是否存在。如果缺少所需的元数据字段(字典中的一个键),我们将将其值分配为 None

def create_metadata_key_dict(card_data, repo_type: str):
    shared_keys = ["tags", "license"]
    if repo_type == "model":
        model_keys = ["library_name", "datasets", "metrics", "co2", "pipeline_tag"]
        shared_keys.extend(model_keys)
        keys = shared_keys
        return {key: card_data.get(key) for key in keys}
    if repo_type == "dataset":
        # [...]

此函数将返回一个字典,其中包含表示我们模型或数据集所需的元数据字段的键。字典值将包含为此字段输入的元数据,或者如果 YAML 中缺少该元数据字段,则包含 None

{'tags': None,
 'license': 'afl-3.0',
 'library_name': None,
 'datasets': None,
 'metrics': None,
 'co2': None,
 'pipeline_tag': None}

一旦我们有了这个字典,我们就可以创建我们的元数据报告。为简洁起见,我们不会在此处包含完整的代码,但此 Webhook 的 Hugging Face Spaces 存储库 包含完整代码。

我们创建一个函数,该函数创建一个 Markdown 表格,该表格会生成我们元数据覆盖率字典中数据的更漂亮的版本。

def create_metadata_breakdown_table(desired_metadata_dictionary):
    # [...]
    return tabulate(
        table_data, tablefmt="github", headers=("Metadata Field", "Provided Value")
    )

我们还有一个 Python 函数生成分数(表示存在的所需元数据字段的百分比)

def calculate_grade(desired_metadata_dictionary):
    # [...]
    return round(score, 2)

以及一个 Python 函数为我们的元数据审查创建 Markdown 报告。此报告包含分数和元数据表格,以及一些有关报告内容的说明。

def create_markdown_report(
    desired_metadata_dictionary, repo_name, repo_type, score, update: bool = False
):
    # [...]
    return report

如何自动发布审查?

我们现在有了 Markdown 格式的元数据审查报告。我们将使用 huggingface_hub 库发布此审查。我们定义了一个函数,该函数取回从 Hub 收到的 Webhook 数据,解析数据并创建元数据报告。根据之前是否创建过报告,该函数会创建新报告或将新问题发布到现有元数据审查线程。

def create_or_update_report(data):
    if parsed_post := parse_webhook_post(data):
        repo_type, repo_name = parsed_post
    else:
        return Response("Unable to parse webhook data", status_code=400)
    # [...]
    return True
`:=` 是 Python 3.8 版本中添加的赋值表达式运算符(在口语中被称为海象运算符)的语法。人们对这种语法褒贬不一,如果你不使用它,它不会改变 Python 代码的执行方式。你可以在这篇 [Real Python 文章](https://realpython.com/python-walrus-operator/) 中了解更多关于此运算符的信息。

创建 Webhook 以响应 Hub 上的变化

我们现在已经拥有了为模型或数据集创建元数据审查报告的核心功能。下一步是使用 Webhook 自动响应更改。

在您的用户资料中创建 Webhook

首先,通过访问 https://huggingface.co/settings/webhooks 创建您的 Webhook。

  • 输入一些您的 Webhook 将监听的目标存储库(您可能希望将其限制在您自己的存储库或您所属组织的存储库中)。
  • 输入一个密钥以提高 Webhook 的安全性(如果您不知道为此选择什么,您可能希望使用 密码生成器 为您的密钥生成一个足够长的随机字符串)。
  • 现在我们可以为 `Webhook URL` 参数传递一个虚拟 URL。

您的 Webhook 将如下所示

webhook settings

创建新的 Bot 用户资料

本指南创建了一个单独的用户帐户,该帐户将发布元数据审查。

Bot user account

在创建将与 Hub 上其他用户交互的机器人时,我们要求您将帐户明确标记为“Bot”(请参阅个人资料屏幕截图)。

创建 Webhook 监听器

我们现在需要某种方法来监听 Webhook 事件。您可以使用许多可能的工具来监听 Webhook 事件。许多现有的服务,如 ZapierIFTTT,可以使用 Webhook 触发操作(例如,它们可以在每次更新模型时发布一条推文)。在本例中,我们将使用 FastAPI 实现我们的 Webhook 监听器。

FastAPI 是一个 Python Web 框架。我们将使用 FastAPI 创建一个 Webhook 监听器。特别是,我们需要实现一个在 `/webhook` 上接受 `POST` 请求的路由。为了进行身份验证,我们将比较 `X-Webhook-Secret` 标头与可以传递给我们的 Docker 容器在运行时 的 `WEBHOOK_SECRET` 密钥。

from fastapi import FastAPI, Request, Response
import os

KEY = os.environ.get("WEBHOOK_SECRET")

app = FastAPI()

@app.post("/webhook")
async def webhook(request: Request):
    if request.method == "POST":
        if request.headers.get("X-Webhook-Secret") != KEY:
            return Response("Invalid secret", status_code=401)
        data = await request.json()
        result = create_or_update_report(data)
        return "Webhook received!" if result else result

上述函数将接收 Webhook 事件并为已更改的存储库创建或更新元数据审查报告。

使用 Spaces 部署我们的 Webhook 应用

我们的 main.py 文件包含我们 Webhook 应用所需的所有代码。为了部署它,我们将使用一个 Space

对于我们的 Space,我们将使用 Docker 来运行我们的应用。 Dockerfile 复制我们的应用文件,安装所需的依赖项,并运行应用程序。为了填充 `KEY` 变量,我们还将为我们的 Space 设置一个 `WEBHOOK_SECRET` 密钥,该密钥与我们之前生成的密钥相同。您可以在 此处 阅读更多关于 Docker Spaces 的信息。

最后,我们需要将 Webhook 设置中的 URL 更新为我们 Space 的 URL。我们可以从上下文菜单中获取我们 Space 的“直接 URL”。单击“嵌入此 Space”并复制“直接 URL”。

direct url

获得此 URL 后,我们可以将其传递给 Webhook 设置中的 `Webhook URL` 参数。现在,我们的机器人应该在监视的存储库发生更改时开始发布审查!

结论和后续步骤

我们现在拥有了一个自动元数据审查机器人!以下是一些关于如何在此指南的基础上进行构建的想法

  • 我们的机器人进行的元数据审查相对粗略;您可以添加更复杂的规则来审查元数据。
  • 您可以使用完整的 `README.md` 文件来进行审查。
  • 您可能希望定义对您的组织特别重要的“规则”,并使用 Webhook 检查这些规则是否得到遵守。

如果您使用 Webhook 构建了一个元数据质量应用,请标记我 @davanstrien;我很想知道!

< > 更新 在 GitHub 上