Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/getting-started/concepts/feature-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,17 @@ It is suggested that you dynamically specify the new FeatureView name using `.wi
{% tabs %}
{% tab title="location_stats_feature_view.py" %}
```python
from feast import BigQuerySource, Entity, FeatureView, Field, ValueType
from feast.types import Int32
from feast import BigQuerySource, Entity, FeatureView, Field
from feast.types import Int32, Int64

location = Entity(name="location", join_keys=["location_id"], value_type=ValueType.INT64)
location = Entity(name="location", join_keys=["location_id"])

location_stats_fv= FeatureView(
name="location_stats",
entities=["location"],
schema=[
Field(name="temperature", dtype=Int32)
Field(name="temperature", dtype=Int32),
Field(name="location_id", dtype=Int64),
],
source=BigQuerySource(
table="feast-oss.demo_data.location_stats"
Expand Down
10 changes: 6 additions & 4 deletions docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ online_store:

from datetime import timedelta

from feast import Entity, FeatureService, FeatureView, Field, FileSource, ValueType
from feast import Entity, FeatureService, FeatureView, Field, FileSource
from feast.types import Float32, Int64

# Read data from parquet files. Parquet is convenient for local development mode. For
Expand All @@ -98,7 +98,7 @@ driver_hourly_stats = FileSource(
# fetch features.
# Entity has a name used for later reference (in a feature view, eg)
# and join_key to identify physical field name used in storages
driver = Entity(name="driver", value_type=ValueType.INT64, join_keys=["driver_id"], description="driver id",)
driver = Entity(name="driver", join_keys=["driver_id"], description="driver id",)

# Our parquet files contain sample data that includes a driver_id column, timestamps and
# three feature column. Here we define a Feature View that will allow us to serve this
Expand All @@ -111,6 +111,7 @@ driver_hourly_stats_view = FeatureView(
Field(name="conv_rate", dtype=Float32),
Field(name="acc_rate", dtype=Float32),
Field(name="avg_daily_trips", dtype=Int64),
Field(name="driver_id", dtype=Int64),
],
online=True,
source=driver_hourly_stats,
Expand Down Expand Up @@ -165,7 +166,7 @@ feast apply

from datetime import timedelta

from feast import Entity, FeatureView, Field, FileSource, ValueType
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64

# Read data from parquet files. Parquet is convenient for local development mode. For
Expand All @@ -181,7 +182,7 @@ driver_hourly_stats = FileSource(
# fetch features.
# Entity has a name used for later reference (in a feature view, eg)
# and join_key to identify physical field name used in storages
driver = Entity(name="driver", value_type=ValueType.INT64, join_keys=["driver_id"], description="driver id",)
driver = Entity(name="driver", join_keys=["driver_id"], description="driver id",)

# Our parquet files contain sample data that includes a driver_id column, timestamps and
# three feature column. Here we define a Feature View that will allow us to serve this
Expand All @@ -194,6 +195,7 @@ driver_hourly_stats_view = FeatureView(
Field(name="conv_rate", dtype=Float32),
Field(name="acc_rate", dtype=Float32),
Field(name="avg_daily_trips", dtype=Int64),
Field(name="driver_id", dtype=Int64),
],
online=True,
source=driver_hourly_stats,
Expand Down
6 changes: 3 additions & 3 deletions docs/reference/feature-repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ A feature repository can also contain one or more Python files that contain feat
```python
from datetime import timedelta

from feast import BigQuerySource, Entity, Feature, FeatureView, Field, ValueType
from feast.types import Float32, String
from feast import BigQuerySource, Entity, Feature, FeatureView, Field
from feast.types import Float32, Int64, String

driver_locations_source = BigQuerySource(
table="rh_prod.ride_hailing_co.drivers",
Expand All @@ -100,7 +100,6 @@ driver_locations_source = BigQuerySource(

driver = Entity(
name="driver",
value_type=ValueType.INT64,
description="driver id",
)

Expand All @@ -111,6 +110,7 @@ driver_locations = FeatureView(
schema=[
Field(name="lat", dtype=Float32),
Field(name="lon", dtype=String),
Field(name="driver", dtype=Int64),
],
source=driver_locations_source,
)
Expand Down
6 changes: 3 additions & 3 deletions docs/reference/feature-repository/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ A feature repository can also contain one or more Python files that contain feat
```python
from datetime import timedelta

from feast import BigQuerySource, Entity, Feature, FeatureView, Field, ValueType
from feast.types import Float32, String
from feast import BigQuerySource, Entity, Feature, FeatureView, Field
from feast.types import Float32, Int64, String

driver_locations_source = BigQuerySource(
table_ref="rh_prod.ride_hailing_co.drivers",
Expand All @@ -105,7 +105,6 @@ driver_locations_source = BigQuerySource(

driver = Entity(
name="driver",
value_type=ValueType.INT64,
description="driver id",
)

Expand All @@ -116,6 +115,7 @@ driver_locations = FeatureView(
schema=[
Field(name="lat", dtype=Float32),
Field(name="lon", dtype=String),
Field(name="driver", dtype=Int64),
],
source=driver_locations_source,
)
Expand Down
15 changes: 8 additions & 7 deletions go/internal/test/feature_repo/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

from google.protobuf.duration_pb2 import Duration

from feast import Entity, Feature, FeatureView, FileSource, ValueType, FeatureService
from feast import Entity, Feature, FeatureView, Field, FileSource, FeatureService
from feast.feature_logging import LoggingConfig
from feast.infra.offline_stores.file_source import FileLoggingDestination
from feast.types import Float32, Int64

# Read data from parquet files. Parquet is convenient for local development mode. For
# production, you can use your favorite DWH, such as BigQuery. See Feast documentation
Expand All @@ -17,19 +18,19 @@

# Define an entity for the driver. You can think of entity as a primary key used to
# fetch features.
driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",)
driver = Entity(name="driver_id", description="driver id")

# Our parquet files contain sample data that includes a driver_id column, timestamps and
# three feature column. Here we define a Feature View that will allow us to serve this
# data to our model online.
driver_hourly_stats_view = FeatureView(
name="driver_hourly_stats",
entities=["driver_id"],
entities=[driver],
ttl=Duration(seconds=86400 * 365 * 10),
features=[
Feature(name="conv_rate", dtype=ValueType.FLOAT),
Feature(name="acc_rate", dtype=ValueType.FLOAT),
Feature(name="avg_daily_trips", dtype=ValueType.INT64),
schema=[
Field(name="conv_rate", dtype=Float32),
Field(name="acc_rate", dtype=Float32),
Field(name="avg_daily_trips", dtype=Int64),
],
online=True,
batch_source=driver_hourly_stats,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def transformed_conv_rate(features_df: pd.DataFrame) -> pd.DataFrame:
path="benchmark_data.parquet", timestamp_field="event_timestamp",
)

entity = Entity(name="entity", value_type=ValueType.STRING,)
entity = Entity(name="entity")

benchmark_feature_views = [
FeatureView(
Expand Down
88 changes: 22 additions & 66 deletions sdk/python/feast/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import warnings
from datetime import datetime
from typing import Dict, List, Optional

Expand All @@ -33,7 +32,10 @@ class Entity:

Attributes:
name: The unique name of the entity.
value_type (deprecated): The type of the entity, such as string or float.
value_type: The type of the entity, such as string or float.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value type should be gone right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value_type is still an attribute of an entity; it's just not set during initialization, but instead inferred during type inference

join_keys: A list of properties that uniquely identifies different entities within the
collection. This currently only supports a list of size one, but is intended to
eventually support multiple join keys.
join_key: A property that uniquely identifies different entities within the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove join_key?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we haven't removed the usage of join_key throughout the codebase, so we still want to be able to do entity.join_key, which is why join_key is left as an attribute

I clarified the TODO below

collection. The join_key property is typically used for joining entities
with their associated features. If not specified, defaults to the name.
Expand All @@ -42,108 +44,62 @@ class Entity:
owner: The owner of the entity, typically the email of the primary maintainer.
created_timestamp: The time when the entity was created.
last_updated_timestamp: The time when the entity was last updated.
join_keys: A list of properties that uniquely identifies different entities within the
collection. This is meant to replace the `join_key` parameter, but currently only
supports a list of size one.
"""

name: str
value_type: ValueType
join_keys: List[str]
join_key: str
description: str
tags: Dict[str, str]
owner: str
created_timestamp: Optional[datetime]
last_updated_timestamp: Optional[datetime]
join_keys: List[str]

@log_exceptions
def __init__(
self,
*args,
name: Optional[str] = None,
value_type: Optional[ValueType] = None,
*,
name: str,
join_keys: Optional[List[str]] = None,
description: str = "",
join_key: Optional[str] = None,
tags: Optional[Dict[str, str]] = None,
owner: str = "",
join_keys: Optional[List[str]] = None,
):
"""
Creates an Entity object.

Args:
name: The unique name of the entity.
value_type (deprecated): The type of the entity, such as string or float.
description: A human-readable description.
join_key (deprecated): A property that uniquely identifies different entities within the
collection. The join_key property is typically used for joining entities
with their associated features. If not specified, defaults to the name.
tags: A dictionary of key-value pairs to store arbitrary metadata.
owner: The owner of the entity, typically the email of the primary maintainer.
join_keys: A list of properties that uniquely identifies different entities within the
collection. This is meant to replace the `join_key` parameter, but currently only
supports a list of size one.
join_keys (optional): A list of properties that uniquely identifies different entities
within the collection. This currently only supports a list of size one, but is
intended to eventually support multiple join keys.
description (optional): A human-readable description.
tags (optional): A dictionary of key-value pairs to store arbitrary metadata.
owner (optional): The owner of the entity, typically the email of the primary maintainer.

Raises:
ValueError: Parameters are specified incorrectly.
"""
if len(args) == 1:
warnings.warn(
(
"Entity name should be specified as a keyword argument instead of a positional arg."
"Feast 0.24+ will not support positional arguments to construct Entities"
),
DeprecationWarning,
)
if len(args) > 1:
raise ValueError(
"All arguments to construct an entity should be specified as keyword arguments only"
)

self.name = args[0] if len(args) > 0 else name

if not self.name:
raise ValueError("Name needs to be specified")

if value_type:
warnings.warn(
(
"The `value_type` parameter is being deprecated. Instead, the type of an entity "
"should be specified as a Field in the schema of a feature view. Feast 0.24 and "
"onwards will not support the `value_type` parameter. The `entities` parameter of "
"feature views should also be changed to a List[Entity] instead of a List[str]; if "
"this is not done, entity columns will be mistakenly interpreted as feature columns."
),
DeprecationWarning,
)
self.value_type = value_type or ValueType.UNKNOWN
self.name = name
self.value_type = ValueType.UNKNOWN

# For now, both the `join_key` and `join_keys` attributes are set correctly,
# so both are usable.
# TODO(felixwang9817): Remove the usage of `join_key` throughout the codebase
# when the usage of `join_key` as a parameter is removed.
if join_key:
warnings.warn(
(
"The `join_key` parameter is being deprecated in favor of the `join_keys` parameter. "
"Please switch from using `join_key` to `join_keys`. Feast 0.24 and onwards will not "
"support the `join_key` parameter."
),
DeprecationWarning,
)
self.join_keys = join_keys or []
# TODO(felixwang9817): Fully remove the usage of `join_key` throughout the codebase,
# at which point the `join_key` attribute no longer needs to be set.
if join_keys and len(join_keys) > 1:
raise ValueError(
"An entity may only have single join key. "
"Multiple join keys will be supported in the future."
)
if join_keys and len(join_keys) == 1:
elif join_keys and len(join_keys) == 1:
self.join_keys = join_keys
self.join_key = join_keys[0]
else:
self.join_key = join_key if join_key else self.name
if not self.join_keys:
self.join_key = self.name
self.join_keys = [self.join_key]

self.description = description
self.tags = tags if tags is not None else {}
self.owner = owner
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@

driver = Entity(
name="driver_id",
value_type=ValueType.INT64,
description="driver id",
join_key="driver_id", # Changed to `join_keys` in 0.20
join_keys=["driver_id"], # Changed to `join_keys` in 0.20
)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import timedelta

from feast import Entity, FeatureView, Field, FileSource, ValueType
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int32, Int64

driver_hourly_stats = FileSource(
Expand All @@ -9,7 +9,7 @@
created_timestamp_column="created",
)

driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id")
driver = Entity(name="driver_id", description="driver id")


driver_hourly_stats_view = FeatureView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ def test_lambda_materialization_consistency():
fs = lambda_environment.feature_store
driver = Entity(
name="driver_id",
join_key="driver_id",
value_type=ValueType.INT64,
join_keys=["driver_id"],
)

driver_stats_fv = FeatureView(
Expand Down
Loading