Skip to content

Commit 80dd40d

Browse files
docs(samples): read, import, batch_serve, batch_create features (#1046)
* feat: SDK feature store samples (create/delete fs) * feat: adding to conftest.py * docs(samples): fixed testing * docs(samples): fixed testing * docs(samples): fixed testing * docs(samples) added changes * docs(samples): style issues * adding create entity * docs(samples): added create feature and entity type * docs(samples): edited test * docs(samples) edited style * moving constants * fixed dates * Update samples/model-builder/create_featurestore_sample_test.py Co-authored-by: Morgan Du <[email protected]> * Update samples/model-builder/test_constants.py Co-authored-by: Morgan Du <[email protected]> * Update samples/model-builder/create_featurestore_sample_test.py Co-authored-by: Morgan Du <[email protected]> * docs(samples): add samples to create/delete featurestore (#980) * feat: SDK feature store samples (create/delete fs) * feat: adding to conftest.py * docs(samples): fixed testing * docs(samples): fixed testing * docs(samples): fixed testing * docs(samples) added changes * docs(samples): style issues * Update samples/model-builder/create_featurestore_sample_test.py Co-authored-by: Morgan Du <[email protected]> * Update samples/model-builder/test_constants.py Co-authored-by: Morgan Du <[email protected]> * Update samples/model-builder/create_featurestore_sample_test.py Co-authored-by: Morgan Du <[email protected]> Co-authored-by: Morgan Du <[email protected]> * Update samples/model-builder/test_constants.py Co-authored-by: Morgan Du <[email protected]> * moving constants * added variables, made fixes, fixed spelling * batch_create_features_sample and test * added batch serve to bq and test * working on batch samples * fixed batch_serve_to_bq test * added read sample * moving constants * added featurestore samples * lint issues * adding revisions * adding revisions, fixing tests * editing spacing for readability Co-authored-by: Morgan Du <[email protected]>
1 parent 6383d4f commit 80dd40d

10 files changed

+440
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
# [START aiplatform_sdk_batch_create_features_sample]
17+
from google.cloud import aiplatform
18+
19+
20+
def batch_create_features_sample(
21+
project: str,
22+
location: str,
23+
entity_type_id: str,
24+
featurestore_id: str,
25+
sync: bool = True,
26+
):
27+
28+
aiplatform.init(project=project, location=location)
29+
30+
my_entity_type = aiplatform.featurestore.EntityType(
31+
entity_type_name=entity_type_id, featurestore_id=featurestore_id
32+
)
33+
34+
FEATURE_CONFIGS = {
35+
"age": {
36+
"value_type": "INT64",
37+
"description": "User age"
38+
},
39+
"gender": {
40+
"value_type": "STRING",
41+
"description": "User gender"
42+
},
43+
"liked_genres": {
44+
"value_type": "STRING_ARRAY",
45+
"description": "An array of genres this user liked",
46+
},
47+
}
48+
49+
my_entity_type.batch_create_features(feature_configs=FEATURE_CONFIGS, sync=sync)
50+
51+
52+
# [END aiplatform_sdk_batch_create_features_sample]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import batch_create_features_sample
16+
import test_constants as constants
17+
18+
19+
def test_batch_create_features_sample(
20+
mock_sdk_init, mock_get_entity_type, mock_batch_create_features
21+
):
22+
23+
batch_create_features_sample.batch_create_features_sample(
24+
project=constants.PROJECT,
25+
location=constants.LOCATION,
26+
entity_type_id=constants.ENTITY_TYPE_ID,
27+
featurestore_id=constants.FEATURESTORE_ID,
28+
sync=constants.SYNC,
29+
)
30+
31+
mock_sdk_init.assert_called_once_with(
32+
project=constants.PROJECT, location=constants.LOCATION
33+
)
34+
35+
mock_get_entity_type.assert_called_once_with(
36+
entity_type_name=constants.ENTITY_TYPE_ID,
37+
featurestore_id=constants.FEATURESTORE_ID,
38+
)
39+
40+
mock_batch_create_features.assert_called_once_with(
41+
feature_configs=constants.FEATURE_CONFIGS, sync=constants.SYNC
42+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
# [START aiplatform_sdk_batch_serve_features_to_bq_sample]
17+
from google.cloud import aiplatform
18+
19+
20+
def batch_serve_features_to_bq_sample(
21+
project: str,
22+
location: str,
23+
featurestore_name: str,
24+
bq_destination_output_uri: str,
25+
read_instances_uri: str,
26+
sync: bool = True,
27+
):
28+
29+
aiplatform.init(project=project, location=location)
30+
31+
fs = aiplatform.featurestore.Featurestore(featurestore_name=featurestore_name)
32+
33+
SERVING_FEATURE_IDS = {
34+
"users": ["age", "gender", "liked_genres"],
35+
"movies": ["title", "average_rating", "genres"],
36+
}
37+
38+
fs.batch_serve_to_bq(
39+
bq_destination_output_uri=bq_destination_output_uri,
40+
serving_feature_ids=SERVING_FEATURE_IDS,
41+
read_instances_uri=read_instances_uri,
42+
sync=sync,
43+
)
44+
45+
46+
# [END aiplatform_sdk_batch_serve_features_to_bq_sample]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import batch_serve_features_to_bq_sample
16+
import test_constants as constants
17+
18+
19+
def test_batch_serve_features_to_bq_sample(
20+
mock_sdk_init, mock_get_featurestore, mock_batch_serve_to_bq
21+
):
22+
23+
batch_serve_features_to_bq_sample.batch_serve_features_to_bq_sample(
24+
project=constants.PROJECT,
25+
location=constants.LOCATION,
26+
featurestore_name=constants.FEATURESTORE_NAME,
27+
bq_destination_output_uri=constants.BQ_DESTINATION_OUTPUT_URI,
28+
read_instances_uri=constants.INPUT_CSV_FILE,
29+
sync=constants.SYNC,
30+
)
31+
32+
mock_sdk_init.assert_called_once_with(
33+
project=constants.PROJECT, location=constants.LOCATION
34+
)
35+
36+
mock_get_featurestore.assert_called_once_with(
37+
featurestore_name=constants.FEATURESTORE_NAME
38+
)
39+
40+
mock_batch_serve_to_bq.assert_called_once_with(
41+
bq_destination_output_uri=constants.BQ_DESTINATION_OUTPUT_URI,
42+
serving_feature_ids=constants.SERVING_FEATURE_IDS,
43+
read_instances_uri=constants.INPUT_CSV_FILE,
44+
sync=constants.SYNC,
45+
)

samples/model-builder/conftest.py

+37-4
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ def mock_endpoint_explain(mock_endpoint):
368368

369369
"""
370370
----------------------------------------------------------------------------
371-
FeatureStore Fixtures
371+
Feature Store Fixtures
372372
----------------------------------------------------------------------------
373373
"""
374374

@@ -398,6 +398,13 @@ def mock_get_featurestore(mock_featurestore):
398398
yield mock_get_featurestore
399399

400400

401+
@pytest.fixture
402+
def mock_get_entity_type(mock_entity_type):
403+
with patch.object(aiplatform.featurestore, "EntityType") as mock_get_entity_type:
404+
mock_get_entity_type.return_value = mock_entity_type
405+
yield mock_get_entity_type
406+
407+
401408
@pytest.fixture
402409
def mock_create_featurestore(mock_featurestore):
403410
with patch.object(
@@ -418,9 +425,7 @@ def mock_create_entity_type(mock_entity_type):
418425

419426
@pytest.fixture
420427
def mock_create_feature(mock_feature):
421-
with patch.object(
422-
aiplatform.featurestore.Feature, "create"
423-
) as mock_create_feature:
428+
with patch.object(aiplatform.featurestore.Feature, "create") as mock_create_feature:
424429
mock_create_feature.return_value = mock_feature
425430
yield mock_create_feature
426431

@@ -429,3 +434,31 @@ def mock_create_feature(mock_feature):
429434
def mock_delete_featurestore(mock_featurestore):
430435
with patch.object(mock_featurestore, "delete") as mock_delete_featurestore:
431436
yield mock_delete_featurestore
437+
438+
439+
@pytest.fixture
440+
def mock_batch_serve_to_bq(mock_featurestore):
441+
with patch.object(mock_featurestore, "batch_serve_to_bq") as mock_batch_serve_to_bq:
442+
yield mock_batch_serve_to_bq
443+
444+
445+
@pytest.fixture
446+
def mock_batch_create_features(mock_entity_type):
447+
with patch.object(
448+
mock_entity_type, "batch_create_features"
449+
) as mock_batch_create_features:
450+
yield mock_batch_create_features
451+
452+
453+
@pytest.fixture
454+
def mock_read_feature_values(mock_entity_type):
455+
with patch.object(mock_entity_type, "read") as mock_read_feature_values:
456+
yield mock_read_feature_values
457+
458+
459+
@pytest.fixture
460+
def mock_import_feature_values(mock_entity_type):
461+
with patch.object(
462+
mock_entity_type, "ingest_from_gcs"
463+
) as mock_import_feature_values:
464+
yield mock_import_feature_values
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
# [START aiplatform_sdk_import_feature_values_sample]
17+
import datetime
18+
from typing import List, Union
19+
20+
from google.cloud import aiplatform
21+
22+
23+
def import_feature_values_sample(
24+
project: str,
25+
location: str,
26+
entity_type_id: str,
27+
featurestore_id: str,
28+
feature_ids: List[str],
29+
feature_time: Union[str, datetime.datetime],
30+
gcs_source_uris: Union[str, List[str]],
31+
gcs_source_type: str,
32+
):
33+
34+
aiplatform.init(project=project, location=location)
35+
36+
my_entity_type = aiplatform.featurestore.EntityType(
37+
entity_type_name=entity_type_id, featurestore_id=featurestore_id
38+
)
39+
40+
my_entity_type.ingest_from_gcs(
41+
feature_ids=feature_ids,
42+
feature_time=feature_time,
43+
gcs_source_uris=gcs_source_uris,
44+
gcs_source_type=gcs_source_type,
45+
)
46+
47+
48+
# [END aiplatform_sdk_import_feature_values_sample]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import import_feature_values_sample
16+
import test_constants as constants
17+
18+
19+
def test_import_feature_values_sample(
20+
mock_sdk_init, mock_get_entity_type, mock_import_feature_values
21+
):
22+
23+
import_feature_values_sample.import_feature_values_sample(
24+
project=constants.PROJECT,
25+
location=constants.LOCATION,
26+
entity_type_id=constants.ENTITY_TYPE_ID,
27+
featurestore_id=constants.FEATURESTORE_ID,
28+
feature_ids=constants.FEATURE_IDS,
29+
feature_time=constants.USERS_FEATURE_TIME,
30+
gcs_source_uris=constants.USERS_GCS_SOURCE_URI,
31+
gcs_source_type=constants.GCS_SOURCE_TYPE,
32+
)
33+
34+
mock_sdk_init.assert_called_once_with(
35+
project=constants.PROJECT, location=constants.LOCATION
36+
)
37+
38+
mock_get_entity_type.assert_called_once_with(
39+
entity_type_name=constants.ENTITY_TYPE_ID,
40+
featurestore_id=constants.FEATURESTORE_ID,
41+
)
42+
43+
mock_import_feature_values.assert_called_once_with(
44+
feature_ids=constants.FEATURE_IDS,
45+
feature_time=constants.USERS_FEATURE_TIME,
46+
gcs_source_uris=constants.USERS_GCS_SOURCE_URI,
47+
gcs_source_type=constants.GCS_SOURCE_TYPE,
48+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
# [START aiplatform_sdk_read_features_sample]
17+
from typing import List, Union
18+
19+
from google.cloud import aiplatform
20+
21+
22+
def read_feature_values_sample(
23+
project: str,
24+
location: str,
25+
entity_type_id: str,
26+
featurestore_id: str,
27+
entity_ids: Union[str, List[str]],
28+
feature_ids: Union[str, List[str]] = "*",
29+
):
30+
31+
aiplatform.init(project=project, location=location)
32+
33+
my_entity_type = aiplatform.featurestore.EntityType(
34+
entity_type_name=entity_type_id, featurestore_id=featurestore_id
35+
)
36+
37+
my_dataframe = my_entity_type.read(entity_ids=entity_ids, feature_ids=feature_ids)
38+
39+
return my_dataframe
40+
41+
42+
# [END aiplatform_sdk_read_features_sample]

0 commit comments

Comments
 (0)