Hub documentation
fenic
fenic
fenic์ PySpark์์ ์๊ฐ์ ๋ฐ์ DataFrame ํ๋ ์์ํฌ๋ก, ํ๋ก๋์ AI ๋ฐ ์์ด์ ํฑ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๊ธฐ ์ํด ์ค๊ณ๋์์ต๋๋ค. fenic์ Hugging Face Hub์์ ๋ฐ์ดํฐ์ ์ ์ง์ ์ฝ๋ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค.

์์ํ๊ธฐ
์์ํ๋ ค๋ฉด fenic์ pip๋ก ์ค์นํ์ธ์:
pip install fenic
์ธ์ ๋ง๋ค๊ธฐ
๊ธฐ๋ณธ ๊ตฌ์ฑ์ผ๋ก fenic ์ธ์ ์ ์ด๊ธฐํํฉ๋๋ค(๋ฐ์ดํฐ์ ์ฝ๊ธฐ ๋ฐ ๊ธฐํ ๋น์๋ฏธ๋ก ์ ์์ ์ ์ถฉ๋ถํฉ๋๋ค):
import fenic as fc
session = fc.Session.get_or_create(fc.SessionConfig())๊ฐ์
fenic๋ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ฒฐํฉํ ์๊ฒฌ์ด ๋ด๊ธด ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ๋ ์์ํฌ์ ๋๋ค:
- DataFrame API: PySpark์์ ์๊ฐ์ ๋ฐ์ ์น์ํ ๋ฐ์ดํฐ ์กฐ์์ ์ํ ์ฐ์ฐ
- ์๋ฏธ๋ก ์ ์ฐ์ฐ: ์๋ฏธ๋ก ์ ํจ์, ์๋ฒ ๋ฉ, ํด๋ฌ์คํฐ๋ง์ ํฌํจํ ๋ด์ฅ AI/LLM ์ฐ์ฐ
- ๋ชจ๋ธ ํตํฉ: AI ์ ๊ณต์ ์ฒด(Anthropic, OpenAI, Cohere, Google)์ ๋ํ ๋ค์ดํฐ๋ธ ์ง์
- ์ฟผ๋ฆฌ ์ต์ ํ: ๋ ผ๋ฆฌ ๊ณํ ๋ณํ์ ํตํ ์๋ ์ต์ ํ
Hugging Face Hub์์ ์ฝ๊ธฐ
fenic์ hf:// ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ Hugging Face Hub์์ ๋ฐ์ดํฐ์
์ ์ง์ ์ฝ์ ์ ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ fenic์ DataFrameReader ์ธํฐํ์ด์ค์ ๋ด์ฅ๋์ด ์์ต๋๋ค.
์ง์๋๋ ํ์
fenic์ Hugging Face์์ ๋ค์ ํ์์ ์ฝ๋ ๊ฒ์ ์ง์ํฉ๋๋ค:
- Parquet ํ์ผ (
.parquet) - CSV ํ์ผ (
.csv)
๋ฐ์ดํฐ์ ์ฝ๊ธฐ
Hugging Face Hub์์ ๋ฐ์ดํฐ์ ์ ์ฝ์ผ๋ ค๋ฉด:
import fenic as fc
session = fc.Session.get_or_create(fc.SessionConfig())
# Read a CSV file from a public dataset
df = session.read.csv("hf://datasets/datasets-examples/doc-formats-csv-1/data.csv")
# Read Parquet files using glob patterns
df = session.read.parquet("hf://datasets/cais/mmlu/astronomy/*.parquet")
# Read from a specific dataset revision
df = session.read.parquet("hf://datasets/datasets-examples/doc-formats-csv-1@~parquet/**/*.parquet")์คํค๋ง ๊ด๋ฆฌ์ ํจ๊ป ์ฝ๊ธฐ
# Read multiple CSV files with schema merging
df = session.read.csv("hf://datasets/username/dataset_name/*.csv", merge_schemas=True)
# Read multiple Parquet files with schema merging
df = session.read.parquet("hf://datasets/username/dataset_name/*.parquet", merge_schemas=True)์ฐธ๊ณ : fenic์์ ์คํค๋ง๋ ์ปฌ๋ผ ์ด๋ฆ๊ณผ ํด๋น ๋ฐ์ดํฐ ํ์ ์ ์งํฉ์ ์๋ฏธํฉ๋๋ค.
merge_schemas๋ฅผ ํ์ฑํํ๋ฉด fenic์ ๋๋ฝ๋ ์ปฌ๋ผ์ null์ ์ฑ์ฐ๊ณ ๊ฐ๋ฅํ ๊ฒฝ์ฐ ํ์ ์ ํ์ฅํ์ฌ ํ์ผ ๊ฐ ์ฐจ์ด๋ฅผ ์กฐ์ ํ๋ ค๊ณ ํฉ๋๋ค. ์ผ๋ถ ๋ ์ด์์์ ๋ณํฉํ ์ ์์ผ๋ฏ๋ก CSV ์คํค๋ง ๋ณํฉ ์ ํ ์ฌํญ ๋ฐ Parquet ์คํค๋ง ๋ณํฉ ์ ํ ์ฌํญ์ ๋ํด fenic ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์.
์ธ์ฆ
๋น๊ณต๊ฐ ๋ฐ์ดํฐ์ ์ ์ฝ์ผ๋ ค๋ฉด Hugging Face ํ ํฐ์ ํ๊ฒฝ ๋ณ์๋ก ์ค์ ํด์ผ ํฉ๋๋ค:
export HF_TOKEN="your_hugging_face_token_here"
๊ฒฝ๋ก ํ์
fenic์ Hugging Face ๊ฒฝ๋ก ํ์์ ๋ค์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฆ ๋๋ค:
hf://{repo_type}/{repo_id}/{path_to_file}๋ฐ์ดํฐ์ ์ ๋ฆฌ๋น์ ๋๋ ๋ฒ์ ์ ์ง์ ํ ์๋ ์์ต๋๋ค:
hf://{repo_type}/{repo_id}@{revision}/{path_to_file}๊ธฐ๋ฅ:
- glob ํจํด(
*,**)์ ์ง์ํฉ๋๋ค - Dataset์ revision/version์ ์ฌ์ฉํ ๋
@๊ธฐํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค:- ํน์ ์ปค๋ฐ:
@d50d8923b5934dc8e74b66e6e4b0e2cd85e9142e - Branch:
@refs/convert/parquet - Branch alias:
@~parquet
- ํน์ ์ปค๋ฐ:
- ๋น๊ณต๊ฐ ๋ฐ์ดํฐ์
์ ๊ฒฝ์ฐ
HF_TOKENํ๊ฒฝ ๋ณ์๊ฐ ํ์ํฉ๋๋ค
๋ฐ์ดํฐ ์์ค ํผํฉ
fenic์ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ๋ฐ์ดํฐ ์์ค๋ฅผ ๋จ์ผ ์ฝ๊ธฐ ์์ ์ผ๋ก ๊ฒฐํฉํ ์ ์์ผ๋ฉฐ, ์๋ก ๋ค๋ฅธ ํ๋กํ ์ฝ์ ํผํฉํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค:
# Mix HF and local files in one read call
df = session.read.parquet([
"hf://datasets/cais/mmlu/astronomy/*.parquet",
"file:///local/data/*.parquet",
"./relative/path/data.parquet"
])์ด๋ฌํ ์ ์ฐ์ฑ์ ํตํด Hugging Face Hub์ ๋ฐ์ดํฐ์ ๋ก์ปฌ ํ์ผ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์ ์์ฐ์ค๋ฝ๊ฒ ๊ฒฐํฉํ ์ ์์ต๋๋ค.
Hugging Face์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
Hugging Face์์ ๋ก๋ํ ํ, fenic์ ์ ์ฒด DataFrame API๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค:
๊ธฐ๋ณธ DataFrame ์ฐ์ฐ
import fenic as fc
session = fc.Session.get_or_create(fc.SessionConfig())
# Load IMDB dataset from Hugging Face
df = session.read.parquet("hf://datasets/imdb/plain_text/train-*.parquet")
# Filter and select
positive_reviews = df.filter(fc.col("label") == 1).select("text", "label")
# Group by and aggregate
label_counts = df.group_by("label").agg(
fc.count("*").alias("count")
)AI ๊ธฐ๋ฐ ์ด์
semantic ๋ฐ embedding ์ฐ์ฐ์ ์ฌ์ฉํ๋ ค๋ฉด SessionConfig์์ ์ธ์ด ๋ฐ ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค. ๊ตฌ์ฑ์ด ์๋ฃ๋๋ฉด:
import fenic as fc
# Requires OPENAI_API_KEY to be set for language and embedding calls
session = fc.Session.get_or_create(
fc.SessionConfig(
semantic=fc.SemanticConfig(
language_models={
"gpt-4o-mini": fc.OpenAILanguageModel(
model_name="gpt-4o-mini",
rpm=60,
tpm=60000,
)
},
embedding_models={
"text-embedding-3-small": fc.OpenAIEmbeddingModel(
model_name="text-embedding-3-small",
rpm=60,
tpm=60000,
)
},
)
)
)
# Load a text dataset from Hugging Face
df = session.read.parquet("hf://datasets/imdb/plain_text/train-00000-of-00001.parquet")
# Add embeddings to text columns
df_with_embeddings = df.select(
"*",
fc.semantic.embed(fc.col("text")).alias("embedding")
)
# Apply semantic functions for sentiment analysis
df_analyzed = df_with_embeddings.select(
"*",
fc.semantic.analyze_sentiment(
fc.col("text"),
model_alias="gpt-4o-mini", # Optional: specify model
).alias("sentiment")
)์: MMLU ๋ฐ์ดํฐ์ ๋ถ์
import fenic as fc
# Requires OPENAI_API_KEY to be set for semantic calls
session = fc.Session.get_or_create(
fc.SessionConfig(
semantic=fc.SemanticConfig(
language_models={
"gpt-4o-mini": fc.OpenAILanguageModel(
model_name="gpt-4o-mini",
rpm=60,
tpm=60000,
)
},
)
)
)
# Load MMLU astronomy subset from Hugging Face
df = session.read.parquet("hf://datasets/cais/mmlu/astronomy/*.parquet")
# Process the data
processed_df = (df
# Filter for specific criteria
.filter(fc.col("subject") == "astronomy")
# Select relevant columns
.select("question", "choices", "answer")
# Add difficulty analysis using semantic.map
.select(
"*",
fc.semantic.map(
"Rate the difficulty of this question from 1-5: {{question}}",
question=fc.col("question"),
model_alias="gpt-4o-mini" # Optional: specify model
).alias("difficulty")
)
)
# Show results
processed_df.show()