Exemple #1
0
    def apply_feature_view(self,
                           feature_view: FeatureView,
                           project: str,
                           commit: bool = True):
        """
        Registers a single feature view with Feast

        Args:
            feature_view: Feature view that will be registered
            project: Feast project that this feature view belongs to
            commit: Whether the change should be persisted immediately
        """
        feature_view.is_valid()
        feature_view_proto = feature_view.to_proto()
        feature_view_proto.spec.project = project
        self._prepare_registry_for_changes()
        assert self.cached_registry_proto

        for idx, existing_feature_view_proto in enumerate(
                self.cached_registry_proto.feature_views):
            if (existing_feature_view_proto.spec.name
                    == feature_view_proto.spec.name
                    and existing_feature_view_proto.spec.project == project):
                if FeatureView.from_proto(
                        existing_feature_view_proto) == feature_view:
                    return
                else:
                    del self.cached_registry_proto.feature_views[idx]
                    break

        self.cached_registry_proto.feature_views.append(feature_view_proto)
        if commit:
            self.commit()
Exemple #2
0
    def plan(self, config: RepoConfig,
             desired_registry_proto: RegistryProto) -> List[InfraObject]:
        project = config.project

        infra_objects: List[InfraObject] = [
            SqliteTable(
                path=self._get_db_path(config),
                name=_table_id(project, FeatureView.from_proto(view)),
            ) for view in desired_registry_proto.feature_views
        ]
        return infra_objects
Exemple #3
0
    def from_proto(cls,
                   on_demand_feature_view_proto: OnDemandFeatureViewProto):
        """
        Creates an on demand feature view from a protobuf representation.

        Args:
            on_demand_feature_view_proto: A protobuf representation of an on-demand feature view.

        Returns:
            A OnDemandFeatureView object based on the on-demand feature view protobuf.
        """
        inputs = {}
        for (
                input_name,
                on_demand_input,
        ) in on_demand_feature_view_proto.spec.inputs.items():
            if on_demand_input.WhichOneof("input") == "feature_view":
                inputs[input_name] = FeatureView.from_proto(
                    on_demand_input.feature_view).projection
            elif on_demand_input.WhichOneof(
                    "input") == "feature_view_projection":
                inputs[input_name] = FeatureViewProjection.from_proto(
                    on_demand_input.feature_view_projection)
            else:
                inputs[input_name] = RequestDataSource.from_proto(
                    on_demand_input.request_data_source)
        on_demand_feature_view_obj = cls(
            name=on_demand_feature_view_proto.spec.name,
            features=[
                Feature(
                    name=feature.name,
                    dtype=ValueType(feature.value_type),
                    labels=dict(feature.labels),
                ) for feature in on_demand_feature_view_proto.spec.features
            ],
            inputs=inputs,
            udf=dill.loads(
                on_demand_feature_view_proto.spec.user_defined_function.body),
        )

        # FeatureViewProjections are not saved in the OnDemandFeatureView proto.
        # Create the default projection.
        on_demand_feature_view_obj.projection = FeatureViewProjection.from_definition(
            on_demand_feature_view_obj)

        if on_demand_feature_view_proto.meta.HasField("created_timestamp"):
            on_demand_feature_view_obj.created_timestamp = (
                on_demand_feature_view_proto.meta.created_timestamp.ToDatetime(
                ))

        return on_demand_feature_view_obj
Exemple #4
0
    def list_feature_views(self, project: str) -> List[FeatureView]:
        """
        Retrieve a list of feature views from the registry

        Args:
            project: Filter feature tables based on project name

        Returns:
            List of feature tables
        """
        registry_proto = self._registry_store.get_registry()
        feature_views = []
        for feature_view_proto in registry_proto.feature_views:
            if feature_view_proto.spec.project == project:
                feature_views.append(
                    FeatureView.from_proto(feature_view_proto))
        return feature_views
Exemple #5
0
    def get_feature_view(self, name: str, project: str) -> FeatureView:
        """
        Retrieves a feature view.

        Args:
            name: Name of feature view
            project: Feast project that this feature view belongs to

        Returns:
            Returns either the specified feature view, or raises an exception if
            none is found
        """
        registry_proto = self._get_registry_proto()
        for feature_view_proto in registry_proto.feature_views:
            if (feature_view_proto.spec.name == name
                    and feature_view_proto.spec.project == project):
                return FeatureView.from_proto(feature_view_proto)
        raise FeatureViewNotFoundException(name, project)
Exemple #6
0
    def list_feature_views(
        self, project: str, allow_cache: bool = False
    ) -> List[FeatureView]:
        """
        Retrieve a list of feature views from the registry

        Args:
            allow_cache: Allow returning feature views from the cached registry
            project: Filter feature tables based on project name

        Returns:
            List of feature views
        """
        registry_proto = self._get_registry_proto(allow_cache=allow_cache)
        feature_views = []
        for feature_view_proto in registry_proto.feature_views:
            if feature_view_proto.spec.project == project:
                feature_views.append(FeatureView.from_proto(feature_view_proto))
        return feature_views
Exemple #7
0
 def updater(registry_proto: RegistryProto):
     for idx, existing_feature_view_proto in enumerate(
         registry_proto.feature_views
     ):
         if (
             existing_feature_view_proto.spec.name == feature_view.name
             and existing_feature_view_proto.spec.project == project
         ):
             existing_feature_view = FeatureView.from_proto(
                 existing_feature_view_proto
             )
             existing_feature_view.materialization_intervals.append(
                 (start_date, end_date)
             )
             feature_view_proto = existing_feature_view.to_proto()
             feature_view_proto.spec.project = project
             del registry_proto.feature_views[idx]
             registry_proto.feature_views.append(feature_view_proto)
             return registry_proto
     raise FeatureViewNotFoundException(feature_view.name, project)
