Зачем это нужно
Теория Feature Store становится реальной, когда вы создаёте feature repo, подключите offline/online stores и запустите materialization. Feast — практичный выбор для учебного кластера MDP: Python-native, работает с Parquet + Redis, хорошо ложится в GitOps.
Урок — пошаговый ориентир: структура проекта, ключевые файлы, типовой workflow DS/MLE.
Основные идеи
Feature repository — структура (Feast 0.3x+):
feature_repo/ ├── feature_store.yaml # registry, offline/online store config ├── entities.py # Entity definitions ├── data_sources.py # BatchSource, StreamSource ├── feature_views.py # FeatureView + schema └── materialize.py # CLI scripts / cron entrypoint
feature_store.yaml (упрощённо):
project: churn_ml registry: s3://ml-feast/registry.db provider: local offline_store: type: file online_store: type: redis connection_string: "redis://feast-redis.ml.svc:6379" entity_key_serialization_version: 2
Prod: offline type: spark или cloud DWH; registry в durable storage.
Entity:
` from feast import Entity
customer = Entity( name="customer_id", description="CRM customer identifier", join_keys=["customer_id"], ) `
Data source + Feature view:
` from feast import FeatureView, Field, FileSource from feast.types import Float32, Int64 from datetime import timedelta
customer_stats_source = FileSource( path="s3://ml-gold/churn/customer_stats/", timestamp_field="event_timestamp", )
customer_features = FeatureView( name="customer_features", entities=[customer], ttl=timedelta(days=90), schema=[ Field(name="avg_check_30d", dtype=Float32), Field(name="tx_count_7d", dtype=Int64), ], source=customer_stats_source, online=True, ) `
Workflow:
feast apply— регистрирует definitions в registry.Spark job пишет Parquet с
event_timestamp(не путать с ingestion time).feast materialize 2026-01-01T00:00:00 2026-01-15T23:59:59— offline → online.feast materialize-incremental $(date -u +%Y-%m-%dT%H:%M:%S)— для cron.
Historical features для train:
` from feast import FeatureStore import pandas as pd
store = FeatureStore(repo_path="feature_repo/")
entity_df = pd.read_parquet("labels.parquet") # customer_id, event_timestamp, churn
training_df = store.get_historical_features( entity_df=entity_df, features=[ "customer_features:avg_check_30d", "customer_features:tx_count_7d", ], ).to_df() `
Online features для inference:
feature_vector = store.get_online_features( features=["customer_features:avg_check_30d", "customer_features:tx_count_7d"], entity_rows=[{"customer_id": "c-9912"}], ).to_dict()
Deployment в K8s.
Feast не обязан быть long-running server для базового Redis backend — client SDK в inference Pod.
Optional: Feast feature server (REST) для языков без SDK.
Redis: StatefulSet + PVC или managed Redis; backup policy для online store.
CI для feature repo.
MR → lint definitions →
feast apply --dry-runили test project.Breaking change (rename feature) → major version нового FeatureView, deprecate старый.
Типовые ошибки.
| Ошибка | Симптом |
|---|---|
Нет event_timestamp в source |
Historical join wrong |
| Забыли materialize | Online store stale / empty |
| TTL слишком короткий | Missing features at inference |
Разные project train vs serve |
Registry mismatch |
Как это выглядит на практике
Capstone integration:
Repo
ml-churn-featuresв GitLab.Spark job (6.3.2) пишет
customer_stats/daily.Argo CronWorkflow 07:00 UTC:
feast materialize-incremental.ClearML train читает historical features через Feast SDK.
KServe inference Pod: init container optional; main container calls
get_online_featuresbefore MLServer predict.
Monitoring:
Age of last materialization (custom metric).
% null features in online responses (связь с модулем 5.3.4).
Redis memory usage.
Local dev:
cd feature_repo feast apply feast materialize 2026-01-01T00:00:00 2026-01-10T00:00:00 feast ui # explore registry locally
Что сделать после занятия
Создайте минимальный
feature_store.yaml+ one Entity + one FeatureView (можно на local paths).Выполните
feast applyи объясните, что попало в registry.Опишите cron schedule materialization для daily batch features.