Hub documentation

Guía de Webhooks: Configuración de una revisión automática de la calidad de los metadatos para modelos y conjuntos de datos

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Guía de Webhooks: Configuración de una revisión automática de la calidad de los metadatos para modelos y conjuntos de datos

Esta guía le guiará a través del proceso de creación de un sistema que reacciona a los cambios en los modelos o conjuntos de datos de un usuario u organización en el Hub y crea una 'revisión de metadatos' para el repositorio modificado.

¿Qué estamos construyendo y por qué?

Antes de profundizar en los detalles técnicos de este flujo de trabajo en particular, repasaremos brevemente qué estamos creando y por qué.

Fichas de modelos y fichas de conjuntos de datos son herramientas esenciales para documentar modelos y conjuntos de datos de aprendizaje automático. El Hugging Face Hub utiliza un archivo README.md que contiene un bloque de encabezado YAML para generar las fichas de modelos y conjuntos de datos. Esta sección YAML define los metadatos relacionados con el modelo o el conjunto de datos. Por ejemplo:

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

Esta metadatos contiene información esencial sobre tu modelo o conjunto de datos para los usuarios potenciales. La licencia, por ejemplo, define los términos bajo los cuales se puede utilizar un modelo o conjunto de datos. Los usuarios del Hub también pueden utilizar los campos definidos en los metadatos YAML como filtros para identificar modelos o conjuntos de datos que cumplan con criterios específicos.

Dado que los metadatos definidos en este bloque son esenciales para los posibles usuarios de nuestros modelos y conjuntos de datos, es importante que completemos esta sección. En un entorno de equipo u organización, los usuarios que suben modelos y conjuntos de datos al Hub pueden tener distintos niveles de familiaridad con la importancia de este bloque de metadatos YAML. Si bien alguien en el equipo podría asumir la responsabilidad de revisar estos metadatos, también es posible implementar cierta automatización para ayudarnos con este problema. El resultado será un informe de revisión de metadatos que se publicará o actualizará automáticamente cuando un repositorio en el Hub cambie. Para la calidad de nuestros metadatos, este sistema funciona de manera similar a CI/CD.

Metadata review

También puedes encontrar un ejemplo de revisión aquí.

Usar la biblioteca de cliente de Hub para crear una tarjeta de revisión de modelo

La biblioteca huggingface_hub es una biblioteca de Python que permite interactuar con el Hub. Podemos usar esta biblioteca para descargar tarjetas de modelos y conjuntos de datos del Hub mediante los métodos DatasetCard.load o ModelCard.load. En particular, usaremos estos métodos para cargar un diccionario de Python que contiene los metadatos definidos en el YAML de nuestra tarjeta de modelo o conjunto de datos. Crearemos una pequeña función de Python para encapsular estos métodos y realizar un manejo de excepciones.

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 {}

Esta función devolverá un diccionario de Python que contiene los metadatos asociados con el repositorio (o un diccionario vacío si no hay metadatos).

{'license': 'afl-3.0'}

Creando nuestro informe de revisión de metadatos

Una vez que tengamos un diccionario de Python que contenga los metadatos asociados con un repositorio, crearemos una «tarjeta de evaluación» para nuestra revisión de metadatos. En este caso particular, revisaremos nuestros metadatos definiendo algunos campos de metadatos para los que queremos valores. Por ejemplo, podemos querer asegurarnos de que el campo license siempre esté completado. Para calificar nuestros metadatos, contaremos qué campos de metadatos están presentes entre los campos deseados y devolveremos una puntuación porcentual basada en la cobertura de los campos de metadatos requeridos para los que queremos ver valores.

Dado que tenemos un diccionario de Python que contiene nuestros metadatos, podemos recorrer este diccionario para comprobar si las claves deseadas están presentes. Si falta un campo de metadatos deseado (una clave en nuestro diccionario), asignaremos el valor 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":
        # [...]

Esta función devolverá un diccionario que contiene claves que representan los campos de metadatos que requerimos para nuestro modelo o conjunto de datos. Los valores del diccionario incluirán los metadatos introducidos para ese campo o None si ese campo de metadatos no está presente en el YAML.

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

Una vez que tenemos este diccionario, podemos crear nuestro informe de metadatos. Por brevedad, no incluiremos el código completo aquí, pero el repositorio de Hugging Face Spaces para este Webhook contiene el código completo.

Creamos una función que genera una tabla en Markdown, que produce una versión más presentable de los datos que tenemos en nuestro diccionario de cobertura de metadatos.

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

También tenemos una función de Python que genera una puntuación (que representa el porcentaje de campos de metadatos deseados presentes)

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

y una función de Python que crea un informe en markdown para la revisión de nuestros metadatos. Este informe contiene tanto la puntuación como la tabla de metadatos, junto con una explicación de lo que contiene el informe.

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

