From 2f3294500292a5a356d461ae4c5518e84cd22883 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Oct 2025 18:15:21 +0000 Subject: [PATCH 1/5] Initial plan From 7f131c994afe7d4e36c15c60ccc8e7be6eeaa7d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Oct 2025 18:24:34 +0000 Subject: [PATCH 2/5] Fix STRING type handling in on-demand feature views Added 'object' dtype mapping to STRING in type_map.py since pandas uses object dtype for string columns by default. Added test case to verify STRING type inputs work with RequestSource. Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com> --- sdk/python/feast/type_map.py | 1 + .../tests/unit/test_on_demand_feature_view.py | 40 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index 9d9921a2bf9..34d3c074d29 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -144,6 +144,7 @@ def python_type_to_feast_value_type( "int": ValueType.INT64, "str": ValueType.STRING, "string": ValueType.STRING, # pandas.StringDtype + "object": ValueType.STRING, # pandas often uses object dtype for strings "float": ValueType.DOUBLE, "bytes": ValueType.BYTES, "float64": ValueType.DOUBLE, diff --git a/sdk/python/tests/unit/test_on_demand_feature_view.py b/sdk/python/tests/unit/test_on_demand_feature_view.py index 505146aa612..a3286846dd4 100644 --- a/sdk/python/tests/unit/test_on_demand_feature_view.py +++ b/sdk/python/tests/unit/test_on_demand_feature_view.py @@ -17,6 +17,7 @@ import pandas as pd import pytest +from feast.data_source import RequestSource from feast.feature_view import FeatureView from feast.field import Field from feast.infra.offline_stores.file_source import FileSource @@ -26,7 +27,7 @@ PythonTransformation, on_demand_feature_view, ) -from feast.types import Float32 +from feast.types import Float32, String def udf1(features_df: pd.DataFrame) -> pd.DataFrame: @@ -418,3 +419,40 @@ def another_transform(features_df: pd.DataFrame) -> pd.DataFrame: deserialized = OnDemandFeatureView.from_proto(proto) assert deserialized.name == CUSTOM_FUNCTION_NAME + + +def test_on_demand_string_features(): + """Test that on-demand feature views work with STRING type inputs from RequestSource.""" + # Define a request data source with STRING type fields + input_request = RequestSource( + name="vals_to_add", + schema=[ + Field(name="val_to_add", dtype=String), + Field(name="val_to_add_2", dtype=String), + ], + ) + + # Use input data to create new features in Pandas mode + @on_demand_feature_view( + sources=[input_request], + schema=[ + Field(name="conv_rate_plus_val1", dtype=String), + Field(name="conv_rate_plus_val2", dtype=String), + ], + mode="pandas", + ) + def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame: + df = pd.DataFrame() + df["conv_rate_plus_val1"] = features_df["val_to_add"] + df["conv_rate_plus_val2"] = features_df["val_to_add_2"] + return df + + # This should work without raising ValueError about 'object' type + transformed_conv_rate.infer_features() + + # Verify the inferred features have the correct type + assert len(transformed_conv_rate.features) == 2 + assert transformed_conv_rate.features[0].name == "conv_rate_plus_val1" + assert transformed_conv_rate.features[0].dtype == String + assert transformed_conv_rate.features[1].name == "conv_rate_plus_val2" + assert transformed_conv_rate.features[1].dtype == String From b9ad729c4e065303bb03497f3983ae53a445e54d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Oct 2025 18:32:12 +0000 Subject: [PATCH 3/5] Improve object dtype handling with value-based type inference Enhanced the fix to check actual value types when type_name='object'. This prevents incorrect type inference for mixed-type object columns while still fixing the STRING type issue. Falls back to STRING when value is None or unknown type. Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com> --- sdk/python/feast/type_map.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index 34d3c074d29..8df2ae324c3 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -144,7 +144,6 @@ def python_type_to_feast_value_type( "int": ValueType.INT64, "str": ValueType.STRING, "string": ValueType.STRING, # pandas.StringDtype - "object": ValueType.STRING, # pandas often uses object dtype for strings "float": ValueType.DOUBLE, "bytes": ValueType.BYTES, "float64": ValueType.DOUBLE, @@ -170,6 +169,15 @@ def python_type_to_feast_value_type( "category": ValueType.STRING, } + # Special handling for pandas 'object' dtype - infer from actual value type + if type_name == "object": + if value is not None: + actual_type = type(value).__name__.lower() + if actual_type in type_map: + return type_map[actual_type] + # Default to STRING for object dtype (pandas commonly uses object for strings) + return ValueType.STRING + if type_name in type_map: return type_map[type_name] From 1530894863609bd2d8daef0bce931aee6b6354fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Oct 2025 00:03:17 +0000 Subject: [PATCH 4/5] Fix object dtype handling to not intercept array types Moved object dtype special handling after array type checks to prevent intercepting numpy arrays with object dtype. Added check to exclude lists/arrays from object dtype value-based inference. This fixes unit test failures where arrays with object dtype were incorrectly mapped to STRING instead of being processed as arrays. Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com> --- sdk/python/feast/type_map.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index 8df2ae324c3..c15601d3e74 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -169,22 +169,23 @@ def python_type_to_feast_value_type( "category": ValueType.STRING, } + if type_name in type_map: + return type_map[type_name] + + if isinstance(value, np.ndarray) and str(value.dtype) in type_map: + item_type = type_map[str(value.dtype)] + return ValueType[item_type.name + "_LIST"] + # Special handling for pandas 'object' dtype - infer from actual value type + # This must come after array handling to avoid intercepting array types if type_name == "object": - if value is not None: + if value is not None and not isinstance(value, (list, np.ndarray)): actual_type = type(value).__name__.lower() if actual_type in type_map: return type_map[actual_type] # Default to STRING for object dtype (pandas commonly uses object for strings) return ValueType.STRING - if type_name in type_map: - return type_map[type_name] - - if isinstance(value, np.ndarray) and str(value.dtype) in type_map: - item_type = type_map[str(value.dtype)] - return ValueType[item_type.name + "_LIST"] - if isinstance(value, (list, np.ndarray)): # if the value's type is "ndarray" and we couldn't infer from "value.dtype" # this is most probably array of "object", From 77540b1fc0e03a41732c3e46644c67276a4ebca0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Oct 2025 01:50:44 +0000 Subject: [PATCH 5/5] Fix object dtype check to not return early for arrays The object dtype check was returning STRING early even when the value was an array/list, preventing the array handling logic from running. Moved the array check to the outer condition so arrays with object dtype fall through to the list/array handling code which correctly returns STRING_LIST. Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com> --- sdk/python/feast/type_map.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/python/feast/type_map.py b/sdk/python/feast/type_map.py index c15601d3e74..4a540eb4953 100644 --- a/sdk/python/feast/type_map.py +++ b/sdk/python/feast/type_map.py @@ -178,8 +178,8 @@ def python_type_to_feast_value_type( # Special handling for pandas 'object' dtype - infer from actual value type # This must come after array handling to avoid intercepting array types - if type_name == "object": - if value is not None and not isinstance(value, (list, np.ndarray)): + if type_name == "object" and not isinstance(value, (list, np.ndarray)): + if value is not None: actual_type = type(value).__name__.lower() if actual_type in type_map: return type_map[actual_type]