Hub documentation

دليل Webhook: إعداد مراجعة تلقائية لجودة البيانات الوصفية للنماذج ومجموعات البيانات

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

دليل Webhook: إعداد مراجعة تلقائية لجودة البيانات الوصفية للنماذج ومجموعات البيانات

ستأخذك هذه الدليل خطوة بخطوة في إنشاء نظام يستجيب للتغييرات التي تطرأ على نماذج المستخدم أو المؤسسة أو مجموعات البيانات على Hub، وينشئ «مراجعة بيانات وصفية» للمستودع الذي تم تغييره.

ما الذي نبنيه ولماذا؟

قبل أن نتعمق في التفاصيل التقنية المرتبطة بهذا المسار العمل المحدد، سنُلقي نظرة سريعة على ما سننشئه ولماذا.

تُعدّ بطاقات النماذج وبطاقات مجموعات البيانات أدوات أساسية لتوثيق نماذج التعلم الآلي ومجموعات البيانات. يستخدم Hugging Face Hub ملف README.md يحتوي على كتلة ترويسة YAML لتوليد بطاقات النماذج ومجموعات البيانات. يحدد قسم 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 لدى المستخدمين الذين يرفعون النماذج ومجموعات البيانات إلى Hub. وبينما يمكن لشخص ما في الفريق أن يتولى مسؤولية مراجعة هذه البيانات الوصفية، فقد يكون هناك بعض الأتمتة التي يمكننا تنفيذها لمساعدتنا في حل هذه المشكلة. ستكون النتيجة تقرير مراجعة بيانات وصفية يُنشر أو يُحدَّث تلقائيًا عند حدوث تغيير في مستودع على Hub. فيما يتعلق بجودة بياناتنا الوصفية، يعمل هذا النظام بشكل مشابه لـ CI/CD.

Metadata review

يمكنك أيضًا العثور على مثال لمراجعة هنا.

استخدام مكتبة عميل Hub لإنشاء بطاقة مراجعة نموذج

huggingface_hub هي مكتبة بلغة بايثون تتيح لك التفاعل مع الـ Hub. يمكننا استخدام هذه المكتبة لـ تحميل بطاقات النماذج والمجموعات من الـ Hub باستخدام طريقتي DatasetCard.load أو ModelCard.load. على وجه التحديد، سنستخدم هذه الطرق لتحميل قاموس بلغة بايثون يحتوي على البيانات الوصفية المعرّفة في YAML الخاص ببطاقة النموذج أو المجموعة. سننشئ دالة بايثون صغيرة لتغليف هذه الطرق وإجراء بعض معالجة الاستثناءات.

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

إنشاء تقرير مراجعة البيانات الوصفية

بمجرد أن نحصل على قاموس بايثون يحتوي على البيانات الوصفية المرتبطة بمستودع، سننشئ «بطاقة تقييم» لمراجعة البيانات الوصفية لدينا. في هذه الحالة بالتحديد، سنراجع البيانات الوصفية من خلال تحديد بعض حقول البيانات الوصفية التي نرغب في وجود قيم لها. على سبيل المثال، قد نرغب في التأكد من أن حقل 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}

بمجرد الحصول على هذا القاموس، يمكننا إنشاء تقرير البيانات الوصفية. ومن باب الاختصار، لن ندرج الكود الكامل هنا، لكن مستودع repository الخاص بـ Hugging Face Spaces لهذا Webhook يحتوي على الكود الكامل.

ننشئ دالة واحدة تنشئ جدولًا بصيغة 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)

ودالة بلغة بايثون تنشئ تقريرًا بصيغة ماركداون لمراجعة بياناتنا الوصفية. يحتوي هذا التقرير على كلٍّ من جدول الدرجات وجدول البيانات الوصفية، إلى جانب بعض الشرح لما يتضمنه التقرير.

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

كيف تُرسل المراجعة تلقائيًا؟

أصبح لدينا الآن تقرير مراجعة بيانات وصفية منسّق بصيغة Markdown. سنستخدم مكتبة huggingface_hub لنشر هذا التقرير. نعرّف دالة تستقبل بيانات Webhook المستلمة من Hub، وتحلل البيانات، وتُنشئ التقرير الوصفي. اعتماداً على ما إذا كان قد تم إنشاء تقرير سابقاً، فإن الدالة تنشئ تقريراً جديداً أو تنشر مشكلة جديدة في خيط مراجعة البيانات الوصفية الموجود مسبقاً.

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

:= هو صياغة بايثون لمُشغِّل تعبير الإسناد الذي أُضيف إلى لغة بايثون في الإصدار 3.8 (ويُعرف شعبيًا بمُشغِّل الفيل القزم). تتباين آراء الناس حول هذه الصياغة، ولا يُغيّر استخدام هذا المُشغِّل طريقة تقييم بايثون للكود إذا لم تستخدمه. يمكنك قراءة المزيد عن هذا المُشغِّل في هذا مقال من Real Python.

