Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: Add native Python mode on demand feature view to the local temp…
…late

The default template already demonstrates a Pandas mode on demand feature
view. Add transformed_conv_rate_python, the same transformation written
in native Python mode (mode="python"), so that feast init shows both
transformation modes side by side, and fetch its features in
test_workflow.py during both historical and online retrieval.

Part of #5478

Signed-off-by: ryota717 <ryota.nishijima@fout.jp>
  • Loading branch information
ryota717 committed Sep 29, 2026
commit 808aa059fb084d7eb170b4a93389814d0adffb0f
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This is an example feature definition file

from datetime import timedelta
from typing import Any

import pandas as pd

Expand Down Expand Up @@ -89,7 +90,8 @@


# Define an on demand feature view which can generate new features based on
# existing feature views and RequestSource features
# existing feature views and RequestSource features. By default the transformation
# runs in Pandas mode (mode="pandas"): the UDF receives and returns a DataFrame.
@on_demand_feature_view(
sources=[driver_stats_fv, input_request],
schema=[
Expand All @@ -104,6 +106,37 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame:
return df


# The same transformation written in native Python mode (mode="python"). The UDF
# receives a dict mapping each input feature name to a list of values (one per
# row) and returns a dict with the same shape. This avoids the Pandas overhead
# for small online requests and is often easier to reason about.
#
# Only the features the UDF needs are selected from the source feature view.
# This is required here: driver_stats_fv also has Map / Struct / Json fields, and
# Python mode feature inference cannot generate sample values for those types.
@on_demand_feature_view(
sources=[driver_stats_fv[["conv_rate"]], input_request],
schema=[
Field(name="conv_rate_plus_val1_python", dtype=Float64),
Field(name="conv_rate_plus_val2_python", dtype=Float64),
],
mode="python",
)
def transformed_conv_rate_python(inputs: dict[str, Any]) -> dict[str, Any]:
return {
"conv_rate_plus_val1_python": [
conv_rate + val_to_add
for conv_rate, val_to_add in zip(inputs["conv_rate"], inputs["val_to_add"])
],
"conv_rate_plus_val2_python": [
conv_rate + val_to_add_2
for conv_rate, val_to_add_2 in zip(
inputs["conv_rate"], inputs["val_to_add_2"]
)
],
}


# This groups features into a model version
driver_activity_v1 = FeatureService(
name="driver_activity_v1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ def fetch_historical_features_entity_df(store: FeatureStore, for_batch_scoring:
"driver_hourly_stats:conv_rate",
"driver_hourly_stats:acc_rate",
"driver_hourly_stats:avg_daily_trips",
# Pandas mode on demand transformation
"transformed_conv_rate:conv_rate_plus_val1",
"transformed_conv_rate:conv_rate_plus_val2",
# Native Python mode on demand transformation
"transformed_conv_rate_python:conv_rate_plus_val1_python",
"transformed_conv_rate_python:conv_rate_plus_val2_python",
],
).to_df()
print(training_df.head())
Expand Down Expand Up @@ -124,8 +128,12 @@ def fetch_online_features(store, source: str = ""):
"driver_hourly_stats:driver_metadata",
"driver_hourly_stats:driver_config",
"driver_hourly_stats:driver_profile",
# Pandas mode on demand transformation
"transformed_conv_rate:conv_rate_plus_val1",
"transformed_conv_rate:conv_rate_plus_val2",
# Native Python mode on demand transformation
"transformed_conv_rate_python:conv_rate_plus_val1_python",
"transformed_conv_rate_python:conv_rate_plus_val2_python",
]
returned_features = store.get_online_features(
features=features_to_fetch,
Expand Down