Hub documentation

دليل Webhook: معالجة الملفات الجديدة في حاوية باستخدام Jobs

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

دليل Webhook: معالجة الملفات الجديدة في حاوية باستخدام Jobs

Storage Buckets مكان مناسب للملفات التي تصل على فترات متباعدة: تصديرات من أدوات أخرى، وسائط، تسجيلات، عمليات مسح. غالبًا ما يكون لديك سير عمل يجب تنفيذه على هذه الملفات قبل أن تصبح مفيدة، مثل تحويلها أو تنظيفها أو تحويلها إلى نص.

يمكن لخطاف ويب (Webhook) على الدلو (Bucket) وJob تنفيذ هذه المهمة تلقائيًا، دون الحاجة إلى خادم. عند تغيّر الملفات، يبدأ الخطاف الويب تشغيل الـ Job. يتلقى الـ Job قائمة الملفات المتغيّرة، ثم يعالجها ويتوقف. لا تدفع أي رسوم إلا أثناء تشغيله.

يشرح هذا الدليل النمط، ثم يوضّح كيفية تطبيقه بمثال واحد: تحويل ملفات CSV وJSON المرفوعة إلى Parquet مُحسّنة.

كيف يعمل

file uploaded ──▶ webhook ──▶ Job runs with the event ──▶ result written to a second bucket

يمكن أن تشغّل مهمة (Job) بدلاً من استدعاء عنوان URL. تقوم بإنشاء المهمة مرة واحدة، ثم يُعيد كل حدث webhook تشغيلها مع وضع الحدث في بيئتها. بالنسبة لخزان (bucket)، تُدرج WEBHOOK_PAYLOAD الملفات التي تغيّرت:

{
  "event": { "action": "update", "scope": "repo.content" },
  "repo": { "type": "bucket", "name": "your-username/my-raw-files", ... },
  "updatedFiles": [
    { "path": "data.csv", "action": "add", "xetHash": "433b53b8...", "size": 10983 }
  ]
}

وبالتالي، يعالج Job الملفات الجديدة فقط، ويمكنه تحديد كيفية التعامل مع كل ملف قبل تنزيل أي شيء.

يعيد كل تشغيل استخدام صورة Job وأمره ومتغيرات بيئته ونوع العتاد الخاص به ومهلة انتهاء الوقت. ولا يحصل على أحجام Job أو أسرارها. ولهذا السبب، تُنفّذ الخطوات التالية السكربت من رابط URL وتضع الرمز (token) على webhook.

تكتب المهمة نتائجها إلى دلو ثانوي. لو كتبت إلى الدلو الذي تراقبه، فإن مخرجاتها الخاصة ستُطلق خطاف الويب مرة أخرى.

مثال: تحويل عمليات الرفع إلى Parquet مُحسّنة

تُعدّ عمليات الاستعلام عن تصديرات CSV و JSON بطيئة، كما أن مشاركتها غير مريحة. أما Parquet المُحسّن فهو أسرع في التصفية والبث، كما أن رفعه وتنزيله أسرع بفضل إزالة التكرار في Xet. في هذا المثال، يظهر كل ملف CSV أو JSON أو Parquet يُرفع إلى دلو واحد على شكل Parquet مُحسّن في دلو آخر. ينفّذ هذا العمل optimize-parquet.py، وهو سكريبت جاهز من uv-scripts.

تحتاج إلى حساب Hugging Face يحتوي على رصيد مدفوع مسبقًا وواجهة hf CLI.

أنشئ حاويتين

يستقبل أحد الدلاء عمليات الرفع الخاصة بك، بينما يستقبل الدلاء الآخر ملفات Parquet:

hf buckets create my-raw-files --private
hf buckets create my-parquet --private

إنشاء المهمة

أنشئ المهمة التي ستنفّذها نقطة الاتصال:

hf jobs run --flavor cpu-upgrade --timeout 2h \
    -e OUTPUT_BUCKET=your-username/my-parquet \
    ghcr.io/astral-sh/uv:python3.12-bookworm \
    uv run https://huggingface.co/datasets/uv-scripts/data-processing/raw/main/optimize-parquet.py

تُنفَّذ السكربت من عنوانها عبر hf jobs run. يُعدّ hf jobs uv run الطريقة المعتادة لتشغيل سكربت UV، لكنه يرفع السكربت إلى وحدة تخزين، وهو ما لا يتوفر في تشغيل عبر خطاف ويب. يكفي cpu-upgrade لهذا العمل، ويترك مهلة انتهاء المهلة البالغة ساعتين مساحةً للملفات الكبيرة.

يمكن أن يكون السكربت أيضًا في دلو أو مستودع خاص. لا تستخدم الدلو المُراقَب: فرفع السكربت سيبدأ مهمة. أضف --secrets HF_TOKEN إلى الأمر، مع رمز يمكنه قراءة السكربت. إذا فشلت العملية مع SyntaxError، فإن الرمز لا يستطيع قراءته. يحتاج رمز الـ webhook إلى نفس مستوى الوصول، لأن عمليات الـ webhook لا تحصل على هذا السر.

hf jobs run يبدأ المهمة فورًا. لا يحتوي هذا التشغيل الأول على حدث webhook، وoptimize-parquet.py لا يفعل شيئًا بدونه، لذا تتوقف المهمة مباشرة. انسخ معرّف المهمة الذي يطبعه.

إنشاء خطاف الويب

شاهد الدلو الأول وشغّل مهمة Job عند حدوث تغيير فيه:

hf webhooks create --job-id <job ID> --watch bucket:your-username/my-raw-files \
    --domain repo --secrets HF_TOKEN

--domain repo يقيّد خطاف الويب على تغييرات الملفات والإعدادات. لا ترسل الدلاء سوى تلك التغييرات، لذا فإن هذا الأمر صريح وليس ضروريًا، لكنه يحافظ على صحة الأمر إذا قمت لاحقًا بمراقبة نموذج أو مجموعة بيانات.

--secrets HF_TOKEN يخزّن رمزًا مع خطّاف الويب (webhook) مشفّرًا. كل مهمة (Job) يبدأها خطّاف الويب يتلقّى هذا الرمز كسرّ ويستخدمه لقراءة الدلاء (buckets) والكتابة فيها. يأتي القيمة من HF_TOKEN في بيئة التشغيل لديك، أو من الرمز الذي سجّلت الدخول به. يُعدّ رمز ذو صلاحيات دقيقة يحمل فقط الصلاحيات التي تحتاجها المهمة الخيار الأكثر أمانًا.

لاستخدام رمز مخصص لهذا المسار، مرّر القيمة صراحةً باستخدام --secrets HF_TOKEN=hf_…، أو احفظه بعيداً عن سجلّ الطرفية (shell) عن طريق تمريره عبر أنبوب: printf 'HF_TOKEN=hf_…\n' | hf webhooks create … --secrets-file -.

يطبع الأمر معرّف خطاف الويب. لإيقاف خط الأنابيب لاحقاً، احذف خطاف الويب باستخدام hf webhooks delete <webhook ID>.

رفع ملف

hf buckets cp data.csv hf://buckets/your-username/my-raw-files/data.csv

بعد دقيقة تقريباً، يظهر Job في صفحة Jobs. إذا لم يظهر، افتح تبويب Activity الخاص بـ webhook في إعدادات webhook لديك لرؤية التسليم، واقرأ مخرجات Job باستخدام hf jobs logs <job ID>. عند انتهاء Job، يكون ملف Parquet في الدلو الثاني:

hf buckets ls your-username/my-parquet -R
data.csv/README.md
data.csv/data/train-00000-of-00001.parquet

