Skip to content

Commit cf7bbc2

Browse files
authored
fix: Schema update (feast-dev#2509)
* Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * fix lint Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * indent fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix lint Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix lint Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix go Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix tests Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Revert Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * fixes Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix lint Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix and clean up Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Lint Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Fix Signed-off-by: Kevin Zhang <kzhang@tecton.ai> * Patch fix, will change definitions in separate pr Signed-off-by: Kevin Zhang <kzhang@tecton.ai>
1 parent 11a342f commit cf7bbc2

File tree

18 files changed

+197
-57
lines changed

18 files changed

+197
-57
lines changed

docs/getting-started/concepts/feature-view.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ from feast import Field, Float64, RequestSource
144144
# available at request time (e.g. part of the user initiated HTTP request)
145145
input_request = RequestSource(
146146
name="vals_to_add",
147-
schema={
148-
"val_to_add": ValueType.INT64,
149-
"val_to_add_2": ValueType.INT64
150-
}
147+
schema=[
148+
Field(name="val_to_add", dtype=PrimitiveFeastType.INT64),
149+
Field(name="val_to_add_2": dtype=PrimitiveFeastType.INT64),
150+
]
151151
)
152152

153153
# Use the input data and feature view features to create new features

docs/how-to-guides/adding-a-new-offline-store.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ Finally, the custom data source class can be use in the feature repo to define a
246246
```python
247247
pdriver_hourly_stats = CustomFileDataSource(
248248
path="feature_repo/data/driver_stats.parquet",
249-
event_timestamp_column="event_timestamp",
249+
timestamp_field="event_timestamp",
250250
created_timestamp_column="created",
251251
)
252252

examples/java-demo/feature_repo/driver_repo.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from feast.request_feature_view import RequestFeatureView
66
from feast.types import Float32, Float64, Int64, String
77
from google.protobuf.duration_pb2 import Duration
8+
from feast.field import Field
89

910
from feast import Entity, Feature, FeatureView, FileSource, ValueType
1011

@@ -33,7 +34,10 @@
3334
# available at request time (e.g. part of the user initiated HTTP request)
3435
input_request = RequestSource(
3536
name="vals_to_add",
36-
schema={"val_to_add": ValueType.INT64, "val_to_add_2": ValueType.INT64},
37+
schema=[
38+
Field(name="val_to_add", dtype=Int64),
39+
Field(name="val_to_add_2", dtype=Int64),
40+
],
3741
)
3842

3943
# Define an on demand feature view which can generate new features based on
@@ -59,6 +63,9 @@ def transformed_conv_rate(inputs: pd.DataFrame) -> pd.DataFrame:
5963
driver_age_request_fv = RequestFeatureView(
6064
name="driver_age",
6165
request_data_source=RequestSource(
62-
name="driver_age", schema={"driver_age": ValueType.INT64,}
66+
name="driver_age",
67+
schema=[
68+
Field(name="driver_age", dtype=Int64),
69+
],
6370
),
6471
)
16 KB
Binary file not shown.

go/internal/feast/model/ondemandfeatureview.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ func (fs *OnDemandFeatureView) ProjectWithFeatures(featureNames []string) (*OnDe
5555
func (fs *OnDemandFeatureView) GetRequestDataSchema() map[string]types.ValueType_Enum {
5656
schema := make(map[string]types.ValueType_Enum)
5757
for _, requestDataSource := range fs.SourceRequestDataSources {
58-
for fieldName, fieldValueType := range requestDataSource.Schema {
59-
schema[fieldName] = fieldValueType
58+
for _, featureSpec := range requestDataSource.Schema {
59+
schema[featureSpec.Name] = featureSpec.ValueType
6060
}
6161
}
6262
return schema

java/serving/src/test/resources/docker-compose/feast10/definitions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from feast.types import Float32, Float64, Int64
99
from feast.value_type import ValueType
1010
from google.protobuf.duration_pb2 import Duration
11-
1211
from feast import FileSource
1312

1413
file_path = "driver_stats.parquet"

protos/feast/core/DataSource.proto

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ option java_package = "feast.proto.core";
2424

2525
import "feast/core/DataFormat.proto";
2626
import "feast/types/Value.proto";
27+
import "feast/core/Feature.proto";
2728

2829
// Defines a Data Source that can be used source Feature data
2930
// Next available id: 28
@@ -212,7 +213,10 @@ message DataSource {
212213
message RequestDataOptions {
213214
reserved 1;
214215
// Mapping of feature name to type
215-
map<string, feast.types.ValueType.Enum> schema = 2;
216+
map<string, feast.types.ValueType.Enum> deprecated_schema = 2;
217+
218+
repeated FeatureSpecV2 schema = 3;
219+
216220
}
217221

218222
// Defines options for DataSource that supports pushing data to it. This allows data to be pushed to

protos/feast/types/Field.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ option go_package = "github.com/feast-dev/feast/go/protos/feast/types";
2626

2727
message Field {
2828
string name = 1;
29-
feast.types.Value value = 2;
29+
feast.types.ValueType.Enum value = 2;
3030
}

sdk/python/feast/data_source.py

Lines changed: 93 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
import enum
1616
import warnings
1717
from abc import ABC, abstractmethod
18-
from typing import Any, Callable, Dict, Iterable, Optional, Tuple
18+
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
1919

2020
from google.protobuf.json_format import MessageToJson
2121

2222
from feast import type_map
2323
from feast.data_format import StreamFormat
24+
from feast.field import Field
2425
from feast.protos.feast.core.DataSource_pb2 import DataSource as DataSourceProto
2526
from feast.repo_config import RepoConfig, get_data_source_class_from_type
27+
from feast.types import VALUE_TYPES_TO_FEAST_TYPES
2628
from feast.value_type import ValueType
2729

2830

@@ -449,27 +451,45 @@ class RequestSource(DataSource):
449451
450452
Args:
451453
name: Name of the request data source
452-
schema: Schema mapping from the input feature name to a ValueType
454+
schema Union[Dict[str, ValueType], List[Field]]: Schema mapping from the input feature name to a ValueType
453455
description (optional): A human-readable description.
454456
tags (optional): A dictionary of key-value pairs to store arbitrary metadata.
455457
owner (optional): The owner of the request data source, typically the email of the primary
456458
maintainer.
457459
"""
458460

459461
name: str
460-
schema: Dict[str, ValueType]
462+
schema: List[Field]
461463

462464
def __init__(
463465
self,
464466
name: str,
465-
schema: Dict[str, ValueType],
467+
schema: Union[Dict[str, ValueType], List[Field]],
466468
description: Optional[str] = "",
467469
tags: Optional[Dict[str, str]] = None,
468470
owner: Optional[str] = "",
469471
):
470472
"""Creates a RequestSource object."""
471473
super().__init__(name=name, description=description, tags=tags, owner=owner)
472-
self.schema = schema
474+
if isinstance(schema, Dict):
475+
warnings.warn(
476+
"Schema in RequestSource is changing type. The schema data type Dict[str, ValueType] is being deprecated in Feast 0.23. "
477+
"Please use List[Field] instead for the schema",
478+
DeprecationWarning,
479+
)
480+
schemaList = []
481+
for key, valueType in schema.items():
482+
schemaList.append(
483+
Field(name=key, dtype=VALUE_TYPES_TO_FEAST_TYPES[valueType])
484+
)
485+
self.schema = schemaList
486+
elif isinstance(schema, List):
487+
self.schema = schema
488+
else:
489+
raise Exception(
490+
"Schema type must be either dictionary or list, not "
491+
+ str(type(schema))
492+
)
473493

474494
def validate(self, config: RepoConfig):
475495
pass
@@ -479,33 +499,86 @@ def get_table_column_names_and_types(
479499
) -> Iterable[Tuple[str, str]]:
480500
pass
481501

502+
def __eq__(self, other):
503+
if not isinstance(other, RequestSource):
504+
raise TypeError(
505+
"Comparisons should only involve RequestSource class objects."
506+
)
507+
if (
508+
self.name != other.name
509+
or self.description != other.description
510+
or self.owner != other.owner
511+
or self.tags != other.tags
512+
):
513+
return False
514+
if isinstance(self.schema, List) and isinstance(other.schema, List):
515+
for field1, field2 in zip(self.schema, other.schema):
516+
if field1 != field2:
517+
return False
518+
return True
519+
else:
520+
return False
521+
522+
def __hash__(self):
523+
return super().__hash__()
524+
482525
@staticmethod
483526
def from_proto(data_source: DataSourceProto):
527+
528+
deprecated_schema = data_source.request_data_options.deprecated_schema
484529
schema_pb = data_source.request_data_options.schema
485-
schema = {}
486-
for key, val in schema_pb.items():
487-
schema[key] = ValueType(val)
488-
return RequestSource(
489-
name=data_source.name,
490-
schema=schema,
491-
description=data_source.description,
492-
tags=dict(data_source.tags),
493-
owner=data_source.owner,
494-
)
530+
531+
if deprecated_schema and not schema_pb:
532+
warnings.warn(
533+
"Schema in RequestSource is changing type. The schema data type Dict[str, ValueType] is being deprecated in Feast 0.23. "
534+
"Please use List[Field] instead for the schema",
535+
DeprecationWarning,
536+
)
537+
dict_schema = {}
538+
for key, val in deprecated_schema.items():
539+
dict_schema[key] = ValueType(val)
540+
return RequestSource(
541+
name=data_source.name,
542+
schema=dict_schema,
543+
description=data_source.description,
544+
tags=dict(data_source.tags),
545+
owner=data_source.owner,
546+
)
547+
else:
548+
list_schema = []
549+
for field_proto in schema_pb:
550+
list_schema.append(Field.from_proto(field_proto))
551+
552+
return RequestSource(
553+
name=data_source.name,
554+
schema=list_schema,
555+
description=data_source.description,
556+
tags=dict(data_source.tags),
557+
owner=data_source.owner,
558+
)
495559

496560
def to_proto(self) -> DataSourceProto:
497-
schema_pb = {}
498-
for key, value in self.schema.items():
499-
schema_pb[key] = value.value
500-
options = DataSourceProto.RequestDataOptions(schema=schema_pb)
561+
562+
schema_pb = []
563+
564+
if isinstance(self.schema, Dict):
565+
for key, value in self.schema.items():
566+
schema_pb.append(
567+
Field(
568+
name=key, dtype=VALUE_TYPES_TO_FEAST_TYPES[value.value]
569+
).to_proto()
570+
)
571+
else:
572+
for field in self.schema:
573+
schema_pb.append(field.to_proto())
501574
data_source_proto = DataSourceProto(
502575
name=self.name,
503576
type=DataSourceProto.REQUEST_SOURCE,
504-
request_data_options=options,
505577
description=self.description,
506578
tags=self.tags,
507579
owner=self.owner,
508580
)
581+
data_source_proto.request_data_options.schema.extend(schema_pb)
509582

510583
return data_source_proto
511584

sdk/python/feast/field.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def from_proto(cls, field_proto: FieldProto):
7474
field_proto: FieldProto protobuf object
7575
"""
7676
value_type = ValueType(field_proto.value_type)
77-
return cls(name=field_proto.name, dtype=from_value_type(value_type))
77+
return cls(name=field_proto.name, dtype=from_value_type(value_type=value_type))
7878

7979
@classmethod
8080
def from_feature(cls, feature: Feature):

0 commit comments

Comments
 (0)