Exemple #8
0
    def apply_materialization(
        self,
        feature_view: FeatureView,
        project: str,
        start_date: datetime,
        end_date: datetime,
        commit: bool = True,
    ):
        """
        Updates materialization intervals tracked for a single feature view in Feast

        Args:
            feature_view: Feature view that will be updated with an additional materialization interval tracked
            project: Feast project that this feature view belongs to
            start_date (datetime): Start date of the materialization interval to track
            end_date (datetime): End date of the materialization interval to track
            commit: Whether the change should be persisted immediately
        """
        self._prepare_registry_for_changes()
        assert self.cached_registry_proto

        for idx, existing_feature_view_proto in enumerate(
                self.cached_registry_proto.feature_views):
            if (existing_feature_view_proto.spec.name == feature_view.name
                    and existing_feature_view_proto.spec.project == project):
                existing_feature_view = FeatureView.from_proto(
                    existing_feature_view_proto)
                existing_feature_view.materialization_intervals.append(
                    (start_date, end_date))
                existing_feature_view.last_updated_timestamp = datetime.utcnow(
                )
                feature_view_proto = existing_feature_view.to_proto()
                feature_view_proto.spec.project = project
                del self.cached_registry_proto.feature_views[idx]
                self.cached_registry_proto.feature_views.append(
                    feature_view_proto)
                if commit:
                    self.commit()
                return

        raise FeatureViewNotFoundException(feature_view.name, project)
Exemple #9
0
 def updater(registry_proto: RegistryProto):
     for idx, existing_feature_view_proto in enumerate(
         registry_proto.feature_views
     ):
         if (
             existing_feature_view_proto.spec.name
             == feature_view_proto.spec.name
             and existing_feature_view_proto.spec.project == project
         ):
             # do not update if feature view has not changed; updating will erase tracked materialization intervals
             if (
                 FeatureView.from_proto(existing_feature_view_proto)
                 == feature_view
             ):
                 return registry_proto
             else:
                 del registry_proto.feature_views[idx]
                 registry_proto.feature_views.append(feature_view_proto)
                 return registry_proto
     registry_proto.feature_views.append(feature_view_proto)
     return registry_proto
Exemple #10
0
    def from_proto(cls,
                   on_demand_feature_view_proto: OnDemandFeatureViewProto):
        """
        Creates an on demand feature view from a protobuf representation.

        Args:
            on_demand_feature_view_proto: A protobuf representation of an on-demand feature view.

        Returns:
            A OnDemandFeatureView object based on the on-demand feature view protobuf.
        """
        inputs = {}
        for (
                input_name,
                on_demand_input,
        ) in on_demand_feature_view_proto.spec.inputs.items():
            if on_demand_input.WhichOneof("input") == "feature_view":
                inputs[input_name] = FeatureView.from_proto(
                    on_demand_input.feature_view)
            else:
                inputs[input_name] = RequestDataSource.from_proto(
                    on_demand_input.request_data_source)
        on_demand_feature_view_obj = cls(
            name=on_demand_feature_view_proto.spec.name,
            features=[
                Feature(
                    name=feature.name,
                    dtype=ValueType(feature.value_type),
                    labels=dict(feature.labels),
                ) for feature in on_demand_feature_view_proto.spec.features
            ],
            inputs=inputs,
            udf=dill.loads(
                on_demand_feature_view_proto.spec.user_defined_function.body),
        )

        return on_demand_feature_view_obj
Exemple #11
0
    def from_proto(cls,
                   on_demand_feature_view_proto: OnDemandFeatureViewProto):
        """
        Creates an on demand feature view from a protobuf representation.

        Args:
            on_demand_feature_view_proto: A protobuf representation of an on-demand feature view.

        Returns:
            A OnDemandFeatureView object based on the on-demand feature view protobuf.
        """
        sources = []
        for (
                _,
                on_demand_source,
        ) in on_demand_feature_view_proto.spec.sources.items():
            if on_demand_source.WhichOneof("source") == "feature_view":
                sources.append(
                    FeatureView.from_proto(
                        on_demand_source.feature_view).projection)
            elif on_demand_source.WhichOneof(
                    "source") == "feature_view_projection":
                sources.append(
                    FeatureViewProjection.from_proto(
                        on_demand_source.feature_view_projection))
            else:
                sources.append(
                    RequestSource.from_proto(
                        on_demand_source.request_data_source))
        on_demand_feature_view_obj = cls(
            name=on_demand_feature_view_proto.spec.name,
            schema=[
                Field(
                    name=feature.name,
                    dtype=from_value_type(ValueType(feature.value_type)),
                ) for feature in on_demand_feature_view_proto.spec.features
            ],
            sources=sources,
            udf=dill.loads(
                on_demand_feature_view_proto.spec.user_defined_function.body),
            description=on_demand_feature_view_proto.spec.description,
            tags=dict(on_demand_feature_view_proto.spec.tags),
            owner=on_demand_feature_view_proto.spec.owner,
        )

        # FeatureViewProjections are not saved in the OnDemandFeatureView proto.
        # Create the default projection.
        on_demand_feature_view_obj.projection = FeatureViewProjection.from_definition(
            on_demand_feature_view_obj)

        if on_demand_feature_view_proto.meta.HasField("created_timestamp"):
            on_demand_feature_view_obj.created_timestamp = (
                on_demand_feature_view_proto.meta.created_timestamp.ToDatetime(
                ))
        if on_demand_feature_view_proto.meta.HasField(
                "last_updated_timestamp"):
            on_demand_feature_view_obj.last_updated_timestamp = (
                on_demand_feature_view_proto.meta.last_updated_timestamp.
                ToDatetime())

        return on_demand_feature_view_obj