¿Cómo publicar la revisión automáticamente?

Ahora tenemos un informe de revisión de metadatos con formato markdown. Usaremos la biblioteca huggingface_hub para publicar esta revisión. Definimos una función que recibe los datos del Webhook recibidos del Hub, analiza los datos y crea el informe de metadatos. Dependiendo de si se ha creado previamente un informe, la función crea un informe nuevo o publica un nuevo issue en un hilo de revisión de metadatos existente.

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

:= es la sintaxis de Python para un operador de expresión de asignación, añadido al lenguaje en la versión 3.8 (conocido coloquialmente como el operador walrus). Las opiniones sobre esta sintaxis son variadas y no cambia cómo Python evalúa el código si no se utiliza. Puede leer más sobre este operador en este artículo de Real Python.

Creación de un Webhook para responder a los cambios en el Hub

Ahora tenemos la funcionalidad principal para crear un informe de revisión de metadatos para un modelo o conjunto de datos. El siguiente paso es usar Webhooks para responder automáticamente a los cambios.

Crea un Webhook en tu perfil de usuario

Primero, crea tu Webhook yendo a https://huggingface.co/settings/webhooks.

  • Introduce algunos repositorios de destino a los que tu Webhook escuchará (probablemente quieras limitar esto a tus propios repositorios o a los repositorios de la organización a la que perteneces).
  • Introduce un secreto para hacer tu Webhook más seguro (si no sabes qué elegir para esto, es posible que quieras usar un generador de contraseñas para generar una cadena aleatoria lo suficientemente larga para tu secreto).
  • Por ahora, podemos pasar una URL ficticia para el parámetro Webhook URL.

Tu Webhook se verá así:

webhook settings

Crear un nuevo perfil de usuario Bot

Esta guía crea una cuenta de usuario separada que publicará las revisiones de metadatos.

Bot user account

Al crear un bot que interactuará con otros usuarios en el Hub, le pedimos que etiquete claramente la cuenta como “Bot” (vea la captura de pantalla del perfil).

Crear un listener de Webhook

Ahora necesitamos alguna forma de escuchar eventos de Webhook. Hay muchas herramientas posibles que puedes usar para escuchar eventos de Webhook. Muchos servicios existentes, como Zapier y IFTTT, pueden usar Webhooks para desencadenar acciones (por ejemplo, podrían publicar un tuit cada vez que se actualiza un modelo). En este caso, implementaremos nuestro listener de Webhook usando FastAPI.

FastAPI es un framework web de Python. Usaremos FastAPI para crear un listener de Webhook. En particular, necesitamos implementar una ruta que acepte solicitudes POST en /webhook. Para la autenticación, compararemos la cabecera X-Webhook-Secret con un secreto WEBHOOK_SECRET que se puede pasar a nuestro contenedor de Docker en tiempo de ejecución.

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

La función anterior recibirá eventos de Webhook y creará o actualizará el informe de revisión de metadatos para el repositorio modificado.

Usa Spaces para desplegar nuestra aplicación Webhook

Nuestro archivo main.py contiene todo el código que necesitamos para nuestra aplicación Webhook. Para desplegarla, utilizaremos un Space.

Para nuestro Space, usaremos Docker para ejecutar nuestra aplicación. El Dockerfile copia el archivo de nuestra aplicación, instala las dependencias necesarias y ejecuta la aplicación. Para poblar la variable KEY, también configuraremos un secreto WEBHOOK_SECRET para nuestro Space con el secreto que generamos anteriormente. Puedes leer más sobre los Spaces de Docker aquí.

Por último, necesitamos actualizar la URL en la configuración de nuestro Webhook con la URL de nuestro Space. Podemos obtener la “direct URL” de nuestro Space desde el menú contextual. Haz clic en “Embed this Space” y copia la “Direct URL”.

direct url

Una vez que tengamos esta URL, podemos pasarla al parámetro Webhook URL en la configuración de nuestro Webhook. ¡Nuestro bot debería comenzar a publicar revisiones cuando los repositorios monitoreados cambien!

Conclusión y próximos pasos

Ahora tenemos un bot automático de revisión de metadatos. Aquí tienes algunas ideas sobre cómo podrías ampliar esta guía:

  • La revisión de metadatos realizada por nuestro bot era relativamente básica; puedes agregar reglas más complejas para revisar los metadatos.
  • Podrías usar el archivo completo README.md para realizar la revisión.
  • Es posible que desee definir ‘reglas’ que sean particularmente importantes para su organización y usar un webhook para verificar que se cumplan.

Si creas una aplicación de calidad de metadatos usando Webhooks, por favor etiquétame @davanstrien; ¡me encantaría saber al respecto!

Update on GitHub