跳到主要内容

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 中定义的字段筛选符合条件的模型或数据集。

由于此元数据对潜在用户至关重要,确保其填写完整十分必要。在团队或组织中,成员对该 YAML 元数据块的重要性理解程度可能不一。与其由某个成员手动负责审查,不如通过自动化手段辅助完成。当仓库内容发生更新时,我们希望自动生成或更新一份元数据审查报告。对于元数据质量而言,该系统的作用类似于 CI/CD

Metadata review

你也可以在这里查看示例报告。

使用 Hub 客户端库创建元数据审查卡片

huggingface_hub 是一个与 Hub 交互的 Python 库。我们可以使用其中的 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 {}

该函数会返回一个包含仓库元数据的字典(若未定义元数据,则返回空字典)。

{'license': 'afl-3.0'}

创建元数据审查报告

在获取到元数据字典后,我们需要生成一份“审查卡片”。这里,我们假设存在一组希望填写的元数据字段(例如必须填写 license)。我们会统计所需字段的覆盖情况,计算一个百分比得分,表示元数据的完整程度。

由于已经得到元数据字典,可以遍历字典并检查特定键是否存在。若缺失,则将该键的值置为 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":
# [...]

该函数返回一个包含我们期望元数据字段的字典;值要么为实际元数据,要么为 None,表示在 YAML 中缺失。

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

接下来便可生成元数据报告。为简洁起见,这里不贴出完整代码。完整示例可在 Hugging Face Spaces 仓库中找到。

我们编写一个函数生成 Markdown 表格,用于更清晰地展示元数据覆盖情况:

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

再编写一个函数计算得分(所需元数据字段中已填写的比例):

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

最后生成 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 引入的赋值表达式(亦称“海象运算符”)。使用该语法不会影响代码逻辑,但能简化写法。可参考 Real Python 的文章了解更多。

创建 Webhook 以响应 Hub 上的变动

我们已经具备生成元数据审查报告的核心功能,下一步是使用 Webhook 自动响应仓库变更。

在个人资料中创建 Webhook

访问 https://huggingface.co/settings/webhooks 创建 Webhook。

  • 输入若干要监听的目标仓库(通常应限制在你自己或所属组织的仓库)。
  • 设置密钥以提升安全性(可使用密码生成器生成足够随机的字符串)。
  • 目标 URL 暂时可填写占位地址。

Webhook 设置如下:

webhook settings

创建新的 Bot 用户

本指南创建了一个独立用户账号用于发布元数据审查结果。

Bot user account

提示

若你的机器人会在 Hub 上与其他用户互动,请清晰地将账号标注为 “Bot”(见上图)。

创建 Webhook 监听器

需要一个 Webhook 监听程序来接收事件。市面上有很多工具可监听 Webhook(例如 ZapierIFTTT 可以在模型更新时发推文等)。此处我们使用 FastAPI 实现。

FastAPI 是 Python Web 框架,我们可用它创建一个监听 /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 Space 的信息请参考文档

最后,需将 Webhook 设置的 URL 更新为 Space 的地址。可在上下文菜单中选择 “Embed this Space”,然后复制 “Direct URL”。

direct url

获取 URL 后,将其填入 Webhook 设置中的 Webhook URL。完成后,机器人便会在监听的仓库发生变动时自动发布审查报告!

总结与下一步

至此,我们搭建了一个自动化的元数据审查机器人。以下是一些扩展思路:

  • 本例的元数据审查较为基础,你可以加入更复杂的审查规则。
  • 可以利用整个 README.md 进行审查。
  • 可为团队设定一些重要规则,并借助 Webhook 检查这些规则是否被遵守。

如果你使用 Webhook 构建了元数据质量应用,请记得 @davanstrien,我很乐意了解你的成果!