Skip to content

Commit 4d0ea72

Browse files
authored
Add FeatureService proto definition (feast-dev#1676)
* Add FeatureService protos Signed-off-by: Achal Shah <achals@gmail.com> * Add python classes Signed-off-by: Achal Shah <achals@gmail.com> * remove import Signed-off-by: Achal Shah <achals@gmail.com> * Remove entities Signed-off-by: Achal Shah <achals@gmail.com> * Rename to FeatureViewProjection Signed-off-by: Achal Shah <achals@gmail.com> * Update imports after renaming Signed-off-by: Achal Shah <achals@gmail.com>
1 parent cb1e7d7 commit 4d0ea72

File tree

8 files changed

+195
-3
lines changed

8 files changed

+195
-3
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
syntax = "proto3";
2+
package feast.core;
3+
4+
option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core";
5+
option java_outer_classname = "FeatureServiceProto";
6+
option java_package = "feast.proto.core";
7+
8+
import "google/protobuf/timestamp.proto";
9+
import "feast/core/FeatureViewProjection.proto";
10+
11+
message FeatureService {
12+
// User-specified specifications of this feature service.
13+
FeatureServiceSpec spec = 1;
14+
15+
// System-populated metadata for this feature service.
16+
FeatureServiceMeta meta = 2;
17+
}
18+
19+
message FeatureServiceSpec {
20+
// Name of the Feature Service. Must be unique. Not updated.
21+
string name = 1;
22+
23+
// Name of Feast project that this Feature Service belongs to.
24+
string project = 2;
25+
26+
// List of features that this feature service encapsulates.
27+
// Stored as a list of references to other features views and the features from those views.
28+
repeated FeatureViewProjection features = 3;
29+
30+
// User defined metadata
31+
map<string,string> tags = 4;
32+
}
33+
34+
35+
message FeatureServiceMeta {
36+
// Time where this Feature Service is created
37+
google.protobuf.Timestamp created_timestamp = 1;
38+
39+
// Time where this Feature Service is last updated
40+
google.protobuf.Timestamp last_updated_timestamp = 2;
41+
42+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
syntax = "proto3";
2+
package feast.core;
3+
4+
option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core";
5+
option java_outer_classname = "FeatureReferenceProto";
6+
option java_package = "feast.proto.core";
7+
8+
import "feast/core/Feature.proto";
9+
10+
11+
// A reference to features in a feature view
12+
message FeatureViewProjection {
13+
// The feature view name
14+
string feature_view_name = 1;
15+
16+
// The features of the feature view that are a part of the feature reference.
17+
repeated FeatureSpecV2 feature_columns = 2;
18+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from datetime import datetime
2+
from typing import List, Optional, Union
3+
4+
from feast.feature_table import FeatureTable
5+
from feast.feature_view import FeatureView
6+
from feast.feature_view_projection import FeatureViewProjection
7+
from feast.protos.feast.core.FeatureService_pb2 import (
8+
FeatureService as FeatureServiceProto,
9+
)
10+
from feast.protos.feast.core.FeatureService_pb2 import (
11+
FeatureServiceMeta,
12+
FeatureServiceSpec,
13+
)
14+
15+
16+
class FeatureService:
17+
name: str
18+
features: List[FeatureViewProjection]
19+
created_timestamp: Optional[datetime] = None
20+
last_updated_timestamp: Optional[datetime] = None
21+
22+
def __init__(
23+
self,
24+
name: str,
25+
features: List[Union[FeatureTable, FeatureView, FeatureViewProjection]],
26+
):
27+
self.name = name
28+
self.features = []
29+
for feature in features:
30+
if isinstance(feature, FeatureTable) or isinstance(feature, FeatureView):
31+
self.features.append(FeatureViewProjection.from_definition(feature))
32+
elif isinstance(feature, FeatureViewProjection):
33+
self.features.append(feature)
34+
else:
35+
raise ValueError(f"Unexpected type: {type(feature)}")
36+
37+
def __eq__(self, other):
38+
pass
39+
40+
@staticmethod
41+
def from_proto(feature_service_proto: FeatureServiceProto):
42+
fs = FeatureService(
43+
name=feature_service_proto.spec.name,
44+
features=[
45+
FeatureViewProjection.from_proto(fp)
46+
for fp in feature_service_proto.spec.features
47+
],
48+
)
49+
50+
if feature_service_proto.meta.HasField("created_timestamp"):
51+
fs.created_timestamp = (
52+
feature_service_proto.meta.created_timestamp.ToDatetime()
53+
)
54+
if feature_service_proto.meta.HasField("last_updated_timestamp"):
55+
fs.last_updated_timestamp = (
56+
feature_service_proto.meta.last_updated_timestamp.ToDatetime()
57+
)
58+
59+
return fs
60+
61+
def to_proto(self):
62+
meta = FeatureServiceMeta()
63+
if self.created_timestamp:
64+
meta.created_timestamp.FromDatetime(self.created_timestamp)
65+
66+
spec = FeatureServiceSpec()
67+
spec.name = self.name
68+
for definition in self.features:
69+
if isinstance(definition, FeatureTable) or isinstance(
70+
definition, FeatureView
71+
):
72+
feature_ref = FeatureViewProjection(
73+
definition.name, definition.features
74+
)
75+
else:
76+
feature_ref = definition
77+
78+
spec.features.append(feature_ref.to_proto())
79+
80+
feature_service_proto = FeatureServiceProto(spec=spec, meta=meta)
81+
return feature_service_proto
82+
83+
def validate(self):
84+
pass

sdk/python/feast/feature_view.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from feast.data_source import DataSource
2424
from feast.errors import RegistryInferenceFailure
2525
from feast.feature import Feature
26+
from feast.feature_view_projection import FeatureViewProjection
2627
from feast.protos.feast.core.FeatureView_pb2 import FeatureView as FeatureViewProto
2728
from feast.protos.feast.core.FeatureView_pb2 import (
2829
FeatureViewMeta as FeatureViewMetaProto,
@@ -110,6 +111,16 @@ def __str__(self):
110111
def __hash__(self):
111112
return hash(self.name)
112113

114+
def __getitem__(self, item) -> FeatureViewProjection:
115+
assert isinstance(item, list)
116+
117+
referenced_features = []
118+
for feature in self.features:
119+
if feature.name in item:
120+
referenced_features.append(feature)
121+
122+
return FeatureViewProjection(self.name, referenced_features)
123+
113124
def __eq__(self, other):
114125
if not isinstance(other, FeatureView):
115126
raise TypeError(
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from typing import List
2+
3+
from attr import dataclass
4+
5+
from feast.feature import Feature
6+
from feast.protos.feast.core.FeatureViewProjection_pb2 import (
7+
FeatureViewProjection as FeatureViewProjectionProto,
8+
)
9+
10+
11+
@dataclass
12+
class FeatureViewProjection:
13+
name: str
14+
features: List[Feature]
15+
16+
def to_proto(self):
17+
feature_reference_proto = FeatureViewProjectionProto(
18+
feature_view_name=self.name
19+
)
20+
for feature in self.features:
21+
feature_reference_proto.feature_columns.append(feature.to_proto())
22+
23+
return feature_reference_proto
24+
25+
@staticmethod
26+
def from_proto(proto: FeatureViewProjectionProto):
27+
ref = FeatureViewProjection(name=proto.feature_view_name, features=[])
28+
for feature_column in proto.feature_columns:
29+
ref.features.append(Feature.from_proto(feature_column))
30+
31+
return ref
32+
33+
@staticmethod
34+
def from_definition(feature_definition):
35+
return FeatureViewProjection(
36+
name=feature_definition.name, features=feature_definition.features
37+
)

sdk/python/tensorflow_metadata/proto/v0/path_pb2.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/python/tensorflow_metadata/proto/v0/schema_pb2.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/python/tensorflow_metadata/proto/v0/statistics_pb2.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)