Skip to content

Commit 26f4881

Browse files
authored
feat: Adds description attribute for features/fields (feast-dev#3425)
* Adding description as a first-class attribute for features/fields Signed-off-by: Amom Mendes <[email protected]> * Formatting Signed-off-by: Amom Mendes <[email protected]> Signed-off-by: Amom Mendes <[email protected]>
1 parent 41c0537 commit 26f4881

File tree

7 files changed

+69
-4
lines changed

7 files changed

+69
-4
lines changed

protos/feast/core/Feature.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@ message FeatureSpecV2 {
3333

3434
// Tags for user defined metadata on a feature
3535
map<string,string> tags = 3;
36+
37+
// Description of the feature.
38+
39+
string description = 4;
3640
}

protos/feast/types/Field.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ option go_package = "github.com/feast-dev/feast/go/protos/feast/types";
2727
message Field {
2828
string name = 1;
2929
feast.types.ValueType.Enum value = 2;
30+
31+
// Tags for user defined metadata on a field
32+
map<string,string> tags = 3;
33+
34+
// Description of the field.
35+
string description = 4;
3036
}

sdk/python/feast/feature.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def __init__(
3333
self,
3434
name: str,
3535
dtype: ValueType,
36+
description: str = "",
3637
labels: Optional[Dict[str, str]] = None,
3738
):
3839
"""Creates a Feature object."""
@@ -42,6 +43,7 @@ def __init__(
4243
if dtype is ValueType.UNKNOWN:
4344
raise ValueError(f"dtype cannot be {dtype}")
4445
self._dtype = dtype
46+
self._description = description
4547
if labels is None:
4648
self._labels = dict()
4749
else:
@@ -77,6 +79,13 @@ def dtype(self) -> ValueType:
7779
"""
7880
return self._dtype
7981

82+
@property
83+
def description(self) -> str:
84+
"""
85+
Gets the description of the feature
86+
"""
87+
return self._description
88+
8089
@property
8190
def labels(self) -> Dict[str, str]:
8291
"""
@@ -96,6 +105,7 @@ def to_proto(self) -> FeatureSpecProto:
96105
return FeatureSpecProto(
97106
name=self.name,
98107
value_type=value_type,
108+
description=self.description,
99109
tags=self.labels,
100110
)
101111

@@ -111,6 +121,7 @@ def from_proto(cls, feature_proto: FeatureSpecProto):
111121
feature = cls(
112122
name=feature_proto.name,
113123
dtype=ValueType(feature_proto.value_type),
124+
description=feature_proto.description,
114125
labels=dict(feature_proto.tags),
115126
)
116127

sdk/python/feast/field.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Field:
3030
Attributes:
3131
name: The name of the field.
3232
dtype: The type of the field, such as string or float.
33-
tags: User-defined metadata in dictionary form.
33+
tags (optional): User-defined metadata in dictionary form.
3434
"""
3535

3636
name: str
@@ -42,6 +42,7 @@ def __init__(
4242
*,
4343
name: str,
4444
dtype: FeastType,
45+
description: str = "",
4546
tags: Optional[Dict[str, str]] = None,
4647
):
4748
"""
@@ -54,6 +55,7 @@ def __init__(
5455
"""
5556
self.name = name
5657
self.dtype = dtype
58+
self.description = description
5759
self.tags = tags or {}
5860

5961
def __eq__(self, other):
@@ -83,7 +85,12 @@ def __str__(self):
8385
def to_proto(self) -> FieldProto:
8486
"""Converts a Field object to its protobuf representation."""
8587
value_type = self.dtype.to_value_type()
86-
return FieldProto(name=self.name, value_type=value_type.value, tags=self.tags)
88+
return FieldProto(
89+
name=self.name,
90+
value_type=value_type.value,
91+
description=self.description,
92+
tags=self.tags,
93+
)
8794

8895
@classmethod
8996
def from_proto(cls, field_proto: FieldProto):
@@ -109,5 +116,8 @@ def from_feature(cls, feature: Feature):
109116
feature: Feature object to convert.
110117
"""
111118
return cls(
112-
name=feature.name, dtype=from_value_type(feature.dtype), tags=feature.labels
119+
name=feature.name,
120+
dtype=from_value_type(feature.dtype),
121+
description=feature.description,
122+
tags=feature.labels,
113123
)

sdk/python/feast/templates/local/feature_repo/example_repo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
schema=[
4646
Field(name="conv_rate", dtype=Float32),
4747
Field(name="acc_rate", dtype=Float32),
48-
Field(name="avg_daily_trips", dtype=Int64),
48+
Field(name="avg_daily_trips", dtype=Int64, description="Average daily trips"),
4949
],
5050
online=True,
5151
source=driver_stats_source,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from feast.field import Feature, Field
2+
from feast.types import Float32
3+
from feast.value_type import ValueType
4+
5+
6+
def test_feature_serialization_with_description():
7+
expected_description = "Average daily trips"
8+
feature = Feature(
9+
name="avg_daily_trips", dtype=ValueType.FLOAT, description=expected_description
10+
)
11+
serialized_feature = feature.to_proto()
12+
13+
assert serialized_feature.description == expected_description
14+
15+
16+
def test_field_serialization_with_description():
17+
expected_description = "Average daily trips"
18+
field = Field(
19+
name="avg_daily_trips", dtype=Float32, description=expected_description
20+
)
21+
feature = Feature(
22+
name="avg_daily_trips", dtype=ValueType.FLOAT, description=expected_description
23+
)
24+
25+
serialized_field = field.to_proto()
26+
field_from_feature = Field.from_feature(feature)
27+
28+
assert serialized_field.description == expected_description
29+
assert field_from_feature.description == expected_description

ui/src/pages/features/FeatureOverviewTab.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ const FeatureOverviewTab = () => {
5555
{feast.types.ValueType.Enum[featureData?.valueType!]}
5656
</EuiDescriptionListDescription>
5757

58+
<EuiDescriptionListTitle>Description</EuiDescriptionListTitle>
59+
<EuiDescriptionListDescription>
60+
{featureData?.description}
61+
</EuiDescriptionListDescription>
62+
5863
<EuiDescriptionListTitle>FeatureView</EuiDescriptionListTitle>
5964
<EuiDescriptionListDescription>
6065
<EuiCustomLink

0 commit comments

Comments
 (0)