diff --git a/bigframes/_config/display_options.py b/bigframes/_config/display_options.py index 2af07d30a8..dc8ab34f2a 100644 --- a/bigframes/_config/display_options.py +++ b/bigframes/_config/display_options.py @@ -35,6 +35,10 @@ class DisplayOptions: max_info_rows: Optional[int] = 200000 memory_usage: bool = True + blob_display: bool = True + blob_display_width: Optional[int] = None + blob_display_height: Optional[int] = None + @contextlib.contextmanager def pandas_repr(display_options: DisplayOptions): diff --git a/bigframes/_config/experiment_options.py b/bigframes/_config/experiment_options.py index cfbcc04cfd..024de392c0 100644 --- a/bigframes/_config/experiment_options.py +++ b/bigframes/_config/experiment_options.py @@ -15,6 +15,7 @@ from typing import Optional import warnings +import bigframes import bigframes.exceptions as bfe @@ -26,10 +27,6 @@ class ExperimentOptions: def __init__(self): self._semantic_operators: bool = False self._ai_operators: bool = False - self._blob: bool = False - self._blob_display: bool = True - self._blob_display_width: Optional[int] = None - self._blob_display_height: Optional[int] = None @property def semantic_operators(self) -> bool: @@ -60,41 +57,72 @@ def ai_operators(self, value: bool): @property def blob(self) -> bool: - return self._blob + msg = bfe.format_message( + "BigFrames Blob is in preview now. This flag is no longer needed." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + return True @blob.setter def blob(self, value: bool): - if value is True: - msg = bfe.format_message( - "BigFrames Blob is still under experiments. It may not work and " - "subject to change in the future." - ) - warnings.warn(msg, category=bfe.PreviewWarning) - self._blob = value + msg = bfe.format_message( + "BigFrames Blob is in preview now. This flag is no longer needed." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) @property def blob_display(self) -> bool: """Whether to display the blob content in notebook DataFrame preview. Default True.""" - return self._blob_display + msg = bfe.format_message( + "BigFrames Blob is in preview now. The option has been moved to bigframes.options.display.blob_display." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + + return bigframes.options.display.blob_display @blob_display.setter def blob_display(self, value: bool): - self._blob_display = value + msg = bfe.format_message( + "BigFrames Blob is in preview now. The option has been moved to bigframes.options.display.blob_display." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + + bigframes.options.display.blob_display = value @property def blob_display_width(self) -> Optional[int]: """Width in pixels that the blob constrained to.""" - return self._blob_display_width + msg = bfe.format_message( + "BigFrames Blob is in preview now. The option has been moved to bigframes.options.display.blob_display_width." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + + return bigframes.options.display.blob_display_width @blob_display_width.setter def blob_display_width(self, value: Optional[int]): - self._blob_display_width = value + msg = bfe.format_message( + "BigFrames Blob is in preview now. The option has been moved to bigframes.options.display.blob_display_width." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + + bigframes.options.display.blob_display_width = value @property def blob_display_height(self) -> Optional[int]: """Height in pixels that the blob constrained to.""" - return self._blob_display_height + msg = bfe.format_message( + "BigFrames Blob is in preview now. The option has been moved to bigframes.options.display.blob_display_height." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + + return bigframes.options.display.blob_display_height @blob_display_height.setter def blob_display_height(self, value: Optional[int]): - self._blob_display_height = value + msg = bfe.format_message( + "BigFrames Blob is in preview now. The option has been moved to bigframes.options.display.blob_display_height." + ) + warnings.warn(msg, category=bfe.ApiDeprecationWarning) + + bigframes.options.display.blob_display_height = value diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index 9cb388329e..e64aec307a 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -768,14 +768,11 @@ def _repr_html_(self) -> str: return formatter.repr_query_job(self._compute_dry_run()) df = self.copy() - if ( - bigframes.options.experiments.blob - and bigframes.options.experiments.blob_display - ): + if bigframes.options.display.blob_display: blob_cols = [ - col - for col in df.columns - if df[col].dtype == bigframes.dtypes.OBJ_REF_DTYPE + series_name + for series_name, series in df.items() + if series.dtype == bigframes.dtypes.OBJ_REF_DTYPE ] for col in blob_cols: # TODO(garrettwu): Not necessary to get access urls for all the rows. Update when having a to get URLs from local data. @@ -794,10 +791,7 @@ def _repr_html_(self) -> str: with display_options.pandas_repr(opts): # Allows to preview images in the DataFrame. The implementation changes the string repr as well, that it doesn't truncate strings or escape html charaters such as "<" and ">". We may need to implement a full-fledged repr module to better support types not in pandas. - if ( - bigframes.options.experiments.blob - and bigframes.options.experiments.blob_display - ): + if bigframes.options.display.blob_display and blob_cols: def obj_ref_rt_to_html(obj_ref_rt) -> str: obj_ref_rt_json = json.loads(obj_ref_rt) @@ -809,12 +803,12 @@ def obj_ref_rt_to_html(obj_ref_rt) -> str: ) if content_type.startswith("image"): size_str = "" - if bigframes.options.experiments.blob_display_width: - size_str = f' width="{bigframes.options.experiments.blob_display_width}"' - if bigframes.options.experiments.blob_display_height: + if bigframes.options.display.blob_display_width: + size_str = f' width="{bigframes.options.display.blob_display_width}"' + if bigframes.options.display.blob_display_height: size_str = ( size_str - + f' height="{bigframes.options.experiments.blob_display_height}"' + + f' height="{bigframes.options.display.blob_display_height}"' ) url = obj_ref_rt_json["access_urls"]["read_url"] return f'' diff --git a/bigframes/ml/llm.py b/bigframes/ml/llm.py index bd414102e1..111ad20f8a 100644 --- a/bigframes/ml/llm.py +++ b/bigframes/ml/llm.py @@ -250,7 +250,10 @@ class MultimodalEmbeddingGenerator(base.RetriableRemotePredictor): """Multimodal embedding generator LLM model. .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. + BigFrames Blob is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the + Service Specific Terms(https://cloud.google.com/terms/service-terms#1). Pre-GA products and features are available "as is" + and might have limited support. For more information, see the launch stage descriptions + (https://cloud.google.com/products#product-launch-stages). Args: model_name (str, Default to "multimodalembedding@001"): @@ -271,8 +274,6 @@ def __init__( session: Optional[bigframes.Session] = None, connection_name: Optional[str] = None, ): - if not bigframes.options.experiments.blob: - raise NotImplementedError() if model_name is None: model_name = "multimodalembedding@001" msg = exceptions.format_message(_REMOVE_DEFAULT_MODEL_WARNING) @@ -610,7 +611,10 @@ def predict( prompt (Iterable of str or bigframes.series.Series, or None, default None): .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. + BigFrames Blob is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the + Service Specific Terms(https://cloud.google.com/terms/service-terms#1). Pre-GA products and features are available "as is" + and might have limited support. For more information, see the launch stage descriptions + (https://cloud.google.com/products#product-launch-stages). Construct a prompt struct column for prediction based on the input. The input must be an Iterable that can take string literals, such as "summarize", string column(s) of X, such as X["str_col"], or blob column(s) of X, such as X["blob_col"]. @@ -646,9 +650,6 @@ def predict( (X,) = utils.batch_convert_to_dataframe(X, session=session) if prompt: - if not bigframes.options.experiments.blob: - raise NotImplementedError() - if self.model_name not in _GEMINI_MULTIMODAL_ENDPOINTS: raise NotImplementedError( f"GeminiTextGenerator only supports model_name {', '.join(_GEMINI_MULTIMODAL_ENDPOINTS)} for Multimodal prompt." diff --git a/bigframes/operations/blob.py b/bigframes/operations/blob.py index 2c6e5fca7f..d211c2b918 100644 --- a/bigframes/operations/blob.py +++ b/bigframes/operations/blob.py @@ -40,21 +40,18 @@ class BlobAccessor(base.SeriesMethods): Blob functions for Series and Index. .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. + BigFrames Blob is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the + Service Specific Terms(https://cloud.google.com/terms/service-terms#1). Pre-GA products and features are available "as is" + and might have limited support. For more information, see the launch stage descriptions + (https://cloud.google.com/products#product-launch-stages). """ def __init__(self, *args, **kwargs): - if not bigframes.options.experiments.blob: - raise NotImplementedError() - super().__init__(*args, **kwargs) def uri(self) -> bigframes.series.Series: """URIs of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: URIs as string.""" s = bigframes.series.Series(self._block) @@ -64,9 +61,6 @@ def uri(self) -> bigframes.series.Series: def authorizer(self) -> bigframes.series.Series: """Authorizers of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: Autorithers(connection) as string.""" s = bigframes.series.Series(self._block) @@ -76,9 +70,6 @@ def authorizer(self) -> bigframes.series.Series: def version(self) -> bigframes.series.Series: """Versions of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: Version as string.""" # version must be retrieved after fetching metadata @@ -87,9 +78,6 @@ def version(self) -> bigframes.series.Series: def metadata(self) -> bigframes.series.Series: """Retrieve the metadata of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: JSON metadata of the Blob. Contains fields: content_type, md5_hash, size and updated(time).""" details_json = self._apply_unary_op(ops.obj_fetch_metadata_op).struct.field( @@ -102,9 +90,6 @@ def metadata(self) -> bigframes.series.Series: def content_type(self) -> bigframes.series.Series: """Retrieve the content type of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: string of the content type.""" return ( @@ -116,9 +101,6 @@ def content_type(self) -> bigframes.series.Series: def md5_hash(self) -> bigframes.series.Series: """Retrieve the md5 hash of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: string of the md5 hash.""" return ( @@ -130,9 +112,6 @@ def md5_hash(self) -> bigframes.series.Series: def size(self) -> bigframes.series.Series: """Retrieve the file size of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: file size in bytes.""" return ( @@ -145,9 +124,6 @@ def size(self) -> bigframes.series.Series: def updated(self) -> bigframes.series.Series: """Retrieve the updated time of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: updated time as UTC datetime.""" import bigframes.pandas as bpd @@ -204,9 +180,6 @@ def _df_apply_udf( def read_url(self) -> bigframes.series.Series: """Retrieve the read URL of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: Read only URLs.""" return self._get_runtime(mode="R")._apply_unary_op( @@ -216,9 +189,6 @@ def read_url(self) -> bigframes.series.Series: def write_url(self) -> bigframes.series.Series: """Retrieve the write URL of the Blob. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Returns: bigframes.series.Series: Writable URLs.""" return self._get_runtime(mode="RW")._apply_unary_op( @@ -235,17 +205,14 @@ def display( ): """Display the blob content in the IPython Notebook environment. Only works for image type now. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Args: n (int, default 3): number of sample blob objects to display. content_type (str, default ""): content type of the blob. If unset, use the blob metadata of the storage. Possible values are "image", "audio" and "video". - width (int or None, default None): width in pixels that the image/video are constrained to. If unset, use the global setting in bigframes.options.experiments.blob_display_width, otherwise image/video's original size or ratio is used. No-op for other content types. - height (int or None, default None): height in pixels that the image/video are constrained to. If unset, use the global setting in bigframes.options.experiments.blob_display_height, otherwise image/video's original size or ratio is used. No-op for other content types. + width (int or None, default None): width in pixels that the image/video are constrained to. If unset, use the global setting in bigframes.options.display.blob_display_width, otherwise image/video's original size or ratio is used. No-op for other content types. + height (int or None, default None): height in pixels that the image/video are constrained to. If unset, use the global setting in bigframes.options.display.blob_display_height, otherwise image/video's original size or ratio is used. No-op for other content types. """ - width = width or bigframes.options.experiments.blob_display_width - height = height or bigframes.options.experiments.blob_display_height + width = width or bigframes.options.display.blob_display_width + height = height or bigframes.options.display.blob_display_height # col name doesn't matter here. Rename to avoid column name conflicts df = bigframes.series.Series(self._block).rename("blob_col").to_frame() @@ -296,10 +263,6 @@ def session(self): def _resolve_connection(self, connection: Optional[str] = None) -> str: """Resovle the BigQuery connection. - .. note:: - BigFrames Blob is still under experiments. It may not work and - subject to change in the future. - Args: connection (str or None, default None): BQ connection used for function internet transactions, and the output blob if "dst" is @@ -324,10 +287,6 @@ def get_runtime_json_str( ) -> bigframes.series.Series: """Get the runtime (contains signed URL to access gcs data) and apply the ToJSONSTring transformation. - .. note:: - BigFrames Blob is still under experiments. It may not work and - subject to change in the future. - Args: mode(str or str, default "R"): the mode for accessing the runtime. Default to "R". Possible values are "R" (read-only) and @@ -353,9 +312,6 @@ def image_blur( ) -> bigframes.series.Series: """Blurs images. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Args: ksize (tuple(int, int)): Kernel size. dst (str or bigframes.series.Series or None, default None): Output destination. Can be one of: @@ -438,9 +394,6 @@ def image_resize( ): """Resize images. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Args: dsize (tuple(int, int), default (0, 0)): Destination size. If set to 0, fx and fy parameters determine the size. fx (float, default 0.0): scale factor along the horizontal axis. If set to 0.0, dsize parameter determines the output size. @@ -534,9 +487,6 @@ def image_normalize( ) -> bigframes.series.Series: """Normalize images. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Args: alpha (float, default 1.0): Norm value to normalize to or the lower range boundary in case of the range normalization. beta (float, default 0.0): Upper range boundary in case of the range normalization; it is not used for the norm normalization. @@ -622,10 +572,6 @@ def pdf_extract( ) -> bigframes.series.Series: """Extracts text from PDF URLs and saves the text as string. - .. note:: - BigFrames Blob is still under experiments. It may not work and - subject to change in the future. - Args: connection (str or None, default None): BQ connection used for function internet transactions, and the output blob if "dst" @@ -688,9 +634,6 @@ def pdf_chunk( """Extracts and chunks text from PDF URLs and saves the text as arrays of strings. - .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. - Args: connection (str or None, default None): BQ connection used for function internet transactions, and the output blob if "dst" diff --git a/bigframes/operations/strings.py b/bigframes/operations/strings.py index 784af8418d..529dd87797 100644 --- a/bigframes/operations/strings.py +++ b/bigframes/operations/strings.py @@ -288,7 +288,10 @@ def to_blob(self, connection: Optional[str] = None) -> series.Series: """Create a BigFrames Blob series from a series of URIs. .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. + BigFrames Blob is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the + Service Specific Terms(https://cloud.google.com/terms/service-terms#1). Pre-GA products and features are available "as is" + and might have limited support. For more information, see the launch stage descriptions + (https://cloud.google.com/products#product-launch-stages). Args: @@ -301,9 +304,6 @@ def to_blob(self, connection: Optional[str] = None) -> series.Series: bigframes.series.Series: Blob Series. """ - if not bigframes.options.experiments.blob: - raise NotImplementedError() - session = self._block.session connection = session._create_bq_connection(connection=connection) return self._apply_binary_op(connection, ops.obj_make_ref_op) diff --git a/bigframes/session/__init__.py b/bigframes/session/__init__.py index 998e6e57bc..1081270c76 100644 --- a/bigframes/session/__init__.py +++ b/bigframes/session/__init__.py @@ -1905,7 +1905,10 @@ def from_glob_path( If you have an existing BQ Object Table, use read_gbq_object_table(). .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. + BigFrames Blob is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the + Service Specific Terms(https://cloud.google.com/terms/service-terms#1). Pre-GA products and features are available "as is" + and might have limited support. For more information, see the launch stage descriptions + (https://cloud.google.com/products#product-launch-stages). Args: path (str): @@ -1920,9 +1923,6 @@ def from_glob_path( bigframes.pandas.DataFrame: Result BigFrames DataFrame. """ - if not bigframes.options.experiments.blob: - raise NotImplementedError() - # TODO(garrettwu): switch to pseudocolumn when b/374988109 is done. connection = self._create_bq_connection(connection=connection) @@ -1966,7 +1966,10 @@ def read_gbq_object_table( This function dosen't retrieve the object table data. If you want to read the data, use read_gbq() instead. .. note:: - BigFrames Blob is still under experiments. It may not work and subject to change in the future. + BigFrames Blob is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the + Service Specific Terms(https://cloud.google.com/terms/service-terms#1). Pre-GA products and features are available "as is" + and might have limited support. For more information, see the launch stage descriptions + (https://cloud.google.com/products#product-launch-stages). Args: object_table (str): name of the object table of form ... @@ -1976,9 +1979,6 @@ def read_gbq_object_table( bigframes.pandas.DataFrame: Result BigFrames DataFrame. """ - if not bigframes.options.experiments.blob: - raise NotImplementedError() - # TODO(garrettwu): switch to pseudocolumn when b/374988109 is done. table = self.bqclient.get_table(object_table) connection = table._properties["externalDataConfiguration"]["connectionId"] diff --git a/notebooks/experimental/multimodal_dataframe.ipynb b/notebooks/experimental/multimodal_dataframe.ipynb index 9c76654a53..4a0cd57a45 100644 --- a/notebooks/experimental/multimodal_dataframe.ipynb +++ b/notebooks/experimental/multimodal_dataframe.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -82,17 +82,7 @@ "id": "bGyhLnfEeB0X", "outputId": "83ac8b64-3f44-4d43-d089-28a5026cbb42" }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/google/home/garrettwu/src/bigframes/bigframes/_config/experiment_options.py:68: PreviewWarning: BigFrames Blob is still under experiments. It may not work and subject\n", - "to change in the future.\n", - " warnings.warn(msg, category=bfe.PreviewWarning)\n" - ] - } - ], + "outputs": [], "source": [ "PROJECT = \"bigframes-dev\" # replace with your project, project needs to be allowlisted go/bq-multimodal-allowlist (internal)\n", "# User must have https://cloud.google.com/bigquery/docs/use-bigquery-dataframes#permissions to use bigframes, BQ connection admin/user to create/use connections, BQ ObjRef permissions for ObjectRef and BQ routines permissions for using transform functions.\n", @@ -101,9 +91,9 @@ "import bigframes\n", "# Setup project\n", "bigframes.options.bigquery.project = PROJECT\n", - "# Flag to enable the feature\n", - "bigframes.options.experiments.blob = True\n", "\n", + "# Display options\n", + "bigframes.options.display.blob_display_width = 300\n", "bigframes.options.display.progress_bar = None\n", "\n", "import bigframes.pandas as bpd" @@ -121,7 +111,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -154,7 +144,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -191,23 +181,23 @@ " \n", " \n", " 0\n", - " \n", + " \n", " \n", " \n", " 1\n", - " \n", + " \n", " \n", " \n", " 2\n", - " \n", + " \n", " \n", " \n", " 3\n", - " \n", + " \n", " \n", " \n", " 4\n", - " \n", + " \n", " \n", " \n", "\n", @@ -225,7 +215,7 @@ "[5 rows x 1 columns]" ] }, - "execution_count": 3, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -256,7 +246,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": { "id": "YYYVn7NDH0Me" }, @@ -292,43 +282,43 @@ " \n", " \n", " 0\n", - " \n", + " \n", " alice\n", " image/png\n", - " 1489405\n", - " 2025-03-20 17:44:58+00:00\n", + " 1591240\n", + " 2025-03-20 17:45:04+00:00\n", " \n", " \n", " 1\n", - " \n", + " \n", " bob\n", " image/png\n", - " 1538007\n", - " 2025-03-20 17:44:56+00:00\n", + " 1182951\n", + " 2025-03-20 17:45:02+00:00\n", " \n", " \n", " 2\n", - " \n", + " \n", " bob\n", " image/png\n", - " 1237551\n", - " 2025-03-20 17:45:14+00:00\n", + " 1520884\n", + " 2025-03-20 17:44:55+00:00\n", " \n", " \n", " 3\n", - " \n", + " \n", " alice\n", " image/png\n", - " 1040455\n", - " 2025-03-20 17:44:45+00:00\n", + " 1235401\n", + " 2025-03-20 17:45:19+00:00\n", " \n", " \n", " 4\n", - " \n", + " \n", " bob\n", " image/png\n", - " 1517938\n", - " 2025-03-20 17:45:05+00:00\n", + " 1591923\n", + " 2025-03-20 17:44:47+00:00\n", " \n", " \n", "\n", @@ -344,16 +334,16 @@ "4 {'uri': 'gs://cloud-samples-data/bigquery/tuto... bob image/png \n", "\n", " size updated \n", - "0 1489405 2025-03-20 17:44:58+00:00 \n", - "1 1538007 2025-03-20 17:44:56+00:00 \n", - "2 1237551 2025-03-20 17:45:14+00:00 \n", - "3 1040455 2025-03-20 17:44:45+00:00 \n", - "4 1517938 2025-03-20 17:45:05+00:00 \n", + "0 1591240 2025-03-20 17:45:04+00:00 \n", + "1 1182951 2025-03-20 17:45:02+00:00 \n", + "2 1520884 2025-03-20 17:44:55+00:00 \n", + "3 1235401 2025-03-20 17:45:19+00:00 \n", + "4 1591923 2025-03-20 17:44:47+00:00 \n", "\n", "[5 rows x 5 columns]" ] }, - "execution_count": 4, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -378,7 +368,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -391,7 +381,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -403,7 +393,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -430,7 +420,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -469,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -494,7 +484,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -539,63 +529,63 @@ " \n", " \n", " 0\n", - " \n", + " \n", " alice\n", " image/png\n", - " 1489405\n", - " 2025-03-20 17:44:58+00:00\n", - " \n", - " \n", - " \n", - " \n", + " 1591240\n", + " 2025-03-20 17:45:04+00:00\n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " 1\n", - " \n", + " \n", " bob\n", " image/png\n", - " 1538007\n", - " 2025-03-20 17:44:56+00:00\n", - " \n", - " \n", - " \n", - " \n", + " 1182951\n", + " 2025-03-20 17:45:02+00:00\n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " 2\n", - " \n", + " \n", " bob\n", " image/png\n", - " 1237551\n", - " 2025-03-20 17:45:14+00:00\n", - " \n", - " \n", - " \n", - " \n", + " 1520884\n", + " 2025-03-20 17:44:55+00:00\n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " 3\n", - " \n", + " \n", " alice\n", " image/png\n", - " 1040455\n", - " 2025-03-20 17:44:45+00:00\n", - " \n", - " \n", - " \n", - " \n", + " 1235401\n", + " 2025-03-20 17:45:19+00:00\n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " 4\n", - " \n", + " \n", " bob\n", " image/png\n", - " 1517938\n", - " 2025-03-20 17:45:05+00:00\n", - " \n", - " \n", - " \n", - " \n", + " 1591923\n", + " 2025-03-20 17:44:47+00:00\n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "\n", @@ -611,11 +601,11 @@ "4 {'uri': 'gs://cloud-samples-data/bigquery/tuto... bob image/png \n", "\n", " size updated \\\n", - "0 1489405 2025-03-20 17:44:58+00:00 \n", - "1 1538007 2025-03-20 17:44:56+00:00 \n", - "2 1237551 2025-03-20 17:45:14+00:00 \n", - "3 1040455 2025-03-20 17:44:45+00:00 \n", - "4 1517938 2025-03-20 17:45:05+00:00 \n", + "0 1591240 2025-03-20 17:45:04+00:00 \n", + "1 1182951 2025-03-20 17:45:02+00:00 \n", + "2 1520884 2025-03-20 17:44:55+00:00 \n", + "3 1235401 2025-03-20 17:45:19+00:00 \n", + "4 1591923 2025-03-20 17:44:47+00:00 \n", "\n", " blurred \\\n", "0 {'uri': 'gs://bigframes_blob_test/image_blur_t... \n", @@ -648,7 +638,7 @@ "[5 rows x 9 columns]" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -668,7 +658,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": { "id": "mRUGfcaFVW-3" }, @@ -680,7 +670,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -694,7 +684,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/array_value.py:107: PreviewWarning: JSON column interpretation as a custom PyArrow extention in\n", + "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/array_value.py:109: PreviewWarning: JSON column interpretation as a custom PyArrow extention in\n", "`db_dtypes` is a preview feature and subject to change.\n", " warnings.warn(msg, bfe.PreviewWarning)\n" ] @@ -727,13 +717,13 @@ " \n", " \n", " 0\n", - " That's a bag of **rabbit food** from the brand **Fluffy Buns**. The specific product is labeled as \"Ranbhow's trood.flee!\" (which appears to be a playful brand name).\n", - " \n", + " That's a tin of **K9Guard Dog Paw Balm**.\n", + " \n", " \n", " \n", " 1\n", - " That's hay. More specifically, it looks like a type of grass hay, often used as feed for small animals like rabbits, guinea pigs, and chinchillas.\n", - " \n", + " That's a bottle of **K9 Guard Dog Hot Spot Spray**. It's a pet product designed to soothe and protect dogs' hot spots (irritated areas of skin).\n", + " \n", " \n", " \n", "\n", @@ -742,8 +732,9 @@ ], "text/plain": [ " ml_generate_text_llm_result \\\n", - "0 That's a bag of **rabbit food** from the brand... \n", - "1 That's hay. More specifically, it looks like ... \n", + "0 That's a tin of **K9Guard Dog Paw Balm**.\n", + " \n", + "1 That's a bottle of **K9 Guard Dog Hot Spot Spr... \n", "\n", " image \n", "0 {'uri': 'gs://cloud-samples-data/bigquery/tuto... \n", @@ -752,7 +743,7 @@ "[2 rows x 2 columns]" ] }, - "execution_count": 10, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -766,7 +757,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "metadata": { "id": "IG3J3HsKhyBY" }, @@ -778,7 +769,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -792,7 +783,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/array_value.py:107: PreviewWarning: JSON column interpretation as a custom PyArrow extention in\n", + "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/array_value.py:109: PreviewWarning: JSON column interpretation as a custom PyArrow extention in\n", "`db_dtypes` is a preview feature and subject to change.\n", " warnings.warn(msg, bfe.PreviewWarning)\n" ] @@ -825,13 +816,13 @@ " \n", " \n", " 0\n", - " That's a bag of **Fluffy Buns Rabbit Food**. It's a blend of various ingredients designed as food for rabbits.\n", - " \n", + " That's a tin of **K9Guard Dog Paw Balm**. It's a balm designed to protect and care for a dog's paws.\n", + " \n", " \n", " \n", " 1\n", - " The picture is primarily light green. There are some slightly darker green and yellowish-green shades mixed in, but the overall color is light green.\n", - " \n", + " The background of the picture is light gray. The bottle is predominantly white with teal/light blue accents on the spray nozzle and text. There is a small image of an aloe vera plant on the label.\n", + " \n", " \n", " \n", "\n", @@ -840,8 +831,8 @@ ], "text/plain": [ " ml_generate_text_llm_result \\\n", - "0 That's a bag of **Fluffy Buns Rabbit Food**. ... \n", - "1 The picture is primarily light green. There a... \n", + "0 That's a tin of **K9Guard Dog Paw Balm**. It'... \n", + "1 The background of the picture is light gray. ... \n", "\n", " image \n", "0 {'uri': 'gs://cloud-samples-data/bigquery/tuto... \n", @@ -850,7 +841,7 @@ "[2 rows x 2 columns]" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -862,7 +853,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -876,7 +867,11 @@ "name": "stderr", "output_type": "stream", "text": [ - "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/array_value.py:107: PreviewWarning: JSON column interpretation as a custom PyArrow extention in\n", + "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/log_adapter.py:164: FutureWarning: Since upgrading the default model can cause unintended breakages, the\n", + "default model will be removed in BigFrames 3.0. Please supply an\n", + "explicit model to avoid this message.\n", + " return method(self, *args, **kwargs)\n", + "/usr/local/google/home/garrettwu/src/bigframes/bigframes/core/array_value.py:109: PreviewWarning: JSON column interpretation as a custom PyArrow extention in\n", "`db_dtypes` is a preview feature and subject to change.\n", " warnings.warn(msg, bfe.PreviewWarning)\n" ] @@ -912,21 +907,21 @@ " \n", " \n", " 0\n", - " [ 0.01182145 0.01575819 0.06243018 ... 0.00010706 -0.03063935\n", - " -0.05756916]\n", + " [ 0.00638822 0.01666385 0.00451817 ... -0.02684802 -0.00475593\n", + " -0.01989058]\n", " \n", " \n", " \n", - " {\"access_urls\":{\"expiry_time\":\"2025-04-09T02:36:17Z\",\"read_url\":\"https://storage.googleapis.com/cloud-samples-data/bigquery%2Ftutorials%2Fcymbal-pets%2Fimages%2Ffluffy-buns-rabbit-food.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=bqcx-1084210331973-pcbl%40gcp-sa-bigquery-condel.iam.gserviceaccount.com%2F20250408%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20250408T203617Z&X-Goog-Expires=21600&X-Goog-SignedHeaders=host&generation=1742492698095241&X-Goog-Signature=860fb5fbf48778f66f0ec2d141b26dd7ce2de7cacc427491f5cc3f420361770e33936c79552a562a3db31c8e02a9ea73e73ac9c7c379dfa0e213eda456c48243acea3227c3e9e786859b19e2b74718d7c3447f09ba371d77e3df65a9e2936c9b9ad5ad7ba359bfaa9fc3a2785d32359a9d50ee64f90f6e7d3a20a5c13f38f932c83b143dd2abdd31f0b35ab60aa21293d2cbf7ea780b13ef02d6b1f9aa56538a498d3da13798a1cbe2535b118caeb35f1e5be36d09c9593796b5ecf8b171d4915735644a94d19d7e78351e475da7b75f72fc8f88b2607ce8d1fb53d7dc2aa16da3b6ed2130fd700cbc797d1a6cc495833945b3bdfaf933b9a4dc70ff3299ab4f\",\"write_url\":\"\"},\"objectref\":{\"authorizer\":\"bigframes-dev.us.bigframes-default-connection\",\"details\":{\"gcs_metadata\":{\"content_type\":\"image/png\",\"md5_hash\":\"4c01d79182ea7580183a2168076e16b8\",\"size\":1489405,\"updated\":1742492698000000}},\"uri\":\"gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/fluffy-buns-rabbit-food.png\",\"version\":\"1742492698095241\"}}\n", + " {\"access_urls\":{\"expiry_time\":\"2025-05-06T06:14:15Z\",\"read_url\":\"https://storage.googleapis.com/cloud-samples-data/bigquery%2Ftutorials%2Fcymbal-pets%2Fimages%2Fk9-guard-dog-paw-balm.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=bqcx-1084210331973-pcbl%40gcp-sa-bigquery-condel.iam.gserviceaccount.com%2F20250506%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20250506T001415Z&X-Goog-Expires=21600&X-Goog-SignedHeaders=host&generation=1742492703986347&X-Goog-Signature=4ff6735f3e2d1b9aede89b881884c8413f7b5fde1c9c65b140de7eed1bdaca3609cd77e5dfb81e83fbc77adf20dbbec687ab0dd3f9fadd7ffd9961b1eecf14464d8257ab71dc509859eda505877a16a6b97a34bdce2a36b93da14ffb9e4de5b6c60b8c49e249efa56cfa144c5855d92fb67ee8a09f753d9889ff69c8bef70f01224bcfdda66341bd8cd7d56cc4fdc2a5618d1cebc654077890afa5329c05bb8accf440802ad3aeaa624f23725f7e9bec9270d4379c30f7dd4c4ca99752103396f87872e9484fe3efcd6514754d85d825d56bed140e49a15985bee0274fc6d4f5eceecc762144d451454896b5fcda4cade198c2b7bf07e5186556a393b3b85264\",\"write_url\":\"\"},\"objectref\":{\"authorizer\":\"bigframes-dev.us.bigframes-default-connection\",\"details\":{\"gcs_metadata\":{\"content_type\":\"image/png\",\"md5_hash\":\"c46ac29292d8ba244101dcada3ea86d5\",\"size\":1591240,\"updated\":1742492704000000}},\"uri\":\"gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/k9-guard-dog-paw-balm.png\",\"version\":\"1742492703986347\"}}\n", " \n", " \n", " 1\n", - " [ 0.02554693 0.01508185 0.04101892 ... -0.02417112 -0.01356636\n", - " -0.01999673]\n", + " [ 0.00973672 0.02148364 0.00244308 ... 0.00462242 0.0131027\n", + " -0.00038765]\n", " \n", " \n", " \n", - " {\"access_urls\":{\"expiry_time\":\"2025-04-09T02:36:17Z\",\"read_url\":\"https://storage.googleapis.com/cloud-samples-data/bigquery%2Ftutorials%2Fcymbal-pets%2Fimages%2Ffluffy-buns-guinea-pig-hay.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=bqcx-1084210331973-pcbl%40gcp-sa-bigquery-condel.iam.gserviceaccount.com%2F20250408%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20250408T203617Z&X-Goog-Expires=21600&X-Goog-SignedHeaders=host&generation=1742492696656039&X-Goog-Signature=192e852a5296d31a048af459afe3dc539e2bbf90c65bc2997219e7822bd0ca2858b8e04475e12d14d63d295b45e51403b4f4585a6b66c8b0dbc3adf19e135a93687aeff7ba675eec2aeddb4a1cb4d2b83bee22c7c2de80287af63158a85ee56fa1daccbf31bf42d57e5724ea24bdd630a8a1930d70a5d38fb0340d846848039f53bf4efbc21da6df9a7d91fec727385018b159e4fc53fce0b57ab0c77583361bc4e10b2a7080aafa288789240e565eb58cb9abf2bd298732fddaad4f32472110b2607f6b3a21d9fbce1fc3ecb23caf967a4e3ff5101ae29fc6c65b888930a1306c8deb3b569997a0a364325b3ac0350ff671f2682d9a8a4a96bfac28eb9f9fd8\",\"write_url\":\"\"},\"objectref\":{\"authorizer\":\"bigframes-dev.us.bigframes-default-connection\",\"details\":{\"gcs_metadata\":{\"content_type\":\"image/png\",\"md5_hash\":\"0888367a63729f5a42f4a041596f635d\",\"size\":1538007,\"updated\":1742492696000000}},\"uri\":\"gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/fluffy-buns-guinea-pig-hay.png\",\"version\":\"1742492696656039\"}}\n", + " {\"access_urls\":{\"expiry_time\":\"2025-05-06T06:14:15Z\",\"read_url\":\"https://storage.googleapis.com/cloud-samples-data/bigquery%2Ftutorials%2Fcymbal-pets%2Fimages%2Fk9-guard-dog-hot-spot-spray.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=bqcx-1084210331973-pcbl%40gcp-sa-bigquery-condel.iam.gserviceaccount.com%2F20250506%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20250506T001415Z&X-Goog-Expires=21600&X-Goog-SignedHeaders=host&generation=1742492702954473&X-Goog-Signature=4adc1cf96fe21f385782ea26d52faf9093995b334f592ab0b3a791dc47402b5626c82b9c31c3ecd553d6ccf16012d42c0f7dd8e07b641c60515e43e33bc64da60082763f1567bc9ff2f37a19d3e33cf2a87a9872512b9400265b42092c8070254d842a26cc28d0332b86d0bc052a71ea4bd85d026604f81235d9ee367852e912ad5b5ea405023f92c269586a8fa417b1b7ffe8026086f1d9aaf893635334715568025d0f1d7a2108b33cde9a9012e0684763a6b1743e8decbf7bc9e9f582c7f72bcc2bf31254253ef3c21cb2d10c4c1580e98729eb0611edaea2690bf4b4884449a44851fb0f788a7692dc94bf4fe3c2e287566b6b92e4cc880870adfc4093c4\",\"write_url\":\"\"},\"objectref\":{\"authorizer\":\"bigframes-dev.us.bigframes-default-connection\",\"details\":{\"gcs_metadata\":{\"content_type\":\"image/png\",\"md5_hash\":\"ae802a64dfaeaf556609429fcbe02542\",\"size\":1182951,\"updated\":1742492702000000}},\"uri\":\"gs://cloud-samples-data/bigquery/tutorials/cymbal-pets/images/k9-guard-dog-hot-spot-spray.png\",\"version\":\"1742492702954473\"}}\n", " \n", " \n", "\n", @@ -935,8 +930,8 @@ ], "text/plain": [ " ml_generate_embedding_result \\\n", - "0 [ 0.01182145 0.01575819 0.06243018 ... 0.00... \n", - "1 [ 0.02554693 0.01508185 0.04101892 ... -0.02... \n", + "0 [ 0.00638822 0.01666385 0.00451817 ... -0.02... \n", + "1 [ 0.00973672 0.02148364 0.00244308 ... 0.00... \n", "\n", " ml_generate_embedding_status ml_generate_embedding_start_sec \\\n", "0 \n", @@ -947,13 +942,13 @@ "1 \n", "\n", " content \n", - "0 {\"access_urls\":{\"expiry_time\":\"2025-04-09T02:3... \n", - "1 {\"access_urls\":{\"expiry_time\":\"2025-04-09T02:3... \n", + "0 {\"access_urls\":{\"expiry_time\":\"2025-05-06T06:1... \n", + "1 {\"access_urls\":{\"expiry_time\":\"2025-05-06T06:1... \n", "\n", "[2 rows x 5 columns]" ] }, - "execution_count": 13, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -976,7 +971,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": { "id": "oDDuYtUm5Yiy" }, @@ -987,7 +982,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -1011,7 +1006,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "metadata": { "id": "kaPvJATN7zlw" }, @@ -1034,7 +1029,7 @@ "Name: chunked, dtype: string" ] }, - "execution_count": 16, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } diff --git a/samples/snippets/multimodal_test.py b/samples/snippets/multimodal_test.py index dc326b266e..fc3d60e12e 100644 --- a/samples/snippets/multimodal_test.py +++ b/samples/snippets/multimodal_test.py @@ -19,8 +19,6 @@ def test_multimodal_dataframe(gcs_dst_bucket: str) -> None: # [START bigquery_dataframes_multimodal_dataframe_create] import bigframes - # Flag to enable the feature - bigframes.options.experiments.blob = True # Flags to control preview image/video preview size bigframes.options.experiments.blob_display_width = 300 diff --git a/tests/system/conftest.py b/tests/system/conftest.py index 19f2a79b65..458e8e0ad2 100644 --- a/tests/system/conftest.py +++ b/tests/system/conftest.py @@ -1500,8 +1500,6 @@ def images_uris() -> list[str]: def images_mm_df( images_uris, test_session: bigframes.Session, bq_connection: str ) -> bpd.DataFrame: - bigframes.options.experiments.blob = True - blob_series = bpd.Series(images_uris, session=test_session).str.to_blob( connection=bq_connection ) @@ -1526,8 +1524,6 @@ def pdf_gcs_path() -> str: def pdf_mm_df( pdf_gcs_path, test_session: bigframes.Session, bq_connection: str ) -> bpd.DataFrame: - bigframes.options.experiments.blob = True - return test_session.from_glob_path( pdf_gcs_path, name="pdf", connection=bq_connection ) diff --git a/tests/system/large/blob/test_function.py b/tests/system/large/blob/test_function.py index a2c3f2b85f..5913df8add 100644 --- a/tests/system/large/blob/test_function.py +++ b/tests/system/large/blob/test_function.py @@ -57,8 +57,6 @@ def test_blob_image_blur_to_series( images_output_uris: list[str], test_session: bigframes.Session, ): - bigframes.options.experiments.blob = True - series = bpd.Series(images_output_uris, session=test_session).str.to_blob( connection=bq_connection ) @@ -91,8 +89,6 @@ def test_blob_image_blur_to_folder( images_output_folder: str, images_output_uris: list[str], ): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.image_blur( (8, 8), dst=images_output_folder, connection=bq_connection ) @@ -116,8 +112,6 @@ def test_blob_image_blur_to_folder( def test_blob_image_blur_to_bq(images_mm_df: bpd.DataFrame, bq_connection: str): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.image_blur((8, 8), connection=bq_connection) assert isinstance(actual, bpd.Series) @@ -131,8 +125,6 @@ def test_blob_image_resize_to_series( images_output_uris: list[str], test_session: bigframes.Session, ): - bigframes.options.experiments.blob = True - series = bpd.Series(images_output_uris, session=test_session).str.to_blob( connection=bq_connection ) @@ -165,8 +157,6 @@ def test_blob_image_resize_to_folder( images_output_folder: str, images_output_uris: list[str], ): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.image_resize( (200, 300), dst=images_output_folder, connection=bq_connection ) @@ -190,8 +180,6 @@ def test_blob_image_resize_to_folder( def test_blob_image_resize_to_bq(images_mm_df: bpd.DataFrame, bq_connection: str): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.image_resize( (200, 300), connection=bq_connection ) @@ -207,8 +195,6 @@ def test_blob_image_normalize_to_series( images_output_uris: list[str], test_session: bigframes.Session, ): - bigframes.options.experiments.blob = True - series = bpd.Series(images_output_uris, session=test_session).str.to_blob( connection=bq_connection ) @@ -241,8 +227,6 @@ def test_blob_image_normalize_to_folder( images_output_folder: str, images_output_uris: list[str], ): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.image_normalize( alpha=50.0, beta=150.0, @@ -270,8 +254,6 @@ def test_blob_image_normalize_to_folder( def test_blob_image_normalize_to_bq(images_mm_df: bpd.DataFrame, bq_connection: str): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.image_normalize( alpha=50.0, beta=150.0, norm_type="minmax", connection=bq_connection ) @@ -314,8 +296,6 @@ def test_blob_pdf_extract( bq_connection: str, expected: pd.Series, ): - bigframes.options.experiments.blob = True - actual = ( pdf_mm_df["pdf"] .blob.pdf_extract(connection=bq_connection, verbose=verbose) @@ -366,8 +346,6 @@ def test_blob_pdf_extract( def test_blob_pdf_chunk( pdf_mm_df: bpd.DataFrame, verbose: bool, bq_connection: str, expected: pd.Series ): - bigframes.options.experiments.blob = True - actual = ( pdf_mm_df["pdf"] .blob.pdf_chunk( diff --git a/tests/system/small/blob/test_io.py b/tests/system/small/blob/test_io.py index c496e5d631..806dad71dc 100644 --- a/tests/system/small/blob/test_io.py +++ b/tests/system/small/blob/test_io.py @@ -21,8 +21,6 @@ def test_blob_create_from_uri_str( bq_connection: str, test_session: bigframes.Session, images_uris ): - bigframes.options.experiments.blob = True - uri_series = bpd.Series(images_uris, session=test_session) blob_series = uri_series.str.to_blob(connection=bq_connection) @@ -44,8 +42,6 @@ def test_blob_create_from_uri_str( def test_blob_create_from_glob_path( bq_connection: str, test_session: bigframes.Session, images_gcs_path, images_uris ): - bigframes.options.experiments.blob = True - blob_df = test_session.from_glob_path( images_gcs_path, connection=bq_connection, name="blob_col" ) @@ -74,8 +70,6 @@ def test_blob_create_from_glob_path( def test_blob_create_read_gbq_object_table( bq_connection: str, test_session: bigframes.Session, images_gcs_path, images_uris ): - bigframes.options.experiments.blob = True - obj_table = test_session._create_object_table(images_gcs_path, bq_connection) blob_df = test_session.read_gbq_object_table(obj_table, name="blob_col") diff --git a/tests/system/small/blob/test_properties.py b/tests/system/small/blob/test_properties.py index 767dbe37b7..f6a0c87f24 100644 --- a/tests/system/small/blob/test_properties.py +++ b/tests/system/small/blob/test_properties.py @@ -14,14 +14,11 @@ import pandas as pd -import bigframes import bigframes.dtypes as dtypes import bigframes.pandas as bpd def test_blob_uri(images_uris: list[str], images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.uri().to_pandas() expected = pd.Series(images_uris, name="uri") @@ -31,8 +28,6 @@ def test_blob_uri(images_uris: list[str], images_mm_df: bpd.DataFrame): def test_blob_authorizer(images_mm_df: bpd.DataFrame, bq_connection: str): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.authorizer().to_pandas() expected = pd.Series( [bq_connection.casefold(), bq_connection.casefold()], name="authorizer" @@ -44,8 +39,6 @@ def test_blob_authorizer(images_mm_df: bpd.DataFrame, bq_connection: str): def test_blob_version(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.version().to_pandas() expected = pd.Series(["1739574332294150", "1739574332271343"], name="version") @@ -55,33 +48,30 @@ def test_blob_version(images_mm_df: bpd.DataFrame): def test_blob_metadata(images_mm_df: bpd.DataFrame): - with bigframes.option_context("experiments.blob", True): - actual = images_mm_df["blob_col"].blob.metadata().to_pandas() - expected = pd.Series( - [ - ( - '{"content_type":"image/jpeg",' - '"md5_hash":"e130ad042261a1883cd2cc06831cf748",' - '"size":338390,' - '"updated":1739574332000000}' - ), - ( - '{"content_type":"image/jpeg",' - '"md5_hash":"e2ae3191ff2b809fd0935f01a537c650",' - '"size":43333,' - '"updated":1739574332000000}' - ), - ], - name="metadata", - dtype=dtypes.JSON_DTYPE, - ) - expected.index = expected.index.astype(dtypes.INT_DTYPE) - pd.testing.assert_series_equal(actual, expected) + actual = images_mm_df["blob_col"].blob.metadata().to_pandas() + expected = pd.Series( + [ + ( + '{"content_type":"image/jpeg",' + '"md5_hash":"e130ad042261a1883cd2cc06831cf748",' + '"size":338390,' + '"updated":1739574332000000}' + ), + ( + '{"content_type":"image/jpeg",' + '"md5_hash":"e2ae3191ff2b809fd0935f01a537c650",' + '"size":43333,' + '"updated":1739574332000000}' + ), + ], + name="metadata", + dtype=dtypes.JSON_DTYPE, + ) + expected.index = expected.index.astype(dtypes.INT_DTYPE) + pd.testing.assert_series_equal(actual, expected) def test_blob_content_type(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.content_type().to_pandas() expected = pd.Series(["image/jpeg", "image/jpeg"], name="content_type") @@ -91,8 +81,6 @@ def test_blob_content_type(images_mm_df: bpd.DataFrame): def test_blob_md5_hash(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.md5_hash().to_pandas() expected = pd.Series( ["e130ad042261a1883cd2cc06831cf748", "e2ae3191ff2b809fd0935f01a537c650"], @@ -105,8 +93,6 @@ def test_blob_md5_hash(images_mm_df: bpd.DataFrame): def test_blob_size(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.size().to_pandas() expected = pd.Series([338390, 43333], name="size") @@ -116,8 +102,6 @@ def test_blob_size(images_mm_df: bpd.DataFrame): def test_blob_updated(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - actual = images_mm_df["blob_col"].blob.updated().to_pandas() expected = pd.Series( [ diff --git a/tests/system/small/blob/test_urls.py b/tests/system/small/blob/test_urls.py index da972348f2..02a76587f5 100644 --- a/tests/system/small/blob/test_urls.py +++ b/tests/system/small/blob/test_urls.py @@ -12,21 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import bigframes import bigframes.pandas as bpd def test_blob_read_url(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - urls = images_mm_df["blob_col"].blob.read_url() assert urls.str.startswith("https://storage.googleapis.com/").all() def test_blob_write_url(images_mm_df: bpd.DataFrame): - bigframes.options.experiments.blob = True - urls = images_mm_df["blob_col"].blob.write_url() assert urls.str.startswith("https://storage.googleapis.com/").all() diff --git a/tests/system/small/ml/test_llm.py b/tests/system/small/ml/test_llm.py index a74642aea3..84698f7821 100644 --- a/tests/system/small/ml/test_llm.py +++ b/tests/system/small/ml/test_llm.py @@ -19,7 +19,6 @@ import pyarrow as pa import pytest -import bigframes from bigframes import exceptions from bigframes.ml import core, llm import bigframes.pandas as bpd @@ -92,8 +91,6 @@ def test_text_embedding_generator_multi_cols_predict_success( def test_create_load_multimodal_embedding_generator_model( dataset_id, session, bq_connection ): - bigframes.options.experiments.blob = True - mm_embedding_model = llm.MultimodalEmbeddingGenerator( connection_name=bq_connection, session=session ) @@ -840,6 +837,5 @@ def test_gemini_preview_model_warnings(model_name): ) def test_text_embedding_generator_no_default_model_warning(model_class): message = "Since upgrading the default model can cause unintended breakages, the\ndefault model will be removed in BigFrames 3.0. Please supply an\nexplicit model to avoid this message." - bigframes.options.experiments.blob = True with pytest.warns(FutureWarning, match=message): model_class(model_name=None) diff --git a/tests/system/small/ml/test_multimodal_llm.py b/tests/system/small/ml/test_multimodal_llm.py index efeadc76cf..5e70a98e07 100644 --- a/tests/system/small/ml/test_multimodal_llm.py +++ b/tests/system/small/ml/test_multimodal_llm.py @@ -16,7 +16,6 @@ import pyarrow as pa import pytest -import bigframes from bigframes.ml import llm import bigframes.pandas as bpd from tests.system import utils @@ -26,8 +25,6 @@ def test_multimodal_embedding_generator_predict_default_params_success( images_mm_df, test_session, bq_connection ): - bigframes.options.experiments.blob = True - text_embedding_model = llm.MultimodalEmbeddingGenerator( connection_name=bq_connection, session=test_session ) @@ -56,8 +53,6 @@ def test_multimodal_embedding_generator_predict_default_params_success( def test_gemini_text_generator_multimodal_input( images_mm_df: bpd.DataFrame, model_name, test_session, bq_connection ): - bigframes.options.experiments.blob = True - gemini_text_generator_model = llm.GeminiTextGenerator( model_name=model_name, connection_name=bq_connection, session=test_session ) @@ -87,8 +82,6 @@ def test_gemini_text_generator_multimodal_input( def test_gemini_text_generator_multimodal_structured_output( images_mm_df: bpd.DataFrame, model_name, test_session, bq_connection ): - bigframes.options.experiments.blob = True - gemini_text_generator_model = llm.GeminiTextGenerator( model_name=model_name, connection_name=bq_connection, session=test_session ) diff --git a/tests/unit/_config/test_experiment_options.py b/tests/unit/_config/test_experiment_options.py index 1e5a8326f7..deeee2e46a 100644 --- a/tests/unit/_config/test_experiment_options.py +++ b/tests/unit/_config/test_experiment_options.py @@ -46,18 +46,3 @@ def test_ai_operators_set_true_shows_warning(): options.ai_operators = True assert options.ai_operators is True - - -def test_blob_default_false(): - options = experiment_options.ExperimentOptions() - - assert options.blob is False - - -def test_blob_set_true_shows_warning(): - options = experiment_options.ExperimentOptions() - - with pytest.warns(bfe.PreviewWarning): - options.blob = True - - assert options.blob is True diff --git a/third_party/bigframes_vendored/pandas/core/config_init.py b/third_party/bigframes_vendored/pandas/core/config_init.py index 4bca3f3c75..51d056a2c8 100644 --- a/third_party/bigframes_vendored/pandas/core/config_init.py +++ b/third_party/bigframes_vendored/pandas/core/config_init.py @@ -84,6 +84,12 @@ memory_usage (bool): This specifies if the memory usage of a DataFrame should be displayed when df.info() is called. Valid values True,False, + blob_display (bool): + Whether to display the blob content in notebook DataFrame preview. Default True. + blob_display_width (int or None): + Width in pixels that the blob constrained to. + blob_display_height (int or None): + Height in pixels that the blob constrained to. """ sampling_options_doc = """