GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — feat: Add MLflow as a first-class offline DataSource for Feast by Vperiodt · Pull Request #6702 · feast-dev/feast

feat: Add MLflow as a first-class offline DataSource for Feast #6702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
ntkathole merged 8 commits into feast-dev:master from Vperiodt:mlflow-datasource
Sep 29, 2026

Uh oh!

There was an error while loading. Please reload this page.

Merged

feat: Add MLflow as a first-class offline DataSource for Feast #6702

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
8 commits
Select commit Hold shift + click to select a range
9a73e1f
add mlflow datasource adaptor
Vperiodt Aug 4, 2026
d6a725c
fix: Correct lint
Vperiodt Aug 10, 2026
e3c8c33
address reviews and fix error handling
Vperiodt Aug 16, 2026
106110f
feat: Close MLflow DataSource scope gaps and add RHOAI E2E suite
Vperiodt Sep 23, 2026
da4bd60
chore: Drop local RHOAI E2E scripts from branch
Vperiodt Sep 23, 2026
24f1df6
chore: Restore protos from master
Vperiodt Sep 23, 2026
56bcc00
chore: Update secrets baseline
Vperiodt Sep 28, 2026
797db4b
chore: Refresh secrets baseline and pixi lock for CI
Vperiodt Sep 29, 2026
File filter
Filter by extension


Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

2 changes: 1 addition & 1 deletion 2 .secrets.baseline
Show comments
View file
Open in desktop

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

1 change: 1 addition & 0 deletions 1 docs/SUMMARY.md
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
* [Adding or reusing tests](how-to-guides/adding-or-reusing-tests.md)
* [Starting Feast servers in TLS(SSL) Mode](how-to-guides/starting-feast-servers-tls-mode.md)
* [Importing Features from dbt](how-to-guides/dbt-integration.md)
* [Using MLflow as a Data Source](how-to-guides/mlflow-datasource.md)
* [Entity Key Serialization (v2 to v3)](how-to-guides/entity-reserialization-of-from-v2-to-v3.md)
* [Feature Quality Monitoring](how-to-guides/feature-monitoring.md)

Expand Down
194 changes: 194 additions & 0 deletions 194 docs/how-to-guides/mlflow-datasource.md
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Using MLflow as a Data Source in Feast

This guide walks through the end-to-end workflow for using MLflow as a **first-class offline DataSource** in Feast. You define `FeatureView` objects backed by `MlflowDatasetSource`, then use `get_historical_features()` and `create_saved_dataset()` without manual export or ETL.

