Skip to content

Commit 6a03bed

Browse files
feat: Switch from Feature to Field (#2514)
* Add type annotation Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field for FeatureViewProjection Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field for BaseFeatureView Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field for RequestFeatureView Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Enforce kwargs for ODFVs and switch from Feature to Field and from `features` to `schema` Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field and from `features` to `schema` for FeatureView Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Fix references to `features` and Feature Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from `Feature` to `Field` for ODFV in tests Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in templates Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in example test repos Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in registration integration tests Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in non-registration integration tests Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in random tests Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in ui Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in some universal feature views Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Switch from Feature to Field in docs Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Add assertion that BaseFeatureView is always initialized with a name Signed-off-by: Felix Wang <wangfelix98@gmail.com> * Fix imports in docs Signed-off-by: Felix Wang <wangfelix98@gmail.com>
1 parent 90db1d1 commit 6a03bed

38 files changed

+557
-373
lines changed

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ A feature view is an object that represents a logical group of time-series featu
77
{% tabs %}
88
{% tab title="driver_trips_feature_view.py" %}
99
```python
10+
from feast import BigQuerySource, FeatureView, Field, Float32, Int64
11+
1012
driver_stats_fv = FeatureView(
1113
name="driver_activity",
1214
entities=["driver"],
13-
features=[
14-
Feature(name="trips_today", dtype=ValueType.INT64),
15-
Feature(name="rating", dtype=ValueType.FLOAT),
15+
schema=[
16+
Field(name="trips_today", dtype=Int64),
17+
Field(name="rating", dtype=Float32),
1618
],
1719
batch_source=BigQuerySource(
1820
table_ref="feast-oss.demo_data.driver_activity"
@@ -39,11 +41,13 @@ If a feature view contains features that are not related to a specific entity, t
3941
{% tabs %}
4042
{% tab title="global_stats.py" %}
4143
```python
44+
from feast import BigQuerySource, FeatureView, Field, Int64
45+
4246
global_stats_fv = FeatureView(
4347
name="global_stats",
4448
entities=[],
45-
features=[
46-
Feature(name="total_trips_today_by_all_drivers", dtype=ValueType.INT64),
49+
schema=[
50+
Field(name="total_trips_today_by_all_drivers", dtype=Int64),
4751
],
4852
batch_source=BigQuerySource(
4953
table_ref="feast-oss.demo_data.global_stats"
@@ -70,13 +74,15 @@ It is suggested that you dynamically specify the new FeatureView name using `.wi
7074
{% tabs %}
7175
{% tab title="location_stats_feature_view.py" %}
7276
```python
77+
from feast import BigQuerySource, Entity, FeatureView, Field, Int32, ValueType
78+
7379
location = Entity(name="location", join_key="location_id", value_type=ValueType.INT64)
7480

7581
location_stats_fv= FeatureView(
7682
name="location_stats",
7783
entities=["location"],
78-
features=[
79-
Feature(name="temperature", dtype=ValueType.INT32)
84+
schema=[
85+
Field(name="temperature", dtype=Int32)
8086
],
8187
batch_source=BigQuerySource(
8288
table_ref="feast-oss.demo_data.location_stats"
@@ -115,9 +121,11 @@ A feature is an individual measurable property. It is typically a property obser
115121
Features are defined as part of feature views. Since Feast does not transform data, a feature is essentially a schema that only contains a name and a type:
116122

117123
```python
118-
trips_today = Feature(
124+
from feast import Field, Float32
125+
126+
trips_today = Field(
119127
name="trips_today",
120-
dtype=ValueType.FLOAT
128+
dtype=Float32
121129
)
122130
```
123131

docs/getting-started/concepts/point-in-time-joins.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ Feature values in Feast are modeled as time-series records. Below is an example
77
The above table can be registered with Feast through the following feature view:
88

99
```python
10+
from feast import FeatureView, Field, FileSource, Float32, Int64
11+
1012
driver_stats_fv = FeatureView(
1113
name="driver_hourly_stats",
1214
entities=["driver"],
13-
features=[
14-
Feature(name="trips_today", dtype=ValueType.INT64),
15-
Feature(name="earnings_today", dtype=ValueType.FLOAT),
15+
schema=[
16+
Field(name="trips_today", dtype=Int64),
17+
Field(name="earnings_today", dtype=Float32),
1618
],
1719
ttl=timedelta(hours=2),
1820
batch_source=FileSource(

docs/getting-started/quickstart.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,16 @@ online_store:
8080
```python
8181
# This is an example feature definition file
8282

83-
from google.protobuf.duration_pb2 import Duration
83+
from datetime import timedelta
8484

85-
from feast import Entity, Feature, FeatureView, FileSource, ValueType
85+
from feast import Entity, FeatureView, Field, FileSource, Float32, Int64, ValueType
8686

8787
# Read data from parquet files. Parquet is convenient for local development mode. For
8888
# production, you can use your favorite DWH, such as BigQuery. See Feast documentation
8989
# for more info.
9090
driver_hourly_stats = FileSource(
9191
path="/content/feature_repo/data/driver_stats.parquet",
92-
event_timestamp_column="event_timestamp",
92+
timestamp_field="event_timestamp",
9393
created_timestamp_column="created",
9494
)
9595

@@ -106,10 +106,10 @@ driver_hourly_stats_view = FeatureView(
106106
name="driver_hourly_stats",
107107
entities=["driver"], # reference entity by name
108108
ttl=Duration(seconds=86400 * 1),
109-
features=[
110-
Feature(name="conv_rate", dtype=ValueType.FLOAT),
111-
Feature(name="acc_rate", dtype=ValueType.FLOAT),
112-
Feature(name="avg_daily_trips", dtype=ValueType.INT64),
109+
schema=[
110+
Field(name="conv_rate", dtype=Float32),
111+
Field(name="acc_rate", dtype=Float32),
112+
Field(name="avg_daily_trips", dtype=Int64),
113113
],
114114
online=True,
115115
batch_source=driver_hourly_stats,
@@ -149,16 +149,16 @@ feast apply
149149
```python
150150
# This is an example feature definition file
151151

152-
from google.protobuf.duration_pb2 import Duration
152+
from datetime import timedelta
153153

154-
from feast import Entity, Feature, FeatureView, FileSource, ValueType
154+
from feast import Entity, FeatureView, Field, FileSource, Float32, Int64, ValueType
155155

156156
# Read data from parquet files. Parquet is convenient for local development mode. For
157157
# production, you can use your favorite DWH, such as BigQuery. See Feast documentation
158158
# for more info.
159159
driver_hourly_stats = FileSource(
160160
path="/content/feature_repo/data/driver_stats.parquet",
161-
event_timestamp_column="event_timestamp",
161+
timestamp_field="event_timestamp",
162162
created_timestamp_column="created",
163163
)
164164

@@ -175,10 +175,10 @@ driver_hourly_stats_view = FeatureView(
175175
name="driver_hourly_stats",
176176
entities=["driver"], # reference entity by name
177177
ttl=Duration(seconds=86400 * 1),
178-
features=[
179-
Feature(name="conv_rate", dtype=ValueType.FLOAT),
180-
Feature(name="acc_rate", dtype=ValueType.FLOAT),
181-
Feature(name="avg_daily_trips", dtype=ValueType.INT64),
178+
schema=[
179+
Field(name="conv_rate", dtype=Float32),
180+
Field(name="acc_rate", dtype=Float32),
181+
Field(name="avg_daily_trips", dtype=Int64),
182182
],
183183
online=True,
184184
batch_source=driver_hourly_stats,

docs/reference/data-sources/push.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ When using a PushSource as a stream source in the definition of a feature view,
1414
### Defining a push source
1515

1616
```python
17-
from feast import PushSource, ValueType, BigQuerySource, FeatureView, Feature
17+
from feast import PushSource, ValueType, BigQuerySource, FeatureView, Feature, Field, Int64
1818

1919
push_source = PushSource(
2020
name="push_source",
@@ -25,7 +25,7 @@ push_source = PushSource(
2525
fv = FeatureView(
2626
name="feature view",
2727
entities=["user_id"],
28-
features=[Feature(name="life_time_value", dtype=ValueType.INT64)],
28+
schema=[Field(name="life_time_value", dtype=Int64)],
2929
stream_source=push_source,
3030
)
3131
```

docs/reference/feature-repository.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ A feature repository can also contain one or more Python files that contain feat
8989
```python
9090
from datetime import timedelta
9191
92-
from feast import BigQuerySource, Entity, Feature, FeatureView, ValueType
92+
from feast import BigQuerySource, Entity, Feature, FeatureView, Field, Float32, String, ValueType
9393
9494
driver_locations_source = BigQuerySource(
9595
table_ref="rh_prod.ride_hailing_co.drivers",
@@ -107,9 +107,9 @@ driver_locations = FeatureView(
107107
name="driver_locations",
108108
entities=["driver"],
109109
ttl=timedelta(days=1),
110-
features=[
111-
Feature(name="lat", dtype=ValueType.FLOAT),
112-
Feature(name="lon", dtype=ValueType.STRING),
110+
schema=[
111+
Field(name="lat", dtype=Float32),
112+
Field(name="lon", dtype=String),
113113
],
114114
batch_source=driver_locations_source,
115115
)

docs/reference/feature-repository/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ A feature repository can also contain one or more Python files that contain feat
9494
```python
9595
from datetime import timedelta
9696
97-
from feast import BigQuerySource, Entity, Feature, FeatureView, ValueType
97+
from feast import BigQuerySource, Entity, Feature, FeatureView, Field, Float32, String, ValueType
9898
9999
driver_locations_source = BigQuerySource(
100100
table_ref="rh_prod.ride_hailing_co.drivers",
@@ -112,9 +112,9 @@ driver_locations = FeatureView(
112112
name="driver_locations",
113113
entities=["driver"],
114114
ttl=timedelta(days=1),
115-
features=[
116-
Feature(name="lat", dtype=ValueType.FLOAT),
117-
Feature(name="lon", dtype=ValueType.STRING),
115+
schema=[
116+
Field(name="lat", dtype=Float32),
117+
Field(name="lon", dtype=String),
118118
],
119119
batch_source=driver_locations_source,
120120
)

docs/tutorials/validating-historical-features.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pyarrow.parquet.write_table(entities_2019_table, "entities.parquet")
107107
import pyarrow.parquet
108108
import pandas as pd
109109

110-
from feast import Feature, FeatureView, Entity, FeatureStore
110+
from feast import Feature, FeatureView, Entity, FeatureStore, Field, Float64, Int64
111111
from feast.value_type import ValueType
112112
from feast.data_format import ParquetFormat
113113
from feast.on_demand_feature_view import on_demand_feature_view
@@ -137,10 +137,10 @@ trips_stats_fv = FeatureView(
137137
name='trip_stats',
138138
entities=['taxi'],
139139
features=[
140-
Feature("total_miles_travelled", ValueType.DOUBLE),
141-
Feature("total_trip_seconds", ValueType.DOUBLE),
142-
Feature("total_earned", ValueType.DOUBLE),
143-
Feature("trip_count", ValueType.INT64),
140+
Field(name="total_miles_travelled", dtype=Float64),
141+
Field(name="total_trip_seconds", dtype=Float64),
142+
Field(name="total_earned", dtype=Float64),
143+
Field(name="trip_count", dtype=Int64),
144144

145145
],
146146
ttl=Duration(seconds=86400),

protos/feast/core/FeatureView.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ message FeatureViewSpec {
4848
// Feature View. Not updatable.
4949
repeated string entities = 3;
5050

51-
// List of features specifications for each feature defined with this feature view.
51+
// List of specifications for each field defined as part of this feature view.
5252
repeated FeatureSpecV2 features = 4;
5353

5454
// Description of the feature view.

sdk/python/feast/__init__.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,22 @@
1313
from .feature_service import FeatureService
1414
from .feature_store import FeatureStore
1515
from .feature_view import FeatureView
16+
from .field import Field
1617
from .on_demand_feature_view import OnDemandFeatureView
1718
from .repo_config import RepoConfig
1819
from .request_feature_view import RequestFeatureView
20+
from .types import (
21+
Array,
22+
Bool,
23+
Bytes,
24+
Float32,
25+
Float64,
26+
Int32,
27+
Int64,
28+
Invalid,
29+
String,
30+
UnixTimestamp,
31+
)
1932
from .value_type import ValueType
2033

2134
logging.basicConfig(
@@ -35,6 +48,7 @@
3548
"KafkaSource",
3649
"KinesisSource",
3750
"Feature",
51+
"Field",
3852
"FeatureService",
3953
"FeatureStore",
4054
"FeatureView",
@@ -48,4 +62,15 @@
4862
"RequestFeatureView",
4963
"SnowflakeSource",
5064
"PushSource",
65+
# Types
66+
"Array",
67+
"Invalid",
68+
"Bytes",
69+
"String",
70+
"Bool",
71+
"Int32",
72+
"Int64",
73+
"Float32",
74+
"Float64",
75+
"UnixTimestamp",
5176
]

sdk/python/feast/base_feature_view.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
from google.protobuf.json_format import MessageToJson
1919
from proto import Message
2020

21-
from feast.feature import Feature
2221
from feast.feature_view_projection import FeatureViewProjection
22+
from feast.field import Field
2323

2424

2525
class BaseFeatureView(ABC):
@@ -41,7 +41,7 @@ class BaseFeatureView(ABC):
4141
"""
4242

4343
name: str
44-
features: List[Feature]
44+
features: List[Field]
4545
description: str
4646
tags: Dict[str, str]
4747
owner: str
@@ -53,8 +53,8 @@ class BaseFeatureView(ABC):
5353
def __init__(
5454
self,
5555
*,
56-
name: Optional[str] = None,
57-
features: Optional[List[Feature]] = None,
56+
name: str,
57+
features: Optional[List[Field]] = None,
5858
description: str = "",
5959
tags: Optional[Dict[str, str]] = None,
6060
owner: str = "",
@@ -64,7 +64,7 @@ def __init__(
6464
6565
Args:
6666
name: The unique name of the base feature view.
67-
features: The list of features defined as part of this base feature view.
67+
features (optional): The list of features defined as part of this base feature view.
6868
description (optional): A human-readable description.
6969
tags (optional): A dictionary of key-value pairs to store arbitrary metadata.
7070
owner (optional): The owner of the base feature view, typically the email of the
@@ -73,12 +73,9 @@ def __init__(
7373
Raises:
7474
ValueError: A field mapping conflicts with an Entity or a Feature.
7575
"""
76-
if not name:
77-
raise ValueError("Name needs to be provided")
76+
assert name is not None
7877
self.name = name
79-
8078
self.features = features or []
81-
8279
self.description = description
8380
self.tags = tags or {}
8481
self.owner = owner

0 commit comments

Comments
 (0)