لتحويل العديد من الملفات، ارفعها في عملية واحدة باستخدام hf buckets sync. عادةً ما تصل الملفات المرفوعة معًا كحدث واحد، وبالتالي يقوم Job واحد بتحويل جميعها، بحد أقصى 10,000 ملف لكل حدث. راجع Webhooks للاطلاع على حمولة bucket الكاملة وما يحدث عند تجاوز هذا الحد.

ما يفعله السكربت

الجزء الخاص بالـ webhooks هو قراءة الحدث:

event = json.loads(os.environ.get("WEBHOOK_PAYLOAD", "{}"))  # empty when you run the Job yourself
input_bucket = os.environ.get("WEBHOOK_REPO_ID")

for changed_file in event.get("updatedFiles", []):
    if changed_file["action"] != "add":
        continue  # skip deleted files
    path, size = changed_file["path"], changed_file["size"]
    ...  # convert the file (see the full script)

لكل ملف جديد، يقوم السكربت بتحميله باستخدام datasets مباشرةً من الدلو (hf://buckets/...). إذا كان حجم الملف أكبر من ثلث مساحة القرص المتاحة في المهمة، يتم بثه بدلاً من تنزيله. ثم يكتب push_to_hub الملف في دلو الإخراج بصيغة Parquet مع تقسيم المحتوى المعرّف بالمحتوى، وفهرس صفحات، ومجموعات صفوف لا تتجاوز 100 ميغابايت.

استخدم النمط الخاص بمهمتك

حافظ على الإعداد وغيّر السكربت. على سبيل المثال:

  • احذف البيانات الشخصية قبل التدريب. اجمع النص الخام في حاوية خاصة، واحجب المعلومات الشخصية باستخدام نموذج مثل GLiNER2 PII filter، ثم ارفع النص المحجوب فقط إلى مجموعة بيانات التدريب الخاصة بك.
  • قيّم نقاط التفتيش الجديدة. يحفظ Job التدريب نقاط التفتيش في bucket، ويبدأ كل نقطة تفتيش جديدة Job تقييم. إذا تم رفع نقطة التفتيش في عدة أجزاء، فتفاعل فقط عند ظهور ملف علامة تكتبه في النهاية في updatedFiles؛ فقد تصل الأحداث خارج الترتيب.
  • نسخ أو تضمين ملفات جديدة. حوّل التسجيلات الجديدة إلى نصوص مكتوبة، أو المستندات الجديدة إلى تمثيلات متجهة للبحث.

عند كتابة سكربت، قرّر ما الذي سيقوم به في التشغيل الأول، عندما لا يكون WEBHOOK_PAYLOAD مضبوطًا. يمكنه الخروج، كما تفعل optimize-parquet.py، أو القيام بعمل حقيقي، مثل معالجة الملفات الموجودة مسبقًا في الدلو. إذا كان التشغيل الأول يحتاج إلى رمز، على سبيل المثال لقراءة الدلو أو سكربت خاص، أضف --secrets HF_TOKEN إلى hf jobs run. لا تحصل عمليات Webhook على هذا السر. تحصل على رمزها من الـ webhook.

Webhook أو جدولة؟

يبدأ خطاف الويب (Webhook) مهمة (Job) لكل حدث، لذا تُعالَج الملفات الجديدة بعد وصولها بنحو دقيقة واحدة. إذا لم تكن هناك حاجة لمعالجتها بهذه السرعة، فإن المهمة المجدولة (scheduled Job) تُعد بديلاً: فهي تعمل كل ساعة أو كل يوم وتعالج كل ما وصل منذ آخر تشغيل. وهذا يجمع العمل في عدد أقل من المهام، مما يساعد في مهام وحدة معالجة الرسوميات (GPU) التي تستغرق وقتاً طويلاً للبدء، ويتجنب حد خطاف الويب البالغ 1,000 تشغيل لكل 24 ساعة. في هذه الحالة، يجب على السكربت أن يجد الملفات الجديدة بنفسه، على سبيل المثال عن طريق مقارنة دلاء الإدخال والإخراج.

Update on GitHub