Skip to content

Commit 2390d2e

Browse files
committed
fix: Add mode field to Transformation proto for proper serialization
Signed-off-by: ntkathole <[email protected]>
1 parent 2ae33de commit 2390d2e

File tree

11 files changed

+251
-53
lines changed

11 files changed

+251
-53
lines changed

protos/feast/core/FeatureView.proto

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ message FeatureView {
3636
FeatureViewMeta meta = 2;
3737
}
3838

39-
// Next available id: 16
39+
// Next available id: 17
4040
// TODO(adchia): refactor common fields from this and ODFV into separate metadata proto
4141
message FeatureViewSpec {
4242
// Name of the feature view. Must be unique. Not updated.
@@ -51,18 +51,9 @@ message FeatureViewSpec {
5151
// List of specifications for each feature defined as part of this feature view.
5252
repeated FeatureSpecV2 features = 4;
5353

54-
// List of specifications for each entity defined as part of this feature view.
55-
repeated FeatureSpecV2 entity_columns = 12;
56-
57-
// Description of the feature view.
58-
string description = 10;
59-
6054
// User defined metadata
6155
map<string,string> tags = 5;
6256

63-
// Owner of the feature view.
64-
string owner = 11;
65-
6657
// Features in this feature view can only be retrieved from online serving
6758
// younger than ttl. Ttl is measured as the duration of time between
6859
// the feature's event timestamp and when the feature is retrieved
@@ -71,20 +62,33 @@ message FeatureViewSpec {
7162

7263
// Batch/Offline DataSource where this view can retrieve offline feature data.
7364
DataSource batch_source = 7;
74-
// Streaming DataSource from where this view can consume "online" feature data.
75-
DataSource stream_source = 9;
7665

7766
// Whether these features should be served online or not
7867
// This is also used to determine whether the features should be written to the online store
7968
bool online = 8;
8069

70+
// Streaming DataSource from where this view can consume "online" feature data.
71+
DataSource stream_source = 9;
72+
73+
// Description of the feature view.
74+
string description = 10;
75+
76+
// Owner of the feature view.
77+
string owner = 11;
78+
79+
// List of specifications for each entity defined as part of this feature view.
80+
repeated FeatureSpecV2 entity_columns = 12;
81+
8182
// Whether these features should be written to the offline store
8283
bool offline = 13;
8384

8485
repeated FeatureViewSpec source_views = 14;
8586

8687
// Feature transformation for batch feature views
8788
FeatureTransformationV2 feature_transformation = 15;
89+
90+
// The transformation mode (e.g., "python", "pandas", "spark", "sql", "ray")
91+
string mode = 16;
8892
}
8993

9094
message FeatureViewMeta {

protos/feast/core/Transformation.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ message UserDefinedFunctionV2 {
1515

1616
// The string representation of the udf
1717
string body_text = 3;
18+
19+
// The transformation mode (e.g., "python", "pandas", "spark", "sql")
20+
string mode = 4;
1821
}
1922

2023
// A feature transformation executed as a user-defined function

sdk/python/feast/batch_feature_view.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def __init__(
136136
schema=schema,
137137
source=source, # type: ignore[arg-type]
138138
sink_source=sink_source,
139+
mode=mode,
139140
)
140141

141142
def get_feature_transformation(self) -> Optional[Transformation]:

sdk/python/feast/feature_view.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from feast.protos.feast.core.Transformation_pb2 import (
4040
FeatureTransformationV2 as FeatureTransformationProto,
4141
)
42+
from feast.transformation.mode import TransformationMode
4243
from feast.types import from_value_type
4344
from feast.value_type import ValueType
4445

@@ -102,6 +103,7 @@ class FeatureView(BaseFeatureView):
102103
tags: Dict[str, str]
103104
owner: str
104105
materialization_intervals: List[Tuple[datetime, datetime]]
106+
mode: Optional[Union["TransformationMode", str]]
105107

106108
def __init__(
107109
self,
@@ -117,6 +119,7 @@ def __init__(
117119
description: str = "",
118120
tags: Optional[Dict[str, str]] = None,
119121
owner: str = "",
122+
mode: Optional[Union["TransformationMode", str]] = None,
120123
):
121124
"""
122125
Creates a FeatureView object.
@@ -140,6 +143,7 @@ def __init__(
140143
tags (optional): A dictionary of key-value pairs to store arbitrary metadata.
141144
owner (optional): The owner of the feature view, typically the email of the
142145
primary maintainer.
146+
mode (optional): The transformation mode to use (e.g., python, pandas, spark, sql).
143147
144148
Raises:
145149
ValueError: A field mapping conflicts with an Entity or a Feature.
@@ -252,6 +256,7 @@ def __init__(
252256
)
253257
self.online = online
254258
self.offline = offline
259+
self.mode = mode
255260
self.materialization_intervals = []
256261

257262
def __hash__(self):
@@ -439,6 +444,14 @@ def to_proto_spec(
439444
substrait_transformation=transformation_proto,
440445
)
441446

447+
mode_str = ""
448+
if self.mode:
449+
mode_str = (
450+
self.mode.value
451+
if isinstance(self.mode, TransformationMode)
452+
else self.mode
453+
)
454+
442455
return FeatureViewSpecProto(
443456
name=self.name,
444457
entities=self.entities,
@@ -454,6 +467,7 @@ def to_proto_spec(
454467
stream_source=stream_source_proto,
455468
source_views=source_view_protos,
456469
feature_transformation=feature_transformation_proto,
470+
mode=mode_str,
457471
)
458472

459473
def to_proto_meta(self):
@@ -527,6 +541,7 @@ def _from_proto_internal(
527541

528542
if has_transformation and cls == FeatureView:
529543
from feast.batch_feature_view import BatchFeatureView
544+
from feast.transformation.factory import get_transformation_class_from_type
530545
from feast.transformation.python_transformation import PythonTransformation
531546
from feast.transformation.substrait_transformation import (
532547
SubstraitTransformation,
@@ -538,14 +553,30 @@ def _from_proto_internal(
538553
transformation = None
539554

540555
if feature_transformation_proto.HasField("user_defined_function"):
541-
transformation = PythonTransformation.from_proto(
542-
feature_transformation_proto.user_defined_function
543-
)
556+
udf_proto = feature_transformation_proto.user_defined_function
557+
if udf_proto.mode:
558+
try:
559+
transformation_class = get_transformation_class_from_type(
560+
udf_proto.mode
561+
)
562+
transformation = transformation_class.from_proto(udf_proto)
563+
except (ValueError, KeyError):
564+
transformation = PythonTransformation.from_proto(udf_proto)
565+
else:
566+
transformation = PythonTransformation.from_proto(udf_proto)
544567
elif feature_transformation_proto.HasField("substrait_transformation"):
545568
transformation = SubstraitTransformation.from_proto(
546569
feature_transformation_proto.substrait_transformation
547570
)
548571

572+
mode: Union[TransformationMode, str]
573+
if feature_view_proto.spec.mode:
574+
mode = feature_view_proto.spec.mode
575+
elif transformation and hasattr(transformation, "mode"):
576+
mode = transformation.mode
577+
else:
578+
mode = TransformationMode.PYTHON
579+
549580
feature_view: FeatureView = BatchFeatureView( # type: ignore[assignment]
550581
name=feature_view_proto.spec.name,
551582
description=feature_view_proto.spec.description,
@@ -560,9 +591,14 @@ def _from_proto_internal(
560591
),
561592
source=source_views if source_views else batch_source, # type: ignore[arg-type]
562593
sink_source=batch_source if source_views else None,
594+
mode=mode,
563595
feature_transformation=transformation,
564596
)
565597
else:
598+
mode_from_spec = (
599+
feature_view_proto.spec.mode if feature_view_proto.spec.mode else None
600+
)
601+
566602
feature_view = cls( # type: ignore[assignment]
567603
name=feature_view_proto.spec.name,
568604
description=feature_view_proto.spec.description,
@@ -577,6 +613,7 @@ def _from_proto_internal(
577613
),
578614
source=source_views if source_views else batch_source,
579615
sink_source=batch_source if source_views else None,
616+
mode=mode_from_spec,
580617
)
581618
if stream_source:
582619
feature_view.stream_source = stream_source

sdk/python/feast/protos/feast/core/FeatureView_pb2.py

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)