Skip to main content

Lightweight feature store for small and medium teams

Project description

feature-forge

Lightweight feature store for small and medium ML teams. Define features in YAML, get point-in-time correct data with one method call. No infrastructure required.

Install

pip install fforge

With optional backends:

pip install fforge[databricks]   # Databricks Unity Catalog
pip install fforge[spark]        # PySpark engine
pip install fforge[all]          # Everything

What it does

  • Point-in-time correct joins: for each row in your data, features are computed using only past information. No data leakage.
  • YAML-based feature definitions: entities, sources, and features are declared in version-controlled YAML files.
  • Multiple data sources: Parquet (local), S3/GCS/Azure, SQLite/PostgreSQL, Databricks Unity Catalog.
  • Two query engines: DuckDB (default, zero-config) or PySpark (for Spark clusters).
  • One method for everything: get_features_table() handles training, inference, and historical backfill.
  • CLI included: init, validate, list, describe, materialize.

Quickstart

1. Initialize

feature-forge init my_features/

2. Define (edit the generated YAML files)

# entities.yml
entities:
  - name: customer
    join_keys: [customer_id]
# sources.yml
sources:
  - name: transactions
    backend: parquet
    path: data/transactions.parquet
    entity: customer
    timestamp_column: event_timestamp
    columns:
      - { name: customer_id, dtype: int64 }
      - { name: amount, dtype: float64 }
      - { name: event_timestamp, dtype: timestamp }
# features.yml
feature_views:
  - name: customer_features
    entity: customer
    source: transactions
    features:
      - name: txn_count_7d
        dtype: int64
        aggregation: { function: count, column: amount, window: 7d }
      - name: avg_amount_30d
        dtype: float64
        aggregation: { function: avg, column: amount, window: 30d }

3. Validate

feature-forge validate --repo my_features/

4. Use

from feature_forge import FeatureStore
import pandas as pd

store = FeatureStore("my_features/")

labels = pd.DataFrame({
    "customer_id": [101, 102],
    "event_timestamp": pd.to_datetime(["2025-03-15", "2025-03-20"]),
    "is_fraud": [1, 0],
})

df = store.get_features_table(
    entity_df=labels,
    feature_views=["customer_features"],
)
# customer_id | event_timestamp | is_fraud | txn_count_7d | avg_amount_30d
# Each row uses ONLY data before its timestamp

Example: training, inference, and backfill

from feature_forge import FeatureStore

store = FeatureStore("my_features/")

# TRAINING: pass labeled data with historical timestamps
training_df = store.get_features_table(
    entity_df=labels_df,
    feature_views=["customer_features"],
)

# INFERENCE: pass entity IDs, features computed as of now
inference_df = store.get_features_table(
    entity_ids={"customer_id": [101, 102, 103]},
    feature_views=["customer_features"],
)

# BACKFILL: entity IDs + date range for historical scoring
backfill_df = store.get_features_table(
    entity_ids={"customer_id": [101, 102]},
    feature_views=["customer_features"],
    start_date="2025-01-01",
    end_date="2025-06-01",
    interval="1d",
)

store.close()

Same method, same PIT guarantees. The behavior changes based on which parameters you pass.

Documentation

Guide Description
Getting Started 5-minute setup
Defining Features Entities, sources, aggregation vs passthrough
Retrieving Features Training, inference, backfill modes
Backends Parquet, S3, SQL, Databricks configuration
Engines DuckDB vs PySpark
Materialization Pre-compute and save to Parquet
CLI Reference All commands and flags

Development

git clone https://github.com/pydoni/feature-forge.git
cd feature-forge
uv sync --extra dev
uv run pytest

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fforge-1.0.1.tar.gz (47.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fforge-1.0.1-py3-none-any.whl (36.5 kB view details)

Uploaded Python 3

File details

Details for the file fforge-1.0.1.tar.gz.

File metadata

  • Download URL: fforge-1.0.1.tar.gz
  • Upload date:
  • Size: 47.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fforge-1.0.1.tar.gz
Algorithm Hash digest
SHA256 b91d528fc3065dbb2375db45564da554ab91e980f0146027bd6948cfdffebc1c
MD5 5d26548d42b10fe6570d6fb1e57262f0
BLAKE2b-256 a313682f87b1bf1c8c3512a615d479f1f7d4d0aeb5c75f196b8b54158bc9dcb6

See more details on using hashes here.

File details

Details for the file fforge-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: fforge-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 36.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fforge-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 507fd73b17f9e811b74e3bb10d6f70f6b494d7013ed9c0065cdf5dd6da94b3ad
MD5 95dc5e7b0d39d34e0eb53711e76cb10f
BLAKE2b-256 41ed999bd44726b313be31062d026618aa7bd3035de28acbce3ceffb069b47bc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page