إنشاء Webhook للاستجابة إلى التغييرات على Hub

لدينا الآن الوظائف الأساسية لإنشاء تقرير مراجعة البيانات الوصفية لنموذج أو مجموعة بيانات. الخطوة التالية هي استخدام Webhooks للاستجابة للتغييرات تلقائيًا.

أنشئ Webhook في ملفك الشخصي

أولاً، أنشئ Webhook الخاص بك بالانتقال إلى https://huggingface.co/settings/webhooks.

  • أدخل بعض المستودعات المستهدفة التي سيستمع إليها Webhook الخاص بك (من المرجح أنك ستريد تحديد هذا النطاق بمستودعاتك الخاصة أو بمستودعات المنظمة التي تنتمي إليها).
  • أدخل كلمة مرور لجعل Webhook الخاص بك أكثر أمانًا (إذا كنت لا تعرف ما يجب اختياره لهذا الغرض، فقد ترغب في استخدام مولّد كلمات مرور لتوليد سلسلة عشوائية طويلة بما يكفي لكلمة المرور الخاصة بك).
  • يمكننا تمرير عنوان URL وهمي لمعامل Webhook URL في الوقت الحالي.

سيبدو Webhook الخاص بك على النحو التالي:

webhook settings

إنشاء ملف مستخدم جديد لروبوت

ينشئ هذا الدليل حساب مستخدم منفصلًا سيقوم بنشر مراجعات البيانات الوصفية.

Bot user account

عند إنشاء بوت سيتفاعل مع مستخدمين آخرين على Hub، نطلب منك وضع علامة واضحة على الحساب بأنه “Bot” (انظر لقطة شاشة الملف الشخصي).

إنشاء مستمع Webhook

نحتاج الآن إلى طريقة ما للاستماع إلى أحداث Webhook. هناك العديد من الأدوات الممكنة التي يمكنك استخدامها للاستماع إلى أحداث Webhook. يمكن للعديد من الخدمات الموجودة مسبقًا، مثل Zapier وIFTTT، استخدام Webhooks لتفعيل الإجراءات (على سبيل المثال، يمكنها نشر تغريدة كل مرة يتم فيها تحديث نموذج). في هذه الحالة، سنقوم بتنفيذ مستمع Webhook الخاص بنا باستخدام FastAPI.

FastAPI هو إطار عمل ويب بلغة بايثون. سنستخدم FastAPI لإنشاء مستمع Webhook. على وجه التحديد، نحتاج إلى تنفيذ مسار يقبل طلبات POST على /webhook. أما للمصادقة، فسنقارن الترويسة X-Webhook-Secret بسر WEBHOOK_SECRET يمكن تمريره إلى حاوية Docker وقت التشغيل.

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.

لتنفيذ تطبيقنا في مساحتنا، سنستخدم Docker. يقوم Dockerfile بنسخ ملف تطبيقنا، وتثبيت الاعتماديات المطلوبة، وتشغيل التطبيق. ولتعبئة متغير KEY، سنضبط أيضًا سراً باسم WEBHOOK_SECRET لمساحتنا باستخدام السر الذي أنشأناه سابقاً. يمكنك قراءة المزيد حول مساحات Docker هنا.

أخيرًا، نحتاج إلى تحديث عنوان URL في إعدادات Webhook لدينا ليصبح عنوان URL الخاص بمساحتنا (Space). يمكننا الحصول على "الرابط المباشر" (direct URL) لمساحتنا من القائمة السياقية. انقر على "تضمين هذه المساحة" (Embed this Space) وانسخ "الرابط المباشر" (Direct URL).

direct url

بمجرد الحصول على هذا الرابط، يمكننا تمريره إلى معامل Webhook URL في إعدادات Webhook لدينا. يجب أن يبدأ بوتنا الآن في نشر المراجعات عند حدوث تغييرات في المستودعات المُراقَبة!

الخلاصة والخطوات التالية

لدينا الآن روبوت مراجعة تلقائي للميتاداتا! فيما يلي بعض الأفكار لكيفية البناء على هذا الدليل:

  • كانت مراجعة البيانات الوصفية التي أجراها روبوتنا بدائية إلى حد ما؛ يمكنك إضافة قواعد أكثر تعقيداً لمراجعة البيانات الوصفية.
  • يمكنك استخدام ملف README.md الكامل لإجراء المراجعة.
  • قد ترغب في تحديد «قواعد» تكون بالغة الأهمية لمنظمتك، واستخدام خطاف ويب (webhook) للتحقق من الالتزام بها.

إذا كنت تبني تطبيقًا لجودة البيانات الوصفية باستخدام Webhooks، فيرجى الإشارة إليّ @davanstrien؛ سأكون سعيدًا بمعرفة المزيد عنه!

Update on GitHub