# fenic

[fenic](https://github.com/typedef-ai/fenic) — это фреймворк для работы с DataFrame, вдохновлённый PySpark, предназначенный для создания производственных AI- и агентных приложений. fenic поддерживает чтение наборов данных непосредственно из Hugging Face Hub.

## Начало работы

Для начала установите `fenic` с помощью pip:

```bash
pip install fenic
```

### Создание сессии

Создайте сессию fenic с конфигурацией по умолчанию (достаточно для чтения наборов данных и других операций, не связанных с семантикой):

```python
import fenic as fc

session = fc.Session.get_or_create(fc.SessionConfig())
```

## Обзор

fenic — это фреймворк обработки данных с чёткой архитектурной позицией, который объединяет:
- **API DataFrame**: операции, вдохновлённые PySpark, для привычной работы с данными
- **Семантические операции**: встроенные операции ИИ/LLM, включая семантические функции, эмбеддинги и кластеризацию
- **Интеграция моделей**: Нативная поддержка провайдеров ИИ (Anthropic, OpenAI, Cohere, Google)
- **Оптимизация запросов**: автоматическая оптимизация с помощью преобразований логического плана

## Чтение из Hugging Face Hub

fenic может читать наборы данных напрямую из Hugging Face Hub с помощью протокола `hf://`. Эта функция встроена в интерфейс DataFrameReader fenic.

### Поддерживаемые форматы

fenic поддерживает чтение следующих форматов из Hugging Face:
- **Файлы Parquet** (`.parquet`)
- **Файлы CSV** (`.csv`)

### Чтение наборов данных

Чтобы прочитать набор данных из Hugging Face Hub:

```python
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")
```

### Чтение с управлением схемой

```python
# 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 и расширяя типы там, где это возможно. Некоторые структуры всё же не поддаются объединению — обратитесь к документации fenic по [ограничениям слияния схем CSV](https://docs.fenic.ai/latest/reference/fenic/?h=parquet#fenic.DataFrameReader.csv) и [ограничениям слияния схем Parquet](https://docs.fenic.ai/latest/reference/fenic/?h=parquet#fenic.DataFrameReader.parquet).

### Аутентификация

Чтобы читать приватные наборы данных, необходимо задать токен Hugging Face в качестве переменной окружения:

```shell
export HF_TOKEN="your_hugging_face_token_here"
```

### Формат пути

Формат пути Hugging Face в fenic следует этой структуре:
```
hf://{repo_type}/{repo_id}/{path_to_file}
```

Вы также можете указать ревизии или версии набора данных:
```
hf://{repo_type}/{repo_id}@{revision}/{path_to_file}
```

Возможности:
- Поддерживает глобальные шаблоны (`*`, `**`)
- Ревизии/версии датасетов с использованием нотации `@`:
  - Конкретный коммит: `@d50d8923b5934dc8e74b66e6e4b0e2cd85e9142e`
  - Ветка: `@refs/convert/parquet`
  - Псевдоним ветки: `@~parquet`
- Требуется переменная окружения `HF_TOKEN` для частных наборов данных

### Смешивание источников данных

fenic позволяет объединять несколько источников данных в одной операции чтения, включая смешивание разных протоколов:

```python
# 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 вы можете использовать полный API DataFrame от fenic:

### Базовые операции с DataFrame

```python
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")
)
```

### Операции на базе ИИ

Для использования семантических и эмбеддинг-операций настройте языковые и эмбеддинг-модели в вашем SessionConfig. После настройки:

```python
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

```python
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()
```

## Ресурсы

- [Репозиторий fenic на GitHub](https://github.com/typedef-ai/fenic)
- [Документация fenic](https://docs.fenic.ai/latest/)

