Hub documentation
Spark
Spark
يتيح Spark معالجة البيانات على نطاق واسع في الوقت الفعلي ضمن بيئة موزعة.
يمكنك استخدام pyspark_huggingface للوصول إلى مستودعات مجموعات بيانات Hugging Face في PySpark عبر مصدر البيانات “huggingface”.
جرّب Spark Notebooks على Hugging Face Spaces للحصول على Notebooks مع تثبيت PySpark وpyspark_huggingface مسبقًا.
الإعداد
التثبيت
للقراءة من Hugging Face Datasets والكتابة إليها، تحتاج إلى تثبيت مكتبة pyspark_huggingface:
pip install pyspark_huggingfaceسيؤدي هذا أيضاً إلى تثبيت الاعتماديات المطلوبة مثل huggingface_hub للمصادقة، وpyarrow لقراءة مجموعات البيانات وكتابتها.
المصادقة
تحتاج إلى المصادقة على Hugging Face لقراءة مستودعات مجموعات البيانات الخاصة/المقيّدة أو للكتابة في مستودعات مجموعات بياناتك.
يمكنك استخدام سطر الأوامر على سبيل المثال:
hf auth loginكما يمكن تزويد رمز Hugging Face الخاص بك عبر متغير البيئة HF_TOKEN أو بتمرير خيار token إلى القارئ.
لمزيد من التفاصيل حول المصادقة، راجع هذا الدليل.
تفعيل مصدر البيانات “huggingface”
جاء PySpark 4 مع واجهة برمجة تطبيقات مصدر بيانات جديدة تتيح استخدام مجموعات البيانات من مصادر مخصصة.
إذا كان pyspark_huggingface مثبّتًا، يستورده PySpark تلقائيًا ويمكّن مصدر بيانات “huggingface”.
توفر المكتبة أيضًا دعمًا رجعيًا لواجهة برمجة تطبيقات مصدر البيانات (Data Source API) لمصدر البيانات “huggingface” في PySpark 3.5 و3.4 و3.3.
ومع ذلك، في هذه الحالة يجب استيراد pyspark_huggingface بشكل صريح لتفعيل الدعم الرجعي وتمكين مصدر البيانات “huggingface”:
>>> import pyspark_huggingface
huggingface datasource enabled for pyspark 3.x.x (backport from pyspark 4)اقرأ
تتيح لك مصدر البيانات “huggingface” قراءة مجموعات البيانات من Hugging Face، باستخدام pyarrow في الخلفية لبث بيانات Arrow.
وهذا متوافق مع جميع مجموعات البيانات في الصيغ المدعومة على Hugging Face، مثل مجموعات بيانات Parquet.
على سبيل المثال، إليك كيفية تحميل مجموعة بيانات stanfordnlp/imdb:
>>> import pyspark_huggingface
>>> from pyspark.sql import SparkSession
>>> spark = SparkSession.builder.appName("demo").getOrCreate()
>>> df = spark.read.format("huggingface").load("stanfordnlp/imdb")إليك مثالًا آخر مع مجموعة بيانات BAAI/Infinity-Instruct. إنها مستودع محمي، حيث يجب على المستخدمين قبول شروط الاستخدام قبل الوصول إليها. كما أنها تحتوي على عدة مجموعات فرعية، وهي “3M” و “7M”. لذا نحتاج إلى تحديد أي منها يجب تحميله.