For API reference, see [MLflow Integration](../reference/mlflow.md#mlflow-as-a-datasource). For operator auto-discovery of MLflow on RHOAI, see [Guide 8 — MLflow Integration](feast-operator/08-mlflow-integration.md).

## Overview

| Mode | Use case | Configuration |
|------|----------|---------------|
| **GenAI Dataset** | Curated evaluation / trace records from MLflow GenAI Datasets | `dataset_name` or `dataset_id` |
| **Artifact** | Parquet or CSV artifacts logged on MLflow runs | `run_id`, `artifact_path`, `artifact_format` |

**Scope (Tech Preview):** offline/historical retrieval only; Parquet and CSV tabular artifacts; reads go through the MLflow Tracking API (no direct object-storage bypass).

## Prerequisites

- Feast with MLflow support: `pip install 'feast[mlflow]'` (MLflow ≥ 2.10 for GenAI datasets).
- A reachable MLflow tracking server.
- On RHOAI: Feast and MLflow operators deployed; FeatureStore CR in Ready state; cluster CA bundle available for TLS if using HTTPS.

## Step 1: Configure `feature_store.yaml`

```yaml
project: my_project
registry: data/registry.db
provider: local
offline_store: duckdb
online_store:
type: sqlite
path: data/online_store.db
entity_key_serialization_version: 3

mlflow:
enabled: true
tracking_uri: https://mlflow.example.com:8443
ca_bundle: /etc/pki/tls/certs/ca-bundle.crt
supported_artifact_formats:
- parquet
- csv
request_timeout: 30 # seconds per HTTP request to MLflow (default: 30)
max_retries: 3 # retry attempts for transient failures (default: 3)
retry_backoff_factor: 1.0 # exponential backoff base (default: 1.0 → 1s, 2s, 4s)
```

On operator-managed clusters, `tracking_uri` and `ui_url` are often injected automatically when an `MLflow` CR is present. You can still set `ca_bundle` explicitly for DataSource reads from a workbench or CI job.

| Field | Default | Description |
|---|---|---|
| `tracking_uri` | `MLFLOW_TRACKING_URI` env | MLflow tracking server URI |
| `ca_bundle` | `None` | CA bundle path for TLS (falls back to `REQUESTS_CA_BUNDLE` env) |
| `supported_artifact_formats` | `["parquet", "csv"]` | Accepted artifact formats |
| `request_timeout` | `30` | Seconds per HTTP request to MLflow |
| `max_retries` | `3` | Retry attempts for transient failures (timeouts, 5xx) |
| `retry_backoff_factor` | `1.0` | Exponential backoff base (wait = factor × 2^attempt) |

## Step 2: Define `MlflowDatasetSource` FeatureViews

`MlflowDatasetSource` is read-only. You must set a `batch_source` (for example `FileSource`) for writeback paths such as `create_saved_dataset()` and materialization.

### GenAI Dataset mode

```python
from feast import Entity, FeatureView, Field, FileSource
from feast.infra.data_sources.mlflow import MlflowDatasetSource
from feast.types import String

batch_sink = FileSource(
path="data/eval_records.parquet",
timestamp_field="event_timestamp",
)

source = MlflowDatasetSource(
name="eval_dataset",
dataset_name="production_validation_set",
batch_source=batch_sink,
timestamp_field="event_timestamp",
field_mapping={"expectations.expected_response": "expected_response"},
)

eval_records = FeatureView(
name="eval_records",
entities=[Entity(name="record_id", join_keys=["record_id"])],
schema=[Field(name="expected_response", dtype=String)],
source=source,
)
```

### Artifact mode (Parquet)

```python
source = MlflowDatasetSource(
name="training_features",
run_id="<mlflow-run-id>",
artifact_path="outputs/features.parquet",
artifact_format="parquet",
batch_source=FileSource(
path="data/features.parquet",
timestamp_field="event_timestamp",
),
timestamp_field="event_timestamp",
)

training_features = FeatureView(
name="training_features",
entities=[Entity(name="record_id", join_keys=["record_id"])],
schema=[...],
source=source,
)
```

## Step 3: Apply and validate

```bash
feast apply
feast mlflow list-sources
feast mlflow validate-source eval_records
```

`validate-source` checks configuration, MLflow reachability, schema introspection, and schema match against the FeatureView.

## Step 4: Retrieve historical features and save datasets

```python
from feast import FeatureStore

store = FeatureStore(".")

job = store.get_historical_features(
entity_df=entity_df,
features=["eval_records:expected_response"],
)
training_df = job.to_df()

from feast.data_format import ParquetFormat
from feast.infra.offline_stores.file_source import SavedDatasetFileStorage

storage = SavedDatasetFileStorage(
path="data/saved_eval.parquet",
file_format=ParquetFormat(),
)

saved = store.create_saved_dataset(
from_=job,
name="eval_training_snapshot",
storage=storage,
)

loaded = store.get_saved_dataset("eval_training_snapshot")
assert loaded.to_df().shape == training_df.shape
```

Feast primitives in scope: **`get_historical_features()`** and **`SavedDataset`** (via `create_saved_dataset()` / `get_saved_dataset()`).

## Step 5: Dataset sync (Tier 3 offline stores)

For BigQuery, Snowflake, or Redshift, sync MLflow GenAI data into the offline store first:

```bash
feast mlflow sync-dataset --feature-view eval_records
feast mlflow sync-dataset --feature-view eval_records --dry-run
feast mlflow preview-dataset --source production_validation_set --limit 10
```

## Authentication

Feast resolves tokens in this order for DataSource reads:

1. User Bearer token from the current Feast API request (REST / Arrow Flight).
2. `MLFLOW_TRACKING_TOKEN` environment variable.
3. Kubernetes ServiceAccount token file (when present).

Feast registers `FeastMLflowHeaderProvider` as an MLflow `request_header_provider` plugin. When a token is active in context, it sets `Authorization: Bearer <token>` on MLflow REST calls.

### Coexistence with `MLFLOW_TRACKING_AUTH`

The Feast operator may inject `MLFLOW_TRACKING_AUTH=kubernetes-namespaced` for pod-level MLflow access. That uses MLflow’s **auth provider** plugin (ServiceAccount token). Feast’s **header provider** runs in parallel; when a ContextVar token is set (user request or `MLFLOW_TRACKING_TOKEN`), the header provider’s `Authorization` value is used for DataSource reads. Automated jobs without a user token continue to rely on kubernetes-namespaced auth.

## Troubleshooting

| Symptom | What to check |
|---------|----------------|
| `ImportError` for `mlflow` | `pip install 'feast[mlflow]'` |
| Connection / timeout errors | `tracking_uri`, network, `ca_bundle`, MLflow pod health |
| HTTP 401 / 403 | Token validity and MLflow RBAC on the target experiment or artifact |
| Unsupported format | Only `parquet` and `csv` are supported in TP |
| Missing artifact / dataset | Run ID, artifact path, or dataset name; 404 errors include context in the message |

## Limitations (Tech Preview)

- No online store integration with MLflow.
- No pickle or other non-tabular artifact formats.
- No bypass of MLflow’s auth layer via direct object storage.
- Operator FeatureStore CR fields for DataSource-specific MLflow config may evolve in follow-up releases.
18 changes: 18 additions & 0 deletions 18 docs/reference/feast-cli-commands.md
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,24 @@ feast registry create-schema

This command only applies to SQL-based registries (`registry_type: sql`). It is safe to run multiple times — existing tables are not modified.

## MLflow

MLflow integration utilities for GenAI dataset sync and DataSource validation. Requires `pip install 'feast[mlflow]'`. See [MLflow Integration](mlflow.md).

```bash
# Sync MLflow GenAI EvaluationDataset → FeatureView (via MlflowDatasetSource)
feast mlflow sync-dataset --feature-view mlflow_labels

# Preview flattened dataset records
feast mlflow preview-dataset --source agent-feedback-v3 --limit 10

# Validate an MlflowDatasetSource-backed FeatureView
feast mlflow validate-source eval_records

# List all FeatureViews backed by MlflowDatasetSource
feast mlflow list-sources
```

## Teardown

Tear down deployed feature store infrastructure
Expand Down
160 changes: 160 additions & 0 deletions 160 docs/reference/mlflow.md
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,163 @@ Start the Feast UI with:
```bash
feast ui --host 127.0.0.1 --port 8888
```

## MLflow as a DataSource

Feast supports MLflow as a first-class **offline DataSource** via `MlflowDatasetSource`. Users define `FeatureView(source=MlflowDatasetSource(...))` and call `get_historical_features()` / `create_saved_dataset()` to retrieve tabular data from MLflow-tracked artifacts or GenAI Datasets.

### Dual-mode design

`MlflowDatasetSource` supports two modes:

| Mode | When to use | Config fields |
|---|---|---|
| **GenAI Dataset** | Flywheel path — curated trace/assessment records from MLflow GenAI Datasets | `dataset_name` or `dataset_id` |
| **Artifact** | General purpose — download tabular artifacts (Parquet/CSV) from MLflow runs | `run_id` + `artifact_path` + `artifact_format` |

### GenAI Dataset mode

Reads from MLflow GenAI EvaluationDatasets via `get_dataset().to_df()`. This is the primary path for the tracing → assessment → training data flywheel.

```python
from feast import Entity, FeatureView, Field, FileSource
from feast.infra.data_sources.mlflow import MlflowDatasetSource
from feast.types import String

batch_sink = FileSource(path="data/eval_records.parquet", timestamp_field="event_timestamp")

source = MlflowDatasetSource(
name="eval_dataset",
dataset_name="production_validation_set",
batch_source=batch_sink,
timestamp_field="event_timestamp",
field_mapping={"expectations.expected_response": "expected_response"},
)

fv = FeatureView(
name="eval_records",
entities=[Entity(name="record_id", join_keys=["record_id"])],
schema=[Field(name="expected_response", dtype=String)],
source=source,
)
```

### Artifact mode

Downloads Parquet or CSV artifacts from MLflow runs via `mlflow.artifacts.download_artifacts()`.

```python
source = MlflowDatasetSource(
name="training_features",
run_id="abc123def456",
artifact_path="outputs/features.parquet",
artifact_format="parquet", # or "csv"
batch_source=FileSource(path="data/features.parquet", timestamp_field="ts"),
timestamp_field="ts",
)
```

### Retrieving historical features

Once registered, use `get_historical_features()` as with any other DataSource:

```python
from feast import FeatureStore

store = FeatureStore(".")
features = store.get_historical_features(
entity_df=entity_df,
features=["eval_records:expected_response"],
)
training_df = features.to_df()
```

### `batch_source` for writeback

`MlflowDatasetSource` is read-only — it does not support writing back to MLflow. A `batch_source` (e.g., `FileSource`) is always required for `create_saved_dataset()` and materialization writeback.

### Authentication

For RHOAI deployments, auth tokens are propagated automatically:

1. **User-initiated requests**: The Bearer token from the Feast API request is forwarded to MLflow
2. **Automated jobs** (materialization CronJobs): The pod's ServiceAccount token is used
3. **Local dev**: Falls back to `MLFLOW_TRACKING_TOKEN` env var or no auth

### Graceful degradation

- When `mlflow` is not installed, attempting to use `MlflowDatasetSource` raises a clear `ImportError` with install instructions
- Non-MLflow FeatureViews are completely unaffected by MLflow availability
- The feature server starts normally without MLflow

### Configuration

The `mlflow:` section in `feature_store.yaml` supports DataSource-specific fields:

```yaml
mlflow:
enabled: true
tracking_uri: https://mlflow.example.com:8443
ca_bundle: /etc/pki/tls/odh-trusted-ca-bundle.crt
supported_artifact_formats:
- parquet
- csv
request_timeout: 30
max_retries: 3
retry_backoff_factor: 1.0
```

| Field | Type | Default | Description |
|---|---|---|---|
| `ca_bundle` | `str` | `None` | Path to CA bundle for TLS verification (falls back to `REQUESTS_CA_BUNDLE` env var) |
| `supported_artifact_formats` | `list[str]` | `["parquet", "csv"]` | Artifact formats the adapter will accept |
| `request_timeout` | `int` | `30` | Timeout in seconds for individual HTTP requests to the MLflow tracking server |
| `max_retries` | `int` | `3` | Maximum retry attempts for transient MLflow API failures (timeouts, 5xx, connection errors) |
| `retry_backoff_factor` | `float` | `1.0` | Base factor for exponential backoff between retries (wait = factor × 2^attempt) |

### CLI commands

#### `feast mlflow validate-source`

Validates that an MlflowDatasetSource-backed FeatureView is reachable and schema-compatible:

```bash
feast mlflow validate-source eval_records
```

Checks performed:
- Config validation (mode, batch_source, artifact_format)
- Schema introspection (column names and types from MLflow)
- Schema match (FeatureView features vs source columns)

#### `feast mlflow list-sources`

Lists all FeatureViews backed by MlflowDatasetSource:

```bash
feast mlflow list-sources
```

#### `feast mlflow sync-dataset`

Syncs an MLflow GenAI Dataset into a Feast FeatureView (for Tier 3 offline stores like BigQuery, Snowflake, Redshift):

```bash
feast mlflow sync-dataset --feature-view eval_records
feast mlflow sync-dataset --feature-view eval_records --full-refresh
feast mlflow sync-dataset --feature-view eval_records --dry-run
feast mlflow sync-dataset --feature-view eval_records --batch-size 5000
feast mlflow sync-dataset --feature-view eval_records --field-mapping mapping.json
```

When `--feature-view` is omitted, syncs all FeatureViews whose source is `MlflowDatasetSource`. Supports incremental sync (default) via watermark tags and full refresh via `--full-refresh`.

#### `feast mlflow preview-dataset`

Preview flattened records from an MLflow GenAI Dataset:

```bash
feast mlflow preview-dataset --source agent-feedback-v3 --limit 10
```

Fetches the dataset, flattens nested fields, and displays a preview. Useful for inspecting data shape before defining a FeatureView.
Loading
Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Loading
Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.