Skip to content

Commit d7a89a0

Browse files
vertex-sdk-botcopybara-github
authored andcommitted
refactor: make create_feature_view method more generic - drop BigQuery naming
Move BigQuerySource to util file to avoid circular dep + a few lint fixes. PiperOrigin-RevId: 629484260
1 parent 3a36784 commit d7a89a0

File tree

6 files changed

+63
-36
lines changed

6 files changed

+63
-36
lines changed

tests/unit/vertexai/test_feature_online_store.py

+25-14
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from vertexai.resources.preview import (
2929
FeatureOnlineStore,
3030
FeatureOnlineStoreType,
31-
FeatureView,
31+
FeatureViewBigQuerySource,
3232
IndexConfig,
3333
DistanceMeasureType,
3434
TreeAhConfig,
@@ -361,15 +361,26 @@ def test_delete(force, delete_fos_mock, get_fos_mock, fos_logger_mock, sync=True
361361
)
362362

363363

364-
def test_create_bq_fv_none_source_raises_error(get_fos_mock):
364+
def test_create_fv_none_source_raises_error(get_fos_mock):
365365
aiplatform.init(project=_TEST_PROJECT, location=_TEST_LOCATION)
366366
fos = FeatureOnlineStore(_TEST_BIGTABLE_FOS1_ID)
367367

368368
with pytest.raises(
369369
ValueError,
370-
match=re.escape("Please specify valid big_query_source."),
370+
match=re.escape("Please specify a valid source."),
371371
):
372-
fos.create_feature_view_from_big_query("bq_fv", None)
372+
fos.create_feature_view("bq_fv", None)
373+
374+
375+
def test_create_fv_wrong_object_type_raises_error(get_fos_mock):
376+
aiplatform.init(project=_TEST_PROJECT, location=_TEST_LOCATION)
377+
fos = FeatureOnlineStore(_TEST_BIGTABLE_FOS1_ID)
378+
379+
with pytest.raises(
380+
ValueError,
381+
match=re.escape("Only FeatureViewBigQuerySource is a supported source."),
382+
):
383+
fos.create_feature_view("bq_fv", fos)
373384

374385

375386
def test_create_bq_fv_bad_uri_raises_error(get_fos_mock):
@@ -378,11 +389,11 @@ def test_create_bq_fv_bad_uri_raises_error(get_fos_mock):
378389

379390
with pytest.raises(
380391
ValueError,
381-
match=re.escape("Please specify URI in big_query_source."),
392+
match=re.escape("Please specify URI in BigQuery source."),
382393
):
383-
fos.create_feature_view_from_big_query(
394+
fos.create_feature_view(
384395
"bq_fv",
385-
FeatureView.BigQuerySource(uri=None, entity_id_columns=["entity_id"]),
396+
FeatureViewBigQuerySource(uri=None, entity_id_columns=["entity_id"]),
386397
)
387398

388399

@@ -395,11 +406,11 @@ def test_create_bq_fv_bad_entity_id_columns_raises_error(
395406

396407
with pytest.raises(
397408
ValueError,
398-
match=re.escape("Please specify entity ID columns in big_query_source."),
409+
match=re.escape("Please specify entity ID columns in BigQuery source."),
399410
):
400-
fos.create_feature_view_from_big_query(
411+
fos.create_feature_view(
401412
"bq_fv",
402-
FeatureView.BigQuerySource(uri="hi", entity_id_columns=entity_id_columns),
413+
FeatureViewBigQuerySource(uri="hi", entity_id_columns=entity_id_columns),
403414
)
404415

405416

@@ -416,9 +427,9 @@ def test_create_bq_fv(
416427
aiplatform.init(project=_TEST_PROJECT, location=_TEST_LOCATION)
417428
fos = FeatureOnlineStore(_TEST_BIGTABLE_FOS1_ID)
418429

419-
fv = fos.create_feature_view_from_big_query(
430+
fv = fos.create_feature_view(
420431
_TEST_FV1_ID,
421-
FeatureView.BigQuerySource(
432+
FeatureViewBigQuerySource(
422433
uri=_TEST_FV1_BQ_URI, entity_id_columns=_TEST_FV1_ENTITY_ID_COLUMNS
423434
),
424435
labels=_TEST_FV1_LABELS,
@@ -478,9 +489,9 @@ def test_create_embedding_fv(
478489
aiplatform.init(project=_TEST_PROJECT, location=_TEST_LOCATION)
479490
fos = FeatureOnlineStore(_TEST_ESF_OPTIMIZED_FOS_ID)
480491

481-
embedding_fv = fos.create_feature_view_from_big_query(
492+
embedding_fv = fos.create_feature_view(
482493
_TEST_OPTIMIZED_EMBEDDING_FV_ID,
483-
FeatureView.BigQuerySource(uri="hi", entity_id_columns=["entity_id"]),
494+
FeatureViewBigQuerySource(uri="hi", entity_id_columns=["entity_id"]),
484495
index_config=IndexConfig(
485496
embedding_column="embedding",
486497
dimensions=1536,

vertexai/resources/preview/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
FeatureOnlineStore,
3939
FeatureOnlineStoreType,
4040
FeatureView,
41+
FeatureViewBigQuerySource,
4142
FeatureViewReadResponse,
4243
IndexConfig,
4344
TreeAhConfig,
@@ -60,6 +61,7 @@
6061
"FeatureOnlineStoreType",
6162
"FeatureOnlineStore",
6263
"FeatureView",
64+
"FeatureViewBigQuerySource",
6365
"FeatureViewReadResponse",
6466
"IndexConfig",
6567
"TreeAhConfig",

vertexai/resources/preview/feature_store/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
)
2727

2828
from vertexai.resources.preview.feature_store.utils import (
29+
FeatureViewBigQuerySource,
2930
FeatureViewReadResponse,
3031
IndexConfig,
3132
TreeAhConfig,
@@ -38,6 +39,7 @@
3839
FeatureOnlineStoreType,
3940
FeatureOnlineStore,
4041
FeatureView,
42+
FeatureViewBigQuerySource,
4143
FeatureViewReadResponse,
4244
IndexConfig,
4345
IndexConfig,

vertexai/resources/preview/feature_store/feature_online_store.py

+27-14
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
)
3939
from vertexai.resources.preview.feature_store.utils import (
4040
IndexConfig,
41+
FeatureViewBigQuerySource,
4142
)
4243

4344

@@ -377,10 +378,10 @@ def labels(self) -> Dict[str, str]:
377378
return self._gca_resource.labels
378379

379380
@base.optional_sync()
380-
def create_feature_view_from_big_query(
381+
def create_feature_view(
381382
self,
382383
name: str,
383-
big_query_source: FeatureView.BigQuerySource,
384+
source: FeatureViewBigQuerySource,
384385
labels: Optional[Dict[str, str]] = None,
385386
sync_config: Optional[str] = None,
386387
index_config: Optional[IndexConfig] = None,
@@ -390,7 +391,7 @@ def create_feature_view_from_big_query(
390391
request_metadata: Optional[Sequence[Tuple[str, str]]] = None,
391392
create_request_timeout: Optional[float] = None,
392393
sync: bool = True,
393-
) -> "FeatureView":
394+
) -> FeatureView:
394395
"""Creates a FeatureView from a BigQuery source.
395396
396397
Example Usage:
@@ -422,9 +423,9 @@ def create_feature_view_from_big_query(
422423
```
423424
Args:
424425
name: The name of the feature view.
425-
big_query_source:
426-
The BigQuery source to load data from when a feature view sync
427-
runs.
426+
source:
427+
The source to load data from when a feature view sync runs.
428+
Currently supports a BigQuery source.
428429
labels:
429430
The labels with user-defined metadata to organize your
430431
FeatureViews.
@@ -445,6 +446,11 @@ def create_feature_view_from_big_query(
445446
for each entity ID of this FeatureView are made ready for online
446447
serving. Example format: "TZ=America/New_York 0 9 * * *" (sync
447448
daily at 9 AM EST).
449+
index_config:
450+
Configuration for index preparation for vector search. It
451+
contains the required configurations to create an index from
452+
source data, so that approximate nearest neighbor (a.k.a ANN)
453+
algorithms search can be performed during online serving.
448454
project:
449455
Project to create feature view in. If unset, the project set in
450456
aiplatform.init will be used.
@@ -467,17 +473,24 @@ def create_feature_view_from_big_query(
467473
Returns:
468474
FeatureView - the FeatureView resource object.
469475
"""
470-
if not big_query_source:
471-
raise ValueError("Please specify valid big_query_source.")
472-
elif not big_query_source.uri:
473-
raise ValueError("Please specify URI in big_query_source.")
474-
elif not big_query_source.entity_id_columns:
475-
raise ValueError("Please specify entity ID columns in big_query_source.")
476+
if not source:
477+
raise ValueError("Please specify a valid source.")
478+
479+
# Only BigQuery source is supported right now.
480+
if not isinstance(source, FeatureViewBigQuerySource):
481+
raise ValueError("Only FeatureViewBigQuerySource is a supported source.")
482+
483+
# BigQuery source validation.
484+
if not source.uri:
485+
raise ValueError("Please specify URI in BigQuery source.")
486+
487+
if not source.entity_id_columns:
488+
raise ValueError("Please specify entity ID columns in BigQuery source.")
476489

477490
gapic_feature_view = gca_feature_view.FeatureView(
478491
big_query_source=gca_feature_view.FeatureView.BigQuerySource(
479-
uri=big_query_source.uri,
480-
entity_id_columns=big_query_source.entity_id_columns,
492+
uri=source.uri,
493+
entity_id_columns=source.entity_id_columns,
481494
),
482495
sync_config=gca_feature_view.FeatureView.SyncConfig(cron=sync_config)
483496
if sync_config

vertexai/resources/preview/feature_store/feature_view.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
# limitations under the License.
1616
#
1717

18-
from dataclasses import dataclass
1918
import re
2019
from typing import List, Optional
2120
from google.cloud.aiplatform import initializer
@@ -342,8 +341,7 @@ def search(
342341
)
343342
else:
344343
raise ValueError(
345-
f"Either entity_id or embedding_value needs to be provided for"
346-
f" search."
344+
"Either entity_id or embedding_value needs to be provided for search."
347345
)
348346
response = self._get_online_store_client.search_nearest_entities(
349347
request=fos_service.SearchNearestEntitiesRequest(
@@ -365,11 +363,6 @@ def search(
365363
)
366364
return fv_utils.SearchNearestEntitiesResponse(response)
367365

368-
@dataclass
369-
class BigQuerySource:
370-
uri: str
371-
entity_id_columns: List[str]
372-
373366
class FeatureViewSync(base.VertexAiResourceNounWithFutureManager):
374367
"""Class for managing Feature View Sync resources."""
375368

vertexai/resources/preview/feature_store/utils.py

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ class PublicEndpointNotFoundError(RuntimeError):
4444
"""Public endpoint has not been created yet."""
4545

4646

47+
@dataclass
48+
class FeatureViewBigQuerySource:
49+
uri: str
50+
entity_id_columns: List[str]
51+
52+
4753
@dataclass
4854
class FeatureViewReadResponse:
4955
_response: fos_service.FetchFeatureValuesResponse

0 commit comments

Comments
 (0)