نستخدم دالة .format() لاستخدام مصدر بيانات “huggingface”، ودالة .load() لتحميل مجموعة البيانات (وبشكل أدق، الإعداد أو المجموعة الفرعية المسمّاة “7M” والتي تحتوي على 7 ملايين عينة). ثم نحسب عدد الحوارات لكل لغة ونُرشّح مجموعة البيانات.
بعد تسجيل الدخول للوصول إلى المستودع المحمي، يمكننا تنفيذ الأمر التالي:
>>> import pyspark_huggingface
>>> from pyspark.sql import SparkSession
>>> spark = SparkSession.builder.appName("demo").getOrCreate()
>>> df = spark.read.format("huggingface").option("config", "7M").load("BAAI/Infinity-Instruct")
>>> df.show()
+---+----------------------------+-----+----------+--------------------+
| id| conversations|label|langdetect| source|
+---+----------------------------+-----+----------+--------------------+
| 0| [{human, def exti...| | en| code_exercises|
| 1| [{human, See the ...| | en| flan|
| 2| [{human, This is ...| | en| flan|
| 3| [{human, If you d...| | en| flan|
| 4| [{human, In a Uni...| | en| flan|
| 5| [{human, Read the...| | en| flan|
| 6| [{human, You are ...| | en| code_bagel|
| 7| [{human, I want y...| | en| Subjective|
| 8| [{human, Given th...| | en| flan|
| 9|[{human, 因果联系原则是法...| | zh-cn| Subjective|
| 10| [{human, Provide ...| | en|self-oss-instruct...|
| 11| [{human, The univ...| | en| flan|
| 12| [{human, Q: I am ...| | en| flan|
| 13| [{human, What is ...| | en| OpenHermes-2.5|
| 14| [{human, In react...| | en| flan|
| 15| [{human, Write Py...| | en| code_exercises|
| 16| [{human, Find the...| | en| MetaMath|
| 17| [{human, Three of...| | en| MetaMath|
| 18| [{human, Chandra ...| | en| MetaMath|
| 19|[{human, 用经济学知识分析...| | zh-cn| Subjective|
+---+----------------------------+-----+----------+--------------------+يُحمِّل هذا الأمر مجموعة البيانات بطريقة البث، ويحتوي إطار البيانات الناتج على قسم واحد لكل ملف بيانات في المجموعة لتمكين المعالجة الموزعة بكفاءة.
لحساب عدد الحوارات لكل لغة، ننفذ هذا الكود الذي يستخدم خيار columns وعمليات groupBy().
يُعد خيار columns مفيدًا لتحميل البيانات التي نحتاجها فقط، نظرًا لأن PySpark لا يتيح دفع الشروط (predicate push-down) مع واجهة برمجة تطبيقات مصدر البيانات (Data Source API).
كما يتوفر خيار filters لتحميل البيانات التي تحتوي على قيم ضمن نطاق معين فقط.
>>> df_langdetect_only = (
... spark.read.format("huggingface")
... .option("config", "7M")
... .option("columns", '["langdetect"]')
... .load("BAAI/Infinity-Instruct")
... )
>>> df_langdetect_only.groupBy("langdetect").count().show()
+----------+-------+
|langdetect| count|
+----------+-------+
| en|6697793|
| zh-cn| 751313|
+----------+-------+لترشيح مجموعة البيانات والاحتفاظ فقط بالحوارات باللغة الصينية:
>>> df_chinese_only = (
... spark.read.format("huggingface")
... .option("config", "7M")
... .option("filters", '[("langdetect", "=", "zh-cn")]')
... .load("BAAI/Infinity-Instruct")
... )
>>> df_chinese_only.show()
+---+----------------------------+-----+----------+----------+
| id| conversations|label|langdetect| source|
+---+----------------------------+-----+----------+----------+
| 9|[{human, 因果联系原则是法...| | zh-cn|Subjective|
| 19|[{human, 用经济学知识分析...| | zh-cn|Subjective|
| 38| [{human, 某个考试共有A、...| | zh-cn|Subjective|
| 39|[{human, 撰写一篇关于斐波...| | zh-cn|Subjective|
| 57|[{human, 总结世界历史上的...| | zh-cn|Subjective|
| 61|[{human, 生成一则广告词。...| | zh-cn|Subjective|
| 66|[{human, 描述一个有效的团...| | zh-cn|Subjective|
| 94|[{human, 如果比利和蒂芙尼...| | zh-cn|Subjective|
|102|[{human, 生成一句英文名言...| | zh-cn|Subjective|
|106|[{human, 写一封感谢信,感...| | zh-cn|Subjective|
|118| [{human, 生成一个故事。}...| | zh-cn|Subjective|
|174|[{human, 高胆固醇水平的后...| | zh-cn|Subjective|
|180|[{human, 基于以下角色信息...| | zh-cn|Subjective|
|192|[{human, 请写一篇文章,概...| | zh-cn|Subjective|
|221|[{human, 以诗歌形式表达对...| | zh-cn|Subjective|
|228|[{human, 根据给定的指令,...| | zh-cn|Subjective|
|236|[{human, 打开一个新的生成...| | zh-cn|Subjective|
|260|[{human, 生成一个有关未来...| | zh-cn|Subjective|
|268|[{human, 如果有一定数量的...| | zh-cn|Subjective|
|273| [{human, 题目:小明有5个...| | zh-cn|Subjective|
+---+----------------------------+-----+----------+----------+من الممكن أيضًا تطبيق عوامل التصفية أو إزالة الأعمدة على إطار البيانات (DataFrame) المحمّل، لكن من الكفاءة أن يتم ذلك أثناء التحميل، خاصةً في مجموعات بيانات Parquet. في الواقع، يحتوي Parquet على بيانات وصفية على مستوى الملف ومجموعة الصفوف، مما يتيح تجاوز أجزاء كاملة من مجموعة البيانات التي لا تحتوي على عينات تحقق من المعايير. كما يمكن تحميل الأعمدة في Parquet بشكل مستقل، مما يتيح تجاوز الأعمدة المستبعدة وتجنب تحميل بيانات غير ضرورية.
خيارات
فيما يلي قائمة بالخيارات المتاحة التي يمكنك تمريرها إلى read..option():
config(نص): اختيار مجموعة فرعية/إعداد من مجموعة البياناتsplit(نص): تحديد تقسيم مجموعة البيانات (الافتراضي هو “train”)token(نص): رمز Hugging Face الخاص بك
بدلاً من تحديد الإعداد أو التقسيم، يمكنك اختيار الملفات التي تريد تحميلها يدويًا:
data_dir(نص): تحديد مجلدdata_files(نص): اختيار ملف واحد أو عدة ملفات، على سبيل المثال"data/*.parquet"أو'["part1.parquet", "par2.parquet"]'
لمجموعات بيانات Parquet:
columns(نص): تحديد مجموعة فرعية من الأعمدة لتحميلها، على سبيل المثال'["id"]'filters(نص): لتخطي الملفات ومجموعات الصفوف التي لا تطابق معيارًا معينًا، مثل'[("source", "=", "code_exercises")]'. تُمرَّر عوامل التصفية إلى pyarrow.parquet.ParquetDataset.
تُمرَّر أي خيارات أخرى كحجج إلى [datasets.load_dataset] (https://huggingface.co/docs/datasets/en/package_reference/loading_methods#datasets.load_dataset)
تشغيل استعلامات SQL
بمجرد أن يكون إطار بيانات PySpark الخاص بك جاهزًا، يمكنك تنفيذ استعلامات SQL باستخدام spark.sql:
>>> import pyspark_huggingface
>>> from pyspark.sql import SparkSession
>>> spark = SparkSession.builder.appName("demo").getOrCreate()
>>> df = (
... spark.read.format("huggingface")
... .option("config", "7M")
... .option("columns", '["source"]')
... .load("BAAI/Infinity-Instruct")
... )
>>> spark.sql("SELECT source, count(*) AS total FROM {df} GROUP BY source ORDER BY total DESC", df=df).show()
+--------------------+-------+
| source| total|
+--------------------+-------+
| flan|2435840|
| Subjective|1342427|
| OpenHermes-2.5| 855478|
| MetaMath| 690138|
| code_exercises| 590958|
|Orca-math-word-pr...| 398168|
| code_bagel| 386649|
| MathInstruct| 329254|
|python-code-datas...| 88632|
|instructional_cod...| 82920|
| CodeFeedback| 79513|
|self-oss-instruct...| 50467|
|Evol-Instruct-Cod...| 43354|
|CodeExercise-Pyth...| 27159|
|code_instructions...| 23130|
| Code-Instruct-700k| 10860|
|Glaive-code-assis...| 9281|
|python_code_instr...| 2581|
|Python-Code-23k-S...| 2297|
+--------------------+-------+مرة أخرى، تحديد خيار columns ليس ضرورياً، لكنه مفيد لتجنب تحميل بيانات غير ضرورية وجعل الاستعلام أسرع.
اكتب
يمكنك كتابة إطار بيانات PySpark إلى Hugging Face باستخدام مصدر البيانات “huggingface”. يقوم برفع ملفات Parquet بالتوازي بطريقة موزعة، ولا يُثبّت الملفات إلا بعد اكتمال رفعها جميعًا. يعمل بالطريقة التالية:
>>> import pyspark_huggingface
>>> df.write.format("huggingface").save("username/dataset_name")إليك كيفية استخدام هذه الدالة لإعادة كتابة النسخة المفلترة من مجموعة بيانات BAAI/Infinity-Instruct إلى Hugging Face.
أولاً، عليك إنشاء مستودع مجموعة بيانات، مثل username/Infinity-Instruct-Chinese-Only (يمكنك جعله خاصاً إذا أردت).
ثم، تأكد من أنك مُوثّق وأنك تستطيع استخدام مصدر البيانات “huggingface”، واضبط mode على “overwrite” (أو “append” إذا أردت توسيع مجموعة بيانات موجودة مسبقاً)، ثم ادفع إلى Hugging Face باستخدام .save():
>>> df_chinese_only.write.format("huggingface").mode("overwrite").save("username/Infinity-Instruct-Chinese-Only")

الوضع
يتوفر وضعان عند دفع مجموعة بيانات إلى Hugging Face:
- “overwrite”: تجاوز مجموعة البيانات إذا كانت موجودة بالفعل
- “append”: إضافة مجموعة البيانات إلى مجموعة بيانات موجودة
خيارات
فيما يلي قائمة بالخيارات المتاحة التي يمكنك تمريرها إلى write.option():
token(نص): رمز Hugging Face الخاص بك
نرحب بالمساهمات لإضافة المزيد من الخيارات هنا، ولا سيما subset وsplit.
دلاء التخزين
من الشائع معالجة البيانات الخام في Storage Buckets والتجربة فيها قبل نشر البيانات الجاهزة للذكاء الاصطناعي في مستودعات مجموعات البيانات.
الوصول إلى دلاء التخزين بنفس طريقة مستودعات مجموعات البيانات، لكن مع بادئة buckets/ وخيارات data_dir أو data_files:
>>> df = spark.read.format("huggingface").option("data_dir", "data").load("buckets/username/my-bucket")
>>> # OR with a glob pattern
>>> # df = spark.read.format("huggingface").option("data_files", "data/*.parquet").load("buckets/username/my-bucket")
>>> df.write.format("huggingface").option("data_dir", "new-data").save("buckets/username/my-bucket")