Hub documentation
Spark
Spark
Spark์ ๋ถ์ฐ ํ๊ฒฝ์์ ์ค์๊ฐ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค.
pyspark_huggingface๋ฅผ ์ฌ์ฉํ๋ฉด โhuggingfaceโ Data Source๋ฅผ ํตํด PySpark์์ Hugging Face datasets ์ ์ฅ์์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
Hugging Face Spaces์์ Spark Notebooks๋ฅผ ์ฌ์ฉํด ๋ณด์ธ์. PySpark์ pyspark_huggingface๊ฐ ๋ฏธ๋ฆฌ ์ค์น๋ Notebooks๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ค์
์ค์น
Hugging Face Datasets์ ์ฝ๊ณ ์ฐ๊ธฐ ์ํด pyspark_huggingface ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ผ ํฉ๋๋ค:
pip install pyspark_huggingface์ด ๋ช
๋ น์ ์ธ์ฆ์ ์ํ huggingface_hub์ ๋ฐ์ดํฐ์
์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ๋ฅผ ์ํ pyarrow์ ๊ฐ์ ํ์ํ ์ข
์์ฑ๋ ์ค์นํฉ๋๋ค.
์ธ์ฆ
Hugging Face์ ์ธ์ฆํด์ผ ๋น๊ณต๊ฐ/๊ฒ์ดํธ๋ ๋ฐ์ดํฐ์ ์ ์ฅ์๋ฅผ ์ฝ๊ฑฐ๋ ๋ฐ์ดํฐ์ ์ ์ฅ์์ ์ธ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด CLI๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
hf auth loginHF_TOKEN ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๊ฑฐ๋ ๋ฆฌ๋์ token ์ต์
์ ์ ๋ฌํ์ฌ Hugging Face ํ ํฐ์ ์ ๊ณตํ ์๋ ์์ต๋๋ค.
์ธ์ฆ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ด ๊ฐ์ด๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
โhuggingfaceโ ๋ฐ์ดํฐ ์์ค ํ์ฑํ
PySpark 4์๋ ์ปค์คํ
์์ค์ ๋ฐ์ดํฐ์
์ ์ฌ์ฉํ ์ ์๋ ์๋ก์ด Data Source API๊ฐ ๋์
๋์์ต๋๋ค.
pyspark_huggingface๊ฐ ์ค์น๋์ด ์์ผ๋ฉด PySpark๊ฐ ์ด๋ฅผ ์๋์ผ๋ก ๊ฐ์ ธ์ โhuggingfaceโ Data Source๋ฅผ ํ์ฑํํฉ๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ PySpark 3.5, 3.4, 3.3์ ๋ํด โhuggingfaceโ Data Source์ Data Source API๋ฅผ ๋ฐฑํฌํธํฉ๋๋ค.
๋ค๋ง ์ด ๊ฒฝ์ฐ ๋ฐฑํฌํธ๋ฅผ ํ์ฑํํ๊ณ โhuggingfaceโ Data Source๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด pyspark_huggingface๋ฅผ ๋ช
์์ ์ผ๋ก ๊ฐ์ ธ์์ผ ํฉ๋๋ค:
>>> import pyspark_huggingface
huggingface datasource enabled for pyspark 3.x.x (backport from pyspark 4)์ฝ๊ธฐ
โhuggingfaceโ Data Source๋ pyarrow๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Arrow ๋ฐ์ดํฐ๋ฅผ ์คํธ๋ฆฌ๋ฐํ์ฌ Hugging Face์์ ๋ฐ์ดํฐ์
์ ์ฝ์ ์ ์์ต๋๋ค.
์ด๋ 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โ Data Source๋ฅผ ์ฌ์ฉํ๊ณ , .load()๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ์
(๋ ์ ํํ๋ 7M ์ํ์ ํฌํจํ๋ โ7Mโ์ด๋ผ๋ ์ด๋ฆ์ config ๋๋ subset)์ ๋ก๋ํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ธ์ด๋ณ ๋ํ ์๋ฅผ ๊ณ์ฐํ๊ณ ๋ฐ์ดํฐ์
์ ํํฐ๋งํฉ๋๋ค.
๊ฒ์ดํธ๋ ์ ์ฅ์์ ์ก์ธ์คํ๊ธฐ ์ํด ๋ก๊ทธ์ธํ ํ, ๋ค์์ ์คํํ ์ ์์ต๋๋ค:
>>> 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|
+---+----------------------------+-----+----------+--------------------+์ด๊ฒ์ ๋ฐ์ดํฐ์ ์ ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ๋ก๋ํ๋ฉฐ, ์ถ๋ ฅ DataFrame์ ๋ฐ์ดํฐ์ ์ ๊ฐ ๋ฐ์ดํฐ ํ์ผ๋น ํ๋์ ํํฐ์ ์ ๊ฐ๋๋ก ํ์ฌ ํจ์จ์ ์ธ ๋ถ์ฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
์ธ์ด๋ณ ๋ํ ์๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด columns ์ต์
๊ณผ groupBy() ์ฐ์ฐ์ ์ฌ์ฉํ๋ ๋ค์ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค.
columns ์ต์
์ PySpark๊ฐ Data Source API์์ predicate push-down์ ์ง์ํ์ง ์์ผ๋ฏ๋ก ํ์ํ ๋ฐ์ดํฐ๋ง ๋ก๋ํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
ํน์ ๋ฒ์์ ๊ฐ์ ๊ฐ์ง ๋ฐ์ดํฐ๋ง ๋ก๋ํ๊ธฐ ์ํ 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๋ ํ์ผ ๋ฐ row group ์์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ ์์ด, ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ์ํ์ด ์๋ ๋ฐ์ดํฐ์ ์ ์ผ๋ถ ์ ์ฒด๋ฅผ ๊ฑด๋๋ธ ์ ์์ต๋๋ค. Parquet์ ์ปฌ๋ผ์ ๋ ๋ฆฝ์ ์ผ๋ก ๋ก๋ํ ์๋ ์์ด, ์ ์ธ๋ ์ปฌ๋ผ์ ๊ฑด๋๋ฐ๊ณ ๋ถํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ์ง ์๋๋ก ํ ์ ์์ต๋๋ค.
์ต์
read..option()์ ์ ๋ฌํ ์ ์๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์ต์
๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
config(string): ๋ฐ์ดํฐ์ ์ ํ์ ์งํฉ/์ค์ ์ ์ ํํฉ๋๋คsplit(string): ๋ฐ์ดํฐ์ ์คํ๋ฆฟ์ ์ ํํฉ๋๋ค (๊ธฐ๋ณธ๊ฐ์ โtrainโ์ ๋๋ค)token(string): Hugging Face ํ ํฐ
config๋ split์ ์ง์ ํ๋ ๋์ , ๋ก๋ํ ํ์ผ์ ์๋์ผ๋ก ์ ํํ ์ ์์ต๋๋ค:
data_dir(string): ๋๋ ํฐ๋ฆฌ ์ ํdata_files(string): ํ๋ ์ด์์ ํ์ผ์ ์ ํํฉ๋๋ค. ์:"data/*.parquet"๋๋'["part1.parquet", "par2.parquet"]'
Parquet ๋ฐ์ดํฐ์ ์ ๊ฒฝ์ฐ:
columns(string): ๋ก๋ํ ์ปฌ๋ผ์ ํ์ ์งํฉ์ ์ ํํฉ๋๋ค. ์:'["id"]'filters(string): ๊ธฐ์ค์ ๋ง์ง ์๋ ํ์ผ๊ณผ row group์ ๊ฑด๋๋ฐ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค. ์:'[("source", "=", "code_exercises")]'. ํํฐ๋ pyarrow.parquet.ParquetDataset์ ์ ๋ฌ๋ฉ๋๋ค.
๊ธฐํ ์ต์ ์ ๋ชจ๋ [datasets.load_dataset] (https://huggingface.co/docs/datasets/en/package_reference/loading_methods#datasets.load_dataset)์ ์ธ์๋ก ์ ๋ฌ๋ฉ๋๋ค.
SQL ์ฟผ๋ฆฌ ์คํ
PySpark Dataframe๊ฐ ์ค๋น๋๋ฉด spark.sql์ ์ฌ์ฉํ์ฌ 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 ์ต์
์ ์ง์ ํ๋ ๊ฒ์ ํ์์ ์ด์ง ์์ง๋ง, ๋ถํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ์ง ์๊ณ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋น ๋ฅด๊ฒ ์คํํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
์ฐ๊ธฐ
โhuggingfaceโ Data Source๋ฅผ ์ฌ์ฉํ์ฌ PySpark Dataframe์ Hugging Face์ ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ Parquet ํ์ผ์ ๋ถ์ฐ ๋ฐฉ์์ผ๋ก ๋ณ๋ ฌ๋ก ์ ๋ก๋ํ๊ณ , ๋ชจ๋ ํ์ผ์ด ์ ๋ก๋๋ ํ์๋ง ํ์ผ์ ์ปค๋ฐํฉ๋๋ค. ๋์ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
>>> import pyspark_huggingface
>>> df.write.format("huggingface").save("username/dataset_name")์ด ํจ์๋ฅผ ์ฌ์ฉํ์ฌ BAAI/Infinity-Instruct ๋ฐ์ดํฐ์ ์ ํํฐ๋ง๋ ๋ฒ์ ์ Hugging Face์ ๋ค์ ์ฐ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋จผ์ ๋ฐ์ดํฐ์
์ ์ฅ์๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด username/Infinity-Instruct-Chinese-Only (์ํ๋ ๊ฒฝ์ฐ ๋น๊ณต๊ฐ๋ก ์ค์ ํ ์ ์์ต๋๋ค).
๊ทธ ๋ค์, ์ธ์ฆ์ด ๋์ด ์๊ณ โhuggingfaceโ Data Source๋ฅผ ์ฌ์ฉํ ์ ์๋์ง ํ์ธํ ํ, mode๋ฅผ โoverwriteโ๋ก ์ค์ ํฉ๋๋ค(๊ธฐ์กด ๋ฐ์ดํฐ์
์ ํ์ฅํ๋ ค๋ฉด โappendโ๋ก ์ค์ ). ๊ทธ๋ฆฌ๊ณ .save()๋ฅผ ์ฌ์ฉํ์ฌ Hugging Face์ pushํฉ๋๋ค:
>>> df_chinese_only.write.format("huggingface").mode("overwrite").save("username/Infinity-Instruct-Chinese-Only")

๋ชจ๋
Hugging Face์ ๋ฐ์ดํฐ์ ์ ํธ์ํ ๋ ์ฌ์ฉํ ์ ์๋ ๋ ๊ฐ์ง ๋ชจ๋๊ฐ ์์ต๋๋ค:
- โoverwriteโ: ์ด๋ฏธ ์กด์ฌํ๋ ๋ฐ์ดํฐ์ ์ ๋ฎ์ด์ฐ๊ธฐ
- โappendโ: ๊ธฐ์กด ๋ฐ์ดํฐ์ ์ ๋ฐ์ดํฐ์ ์ ์ถ๊ฐ
์ต์
write.option()์ ์ ๋ฌํ ์ ์๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์ต์
๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
token(string): Hugging Face ํ ํฐ
์ฌ๊ธฐ์ ๋ ๋ง์ ์ต์
์ ์ถ๊ฐํ๋ ๊ธฐ์ฌ๋ฅผ ํ์ํฉ๋๋ค. ํนํ subset์ split์ ๋ํด.
Storage Buckets
It is common to process raw data in Storage Buckets and experiment there before publishing AI-ready data in Dataset repositories.
Dataset ์ ์ฅ์์ ๋์ผํ ๋ฐฉ์์ผ๋ก 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")