diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh index 002d6cbbc7..febfc20cac 100755 --- a/.kokoro/test-samples-impl.sh +++ b/.kokoro/test-samples-impl.sh @@ -34,7 +34,7 @@ env | grep KOKORO # Install nox # `virtualenv==20.26.6` is added for Python 3.7 compatibility -python3 -m pip install --upgrade --quiet nox uv virtualenv==20.26.6 +python3 -m pip install --upgrade --quiet nox virtualenv==20.26.6 # Use secrets acessor service account to get secrets if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then diff --git a/google/cloud/aiplatform_v1/__init__.py b/google/cloud/aiplatform_v1/__init__.py index 830c766633..2c1d8517ee 100644 --- a/google/cloud/aiplatform_v1/__init__.py +++ b/google/cloud/aiplatform_v1/__init__.py @@ -123,15 +123,21 @@ from .types.content import LogprobsResult from .types.content import ModalityTokenCount from .types.content import ModelArmorConfig +from .types.content import MultiSpeakerVoiceConfig from .types.content import Part +from .types.content import PrebuiltVoiceConfig +from .types.content import ReplicatedVoiceConfig from .types.content import RetrievalMetadata from .types.content import SafetyRating from .types.content import SafetySetting from .types.content import SearchEntryPoint from .types.content import Segment +from .types.content import SpeakerVoiceConfig +from .types.content import SpeechConfig from .types.content import UrlContextMetadata from .types.content import UrlMetadata from .types.content import VideoMetadata +from .types.content import VoiceConfig from .types.content import HarmCategory from .types.content import Modality from .types.context import Context @@ -837,6 +843,8 @@ from .types.prediction_service import DirectPredictResponse from .types.prediction_service import DirectRawPredictRequest from .types.prediction_service import DirectRawPredictResponse +from .types.prediction_service import EmbedContentRequest +from .types.prediction_service import EmbedContentResponse from .types.prediction_service import ExplainRequest from .types.prediction_service import ExplainResponse from .types.prediction_service import GenerateContentRequest @@ -963,6 +971,9 @@ from .types.tool import FunctionCallingConfig from .types.tool import FunctionDeclaration from .types.tool import FunctionResponse +from .types.tool import FunctionResponseBlob +from .types.tool import FunctionResponseFileData +from .types.tool import FunctionResponsePart from .types.tool import GoogleMaps from .types.tool import GoogleSearchRetrieval from .types.tool import RagRetrievalConfig @@ -980,6 +991,7 @@ from .types.training_pipeline import StratifiedSplit from .types.training_pipeline import TimestampSplit from .types.training_pipeline import TrainingPipeline +from .types.tuning_job import PreTunedModel from .types.tuning_job import SupervisedHyperParameters from .types.tuning_job import SupervisedTuningDatasetDistribution from .types.tuning_job import SupervisedTuningDataStats @@ -995,6 +1007,7 @@ from .types.types import StringArray from .types.types import Tensor from .types.unmanaged_container_model import UnmanagedContainerModel +from .types.usage_metadata import UsageMetadata from .types.user_action_reference import UserActionReference from .types.value import Value from .types.vertex_rag_data import CorpusStatus @@ -1348,6 +1361,8 @@ "DnsPeeringConfig", "DoubleArray", "DynamicRetrievalConfig", + "EmbedContentRequest", + "EmbedContentResponse", "EncryptionSpec", "Endpoint", "EndpointServiceClient", @@ -1438,6 +1453,9 @@ "FunctionCallingConfig", "FunctionDeclaration", "FunctionResponse", + "FunctionResponseBlob", + "FunctionResponseFileData", + "FunctionResponsePart", "GcsDestination", "GcsSource", "GenAiAdvancedFeaturesConfig", @@ -1689,6 +1707,7 @@ "ModelServiceClient", "ModelSourceInfo", "ModelVersionCheckpoint", + "MultiSpeakerVoiceConfig", "MutateDeployedIndexOperationMetadata", "MutateDeployedIndexRequest", "MutateDeployedIndexResponse", @@ -1752,6 +1771,8 @@ "PointwiseMetricSpec", "Port", "PostStartupScriptConfig", + "PreTunedModel", + "PrebuiltVoiceConfig", "PredefinedSplit", "PredictRequest", "PredictRequestResponseLoggingConfig", @@ -1840,6 +1861,7 @@ "RemoveContextChildrenResponse", "RemoveDatapointsRequest", "RemoveDatapointsResponse", + "ReplicatedVoiceConfig", "ReservationAffinity", "ResourcePool", "ResourceRuntime", @@ -1893,9 +1915,11 @@ "ShieldedVmConfig", "SlackSource", "SmoothGradConfig", + "SpeakerVoiceConfig", "SpecialistPool", "SpecialistPoolServiceClient", "SpeculativeDecodingSpec", + "SpeechConfig", "StartNotebookRuntimeOperationMetadata", "StartNotebookRuntimeRequest", "StartNotebookRuntimeResponse", @@ -2061,6 +2085,7 @@ "UrlContext", "UrlContextMetadata", "UrlMetadata", + "UsageMetadata", "UserActionReference", "Value", "VertexAISearch", @@ -2070,6 +2095,7 @@ "VertexRagStore", "VideoMetadata", "VizierServiceClient", + "VoiceConfig", "WorkerPoolSpec", "WriteFeatureValuesPayload", "WriteFeatureValuesRequest", diff --git a/google/cloud/aiplatform_v1/gapic_metadata.json b/google/cloud/aiplatform_v1/gapic_metadata.json index 7caba02205..c5e53304ab 100644 --- a/google/cloud/aiplatform_v1/gapic_metadata.json +++ b/google/cloud/aiplatform_v1/gapic_metadata.json @@ -4091,6 +4091,11 @@ "direct_raw_predict" ] }, + "EmbedContent": { + "methods": [ + "embed_content" + ] + }, "Explain": { "methods": [ "explain" @@ -4161,6 +4166,11 @@ "direct_raw_predict" ] }, + "EmbedContent": { + "methods": [ + "embed_content" + ] + }, "Explain": { "methods": [ "explain" @@ -4231,6 +4241,11 @@ "direct_raw_predict" ] }, + "EmbedContent": { + "methods": [ + "embed_content" + ] + }, "Explain": { "methods": [ "explain" diff --git a/google/cloud/aiplatform_v1/services/prediction_service/async_client.py b/google/cloud/aiplatform_v1/services/prediction_service/async_client.py index d2c4e46e19..222909f14b 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/async_client.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/async_client.py @@ -50,9 +50,11 @@ from google.api import httpbody_pb2 # type: ignore from google.cloud.aiplatform_v1.types import content +from google.cloud.aiplatform_v1.types import content as gca_content from google.cloud.aiplatform_v1.types import explanation from google.cloud.aiplatform_v1.types import prediction_service from google.cloud.aiplatform_v1.types import types +from google.cloud.aiplatform_v1.types import usage_metadata from google.cloud.location import locations_pb2 # type: ignore from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore @@ -1931,6 +1933,127 @@ async def sample_stream_generate_content(): # Done; return the response. return response + async def embed_content( + self, + request: Optional[Union[prediction_service.EmbedContentRequest, dict]] = None, + *, + model: Optional[str] = None, + content: Optional[gca_content.Content] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Embed content with multimodal inputs. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import aiplatform_v1 + + async def sample_embed_content(): + # Create a client + client = aiplatform_v1.PredictionServiceAsyncClient() + + # Initialize request argument(s) + request = aiplatform_v1.EmbedContentRequest( + ) + + # Make the request + response = await client.embed_content(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.aiplatform_v1.types.EmbedContentRequest, dict]]): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + model (:class:`str`): + Required. The name of the publisher model requested to + serve the prediction. Format: + ``projects/{project}/locations/{location}/publishers/*/models/*`` + + This corresponds to the ``model`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + content (:class:`google.cloud.aiplatform_v1.types.Content`): + Required. Input content to be + embedded. Required. + + This corresponds to the ``content`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.aiplatform_v1.types.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [model, content] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, prediction_service.EmbedContentRequest): + request = prediction_service.EmbedContentRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if model is not None: + request.model = model + if content is not None: + request.content = content + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.embed_content + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + async def list_operations( self, request: Optional[operations_pb2.ListOperationsRequest] = None, diff --git a/google/cloud/aiplatform_v1/services/prediction_service/client.py b/google/cloud/aiplatform_v1/services/prediction_service/client.py index 71ae364277..77ece99a94 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/client.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/client.py @@ -65,9 +65,11 @@ from google.api import httpbody_pb2 # type: ignore from google.cloud.aiplatform_v1.types import content +from google.cloud.aiplatform_v1.types import content as gca_content from google.cloud.aiplatform_v1.types import explanation from google.cloud.aiplatform_v1.types import prediction_service from google.cloud.aiplatform_v1.types import types +from google.cloud.aiplatform_v1.types import usage_metadata from google.cloud.location import locations_pb2 # type: ignore from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore @@ -2442,6 +2444,124 @@ def sample_stream_generate_content(): # Done; return the response. return response + def embed_content( + self, + request: Optional[Union[prediction_service.EmbedContentRequest, dict]] = None, + *, + model: Optional[str] = None, + content: Optional[gca_content.Content] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Embed content with multimodal inputs. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import aiplatform_v1 + + def sample_embed_content(): + # Create a client + client = aiplatform_v1.PredictionServiceClient() + + # Initialize request argument(s) + request = aiplatform_v1.EmbedContentRequest( + ) + + # Make the request + response = client.embed_content(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.aiplatform_v1.types.EmbedContentRequest, dict]): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + model (str): + Required. The name of the publisher model requested to + serve the prediction. Format: + ``projects/{project}/locations/{location}/publishers/*/models/*`` + + This corresponds to the ``model`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + content (google.cloud.aiplatform_v1.types.Content): + Required. Input content to be + embedded. Required. + + This corresponds to the ``content`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.aiplatform_v1.types.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [model, content] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, prediction_service.EmbedContentRequest): + request = prediction_service.EmbedContentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if model is not None: + request.model = model + if content is not None: + request.content = content + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.embed_content] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "PredictionServiceClient": return self diff --git a/google/cloud/aiplatform_v1/services/prediction_service/transports/base.py b/google/cloud/aiplatform_v1/services/prediction_service/transports/base.py index 56058be428..b7e61ae977 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/transports/base.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/transports/base.py @@ -207,6 +207,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.embed_content: gapic_v1.method.wrap_method( + self.embed_content, + default_timeout=None, + client_info=client_info, + ), self.get_location: gapic_v1.method.wrap_method( self.get_location, default_timeout=None, @@ -418,6 +423,18 @@ def stream_generate_content( ]: raise NotImplementedError() + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + Union[ + prediction_service.EmbedContentResponse, + Awaitable[prediction_service.EmbedContentResponse], + ], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc.py b/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc.py index 9c27e84ac0..0857a8e2e1 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc.py @@ -729,6 +729,35 @@ def stream_generate_content( ) return self._stubs["stream_generate_content"] + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + prediction_service.EmbedContentResponse, + ]: + r"""Return a callable for the embed content method over gRPC. + + Embed content with multimodal inputs. + + Returns: + Callable[[~.EmbedContentRequest], + ~.EmbedContentResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "embed_content" not in self._stubs: + self._stubs["embed_content"] = self._logged_channel.unary_unary( + "/google.cloud.aiplatform.v1.PredictionService/EmbedContent", + request_serializer=prediction_service.EmbedContentRequest.serialize, + response_deserializer=prediction_service.EmbedContentResponse.deserialize, + ) + return self._stubs["embed_content"] + def close(self): self._logged_channel.close() diff --git a/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc_asyncio.py b/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc_asyncio.py index e6dd57c60b..81ed9c6e8a 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc_asyncio.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/transports/grpc_asyncio.py @@ -743,6 +743,35 @@ def stream_generate_content( ) return self._stubs["stream_generate_content"] + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + Awaitable[prediction_service.EmbedContentResponse], + ]: + r"""Return a callable for the embed content method over gRPC. + + Embed content with multimodal inputs. + + Returns: + Callable[[~.EmbedContentRequest], + Awaitable[~.EmbedContentResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "embed_content" not in self._stubs: + self._stubs["embed_content"] = self._logged_channel.unary_unary( + "/google.cloud.aiplatform.v1.PredictionService/EmbedContent", + request_serializer=prediction_service.EmbedContentRequest.serialize, + response_deserializer=prediction_service.EmbedContentResponse.deserialize, + ) + return self._stubs["embed_content"] + def _prep_wrapped_messages(self, client_info): """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" self._wrapped_methods = { @@ -811,6 +840,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.embed_content: self._wrap_method( + self.embed_content, + default_timeout=None, + client_info=client_info, + ), self.get_location: self._wrap_method( self.get_location, default_timeout=None, diff --git a/google/cloud/aiplatform_v1/services/prediction_service/transports/rest.py b/google/cloud/aiplatform_v1/services/prediction_service/transports/rest.py index 45fac29870..f1031919b7 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/transports/rest.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/transports/rest.py @@ -99,6 +99,14 @@ def post_direct_raw_predict(self, response): logging.log(f"Received response: {response}") return response + def pre_embed_content(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_embed_content(self, response): + logging.log(f"Received response: {response}") + return response + def pre_explain(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -264,6 +272,56 @@ def post_direct_raw_predict_with_metadata( """ return response, metadata + def pre_embed_content( + self, + request: prediction_service.EmbedContentRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for embed_content + + Override in a subclass to manipulate the request or metadata + before they are sent to the PredictionService server. + """ + return request, metadata + + def post_embed_content( + self, response: prediction_service.EmbedContentResponse + ) -> prediction_service.EmbedContentResponse: + """Post-rpc interceptor for embed_content + + DEPRECATED. Please use the `post_embed_content_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the PredictionService server but before + it is returned to user code. This `post_embed_content` interceptor runs + before the `post_embed_content_with_metadata` interceptor. + """ + return response + + def post_embed_content_with_metadata( + self, + response: prediction_service.EmbedContentResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentResponse, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for embed_content + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the PredictionService server but before it is returned to user code. + + We recommend only using this `post_embed_content_with_metadata` + interceptor in new development instead of the `post_embed_content` interceptor. + When both interceptors are used, this `post_embed_content_with_metadata` interceptor runs after the + `post_embed_content` interceptor. The (possibly modified) response returned by + `post_embed_content` will be passed to + `post_embed_content_with_metadata`. + """ + return response, metadata + def pre_explain( self, request: prediction_service.ExplainRequest, @@ -1264,6 +1322,162 @@ def __call__( ) return resp + class _EmbedContent( + _BasePredictionServiceRestTransport._BaseEmbedContent, PredictionServiceRestStub + ): + def __hash__(self): + return hash("PredictionServiceRestTransport.EmbedContent") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: prediction_service.EmbedContentRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Call the embed content method over HTTP. + + Args: + request (~.prediction_service.EmbedContentRequest): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.prediction_service.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + + """ + + http_options = ( + _BasePredictionServiceRestTransport._BaseEmbedContent._get_http_options() + ) + + request, metadata = self._interceptor.pre_embed_content(request, metadata) + transcoded_request = _BasePredictionServiceRestTransport._BaseEmbedContent._get_transcoded_request( + http_options, request + ) + + body = _BasePredictionServiceRestTransport._BaseEmbedContent._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BasePredictionServiceRestTransport._BaseEmbedContent._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.aiplatform_v1.PredictionServiceClient.EmbedContent", + extra={ + "serviceName": "google.cloud.aiplatform.v1.PredictionService", + "rpcName": "EmbedContent", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = PredictionServiceRestTransport._EmbedContent._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = prediction_service.EmbedContentResponse() + pb_resp = prediction_service.EmbedContentResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_embed_content(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_embed_content_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = prediction_service.EmbedContentResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.aiplatform_v1.PredictionServiceClient.embed_content", + extra={ + "serviceName": "google.cloud.aiplatform.v1.PredictionService", + "rpcName": "EmbedContent", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _Explain( _BasePredictionServiceRestTransport._BaseExplain, PredictionServiceRestStub ): @@ -2550,6 +2764,17 @@ def direct_raw_predict( # In C++ this would require a dynamic_cast return self._DirectRawPredict(self._session, self._host, self._interceptor) # type: ignore + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + prediction_service.EmbedContentResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._EmbedContent(self._session, self._host, self._interceptor) # type: ignore + @property def explain( self, diff --git a/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_asyncio.py b/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_asyncio.py index ae8716306a..043f3368ba 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_asyncio.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_asyncio.py @@ -115,6 +115,14 @@ async def post_direct_raw_predict(self, response): logging.log(f"Received response: {response}") return response + async def pre_embed_content(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + async def post_embed_content(self, response): + logging.log(f"Received response: {response}") + return response + async def pre_explain(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -280,6 +288,56 @@ async def post_direct_raw_predict_with_metadata( """ return response, metadata + async def pre_embed_content( + self, + request: prediction_service.EmbedContentRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for embed_content + + Override in a subclass to manipulate the request or metadata + before they are sent to the PredictionService server. + """ + return request, metadata + + async def post_embed_content( + self, response: prediction_service.EmbedContentResponse + ) -> prediction_service.EmbedContentResponse: + """Post-rpc interceptor for embed_content + + DEPRECATED. Please use the `post_embed_content_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the PredictionService server but before + it is returned to user code. This `post_embed_content` interceptor runs + before the `post_embed_content_with_metadata` interceptor. + """ + return response + + async def post_embed_content_with_metadata( + self, + response: prediction_service.EmbedContentResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentResponse, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for embed_content + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the PredictionService server but before it is returned to user code. + + We recommend only using this `post_embed_content_with_metadata` + interceptor in new development instead of the `post_embed_content` interceptor. + When both interceptors are used, this `post_embed_content_with_metadata` interceptor runs after the + `post_embed_content` interceptor. The (possibly modified) response returned by + `post_embed_content` will be passed to + `post_embed_content_with_metadata`. + """ + return response, metadata + async def pre_explain( self, request: prediction_service.ExplainRequest, @@ -1013,6 +1071,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.embed_content: self._wrap_method( + self.embed_content, + default_timeout=None, + client_info=client_info, + ), self.get_location: self._wrap_method( self.get_location, default_timeout=None, @@ -1402,6 +1465,173 @@ async def __call__( return resp + class _EmbedContent( + _BasePredictionServiceRestTransport._BaseEmbedContent, + AsyncPredictionServiceRestStub, + ): + def __hash__(self): + return hash("AsyncPredictionServiceRestTransport.EmbedContent") + + @staticmethod + async def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = await getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + async def __call__( + self, + request: prediction_service.EmbedContentRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Call the embed content method over HTTP. + + Args: + request (~.prediction_service.EmbedContentRequest): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.prediction_service.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + + """ + + http_options = ( + _BasePredictionServiceRestTransport._BaseEmbedContent._get_http_options() + ) + + request, metadata = await self._interceptor.pre_embed_content( + request, metadata + ) + transcoded_request = _BasePredictionServiceRestTransport._BaseEmbedContent._get_transcoded_request( + http_options, request + ) + + body = _BasePredictionServiceRestTransport._BaseEmbedContent._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BasePredictionServiceRestTransport._BaseEmbedContent._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.aiplatform_v1.PredictionServiceClient.EmbedContent", + extra={ + "serviceName": "google.cloud.aiplatform.v1.PredictionService", + "rpcName": "EmbedContent", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + await AsyncPredictionServiceRestTransport._EmbedContent._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + content = await response.read() + payload = json.loads(content.decode("utf-8")) + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + raise core_exceptions.format_http_response_error(response, method, request_url, payload) # type: ignore + + # Return the response + resp = prediction_service.EmbedContentResponse() + pb_resp = prediction_service.EmbedContentResponse.pb(resp) + content = await response.read() + json_format.Parse(content, pb_resp, ignore_unknown_fields=True) + resp = await self._interceptor.post_embed_content(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = await self._interceptor.post_embed_content_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = prediction_service.EmbedContentResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": "OK", # need to obtain this properly + } + _LOGGER.debug( + "Received response for google.cloud.aiplatform_v1.PredictionServiceAsyncClient.embed_content", + extra={ + "serviceName": "google.cloud.aiplatform.v1.PredictionService", + "rpcName": "EmbedContent", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + + return resp + class _Explain( _BasePredictionServiceRestTransport._BaseExplain, AsyncPredictionServiceRestStub ): @@ -2730,6 +2960,15 @@ def direct_raw_predict( ]: return self._DirectRawPredict(self._session, self._host, self._interceptor) # type: ignore + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + prediction_service.EmbedContentResponse, + ]: + return self._EmbedContent(self._session, self._host, self._interceptor) # type: ignore + @property def explain( self, diff --git a/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_base.py b/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_base.py index 18970cabb7..24399ee420 100644 --- a/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_base.py +++ b/google/cloud/aiplatform_v1/services/prediction_service/transports/rest_base.py @@ -208,6 +208,48 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseEmbedContent: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{model=projects/*/locations/*/publishers/*/models/*}:embedContent", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = prediction_service.EmbedContentRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseExplain: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/google/cloud/aiplatform_v1/services/reasoning_engine_service/async_client.py b/google/cloud/aiplatform_v1/services/reasoning_engine_service/async_client.py index 31103cee7d..d0382eba25 100644 --- a/google/cloud/aiplatform_v1/services/reasoning_engine_service/async_client.py +++ b/google/cloud/aiplatform_v1/services/reasoning_engine_service/async_client.py @@ -86,6 +86,12 @@ class ReasoningEngineServiceAsyncClient: _DEFAULT_ENDPOINT_TEMPLATE = ReasoningEngineServiceClient._DEFAULT_ENDPOINT_TEMPLATE _DEFAULT_UNIVERSE = ReasoningEngineServiceClient._DEFAULT_UNIVERSE + git_repository_link_path = staticmethod( + ReasoningEngineServiceClient.git_repository_link_path + ) + parse_git_repository_link_path = staticmethod( + ReasoningEngineServiceClient.parse_git_repository_link_path + ) network_attachment_path = staticmethod( ReasoningEngineServiceClient.network_attachment_path ) diff --git a/google/cloud/aiplatform_v1/services/reasoning_engine_service/client.py b/google/cloud/aiplatform_v1/services/reasoning_engine_service/client.py index 94a95c4943..fecb834fe8 100644 --- a/google/cloud/aiplatform_v1/services/reasoning_engine_service/client.py +++ b/google/cloud/aiplatform_v1/services/reasoning_engine_service/client.py @@ -222,6 +222,30 @@ def transport(self) -> ReasoningEngineServiceTransport: """ return self._transport + @staticmethod + def git_repository_link_path( + project: str, + location: str, + connection: str, + git_repository_link: str, + ) -> str: + """Returns a fully-qualified git_repository_link string.""" + return "projects/{project}/locations/{location}/connections/{connection}/gitRepositoryLinks/{git_repository_link}".format( + project=project, + location=location, + connection=connection, + git_repository_link=git_repository_link, + ) + + @staticmethod + def parse_git_repository_link_path(path: str) -> Dict[str, str]: + """Parses a git_repository_link path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/connections/(?P.+?)/gitRepositoryLinks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def network_attachment_path( project: str, diff --git a/google/cloud/aiplatform_v1/types/__init__.py b/google/cloud/aiplatform_v1/types/__init__.py index f48e91e86e..1ef6535a2f 100644 --- a/google/cloud/aiplatform_v1/types/__init__.py +++ b/google/cloud/aiplatform_v1/types/__init__.py @@ -52,15 +52,21 @@ LogprobsResult, ModalityTokenCount, ModelArmorConfig, + MultiSpeakerVoiceConfig, Part, + PrebuiltVoiceConfig, + ReplicatedVoiceConfig, RetrievalMetadata, SafetyRating, SafetySetting, SearchEntryPoint, Segment, + SpeakerVoiceConfig, + SpeechConfig, UrlContextMetadata, UrlMetadata, VideoMetadata, + VoiceConfig, HarmCategory, Modality, ) @@ -916,6 +922,8 @@ DirectPredictResponse, DirectRawPredictRequest, DirectRawPredictResponse, + EmbedContentRequest, + EmbedContentResponse, ExplainRequest, ExplainResponse, GenerateContentRequest, @@ -1080,6 +1088,9 @@ FunctionCallingConfig, FunctionDeclaration, FunctionResponse, + FunctionResponseBlob, + FunctionResponseFileData, + FunctionResponsePart, GoogleMaps, GoogleSearchRetrieval, RagRetrievalConfig, @@ -1101,6 +1112,7 @@ TrainingPipeline, ) from .tuning_job import ( + PreTunedModel, SupervisedHyperParameters, SupervisedTuningDatasetDistribution, SupervisedTuningDataStats, @@ -1121,6 +1133,9 @@ from .unmanaged_container_model import ( UnmanagedContainerModel, ) +from .usage_metadata import ( + UsageMetadata, +) from .user_action_reference import ( UserActionReference, ) @@ -1226,15 +1241,21 @@ "LogprobsResult", "ModalityTokenCount", "ModelArmorConfig", + "MultiSpeakerVoiceConfig", "Part", + "PrebuiltVoiceConfig", + "ReplicatedVoiceConfig", "RetrievalMetadata", "SafetyRating", "SafetySetting", "SearchEntryPoint", "Segment", + "SpeakerVoiceConfig", + "SpeechConfig", "UrlContextMetadata", "UrlMetadata", "VideoMetadata", + "VoiceConfig", "HarmCategory", "Modality", "Context", @@ -1924,6 +1945,8 @@ "DirectPredictResponse", "DirectRawPredictRequest", "DirectRawPredictResponse", + "EmbedContentRequest", + "EmbedContentResponse", "ExplainRequest", "ExplainResponse", "GenerateContentRequest", @@ -2050,6 +2073,9 @@ "FunctionCallingConfig", "FunctionDeclaration", "FunctionResponse", + "FunctionResponseBlob", + "FunctionResponseFileData", + "FunctionResponsePart", "GoogleMaps", "GoogleSearchRetrieval", "RagRetrievalConfig", @@ -2067,6 +2093,7 @@ "StratifiedSplit", "TimestampSplit", "TrainingPipeline", + "PreTunedModel", "SupervisedHyperParameters", "SupervisedTuningDatasetDistribution", "SupervisedTuningDataStats", @@ -2082,6 +2109,7 @@ "StringArray", "Tensor", "UnmanagedContainerModel", + "UsageMetadata", "UserActionReference", "Value", "CorpusStatus", diff --git a/google/cloud/aiplatform_v1/types/content.py b/google/cloud/aiplatform_v1/types/content.py index 7ce727205d..1616544490 100644 --- a/google/cloud/aiplatform_v1/types/content.py +++ b/google/cloud/aiplatform_v1/types/content.py @@ -37,6 +37,12 @@ "Blob", "FileData", "VideoMetadata", + "PrebuiltVoiceConfig", + "ReplicatedVoiceConfig", + "VoiceConfig", + "SpeakerVoiceConfig", + "MultiSpeakerVoiceConfig", + "SpeechConfig", "ImageConfig", "GenerationConfig", "SafetySetting", @@ -341,6 +347,156 @@ class VideoMetadata(proto.Message): ) +class PrebuiltVoiceConfig(proto.Message): + r"""Configuration for a prebuilt voice. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + voice_name (str): + The name of the prebuilt voice to use. + + This field is a member of `oneof`_ ``_voice_name``. + """ + + voice_name: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ReplicatedVoiceConfig(proto.Message): + r"""The configuration for the replicated voice to use. + + Attributes: + mime_type (str): + Optional. The mimetype of the voice sample. Currently only + mime_type=audio/pcm is supported, which is raw mono 16-bit + signed little-endian pcm data, with 24k sampling rate. + voice_sample_audio (bytes): + Optional. The sample of the custom voice. + """ + + mime_type: str = proto.Field( + proto.STRING, + number=1, + ) + voice_sample_audio: bytes = proto.Field( + proto.BYTES, + number=2, + ) + + +class VoiceConfig(proto.Message): + r"""Configuration for a voice. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + prebuilt_voice_config (google.cloud.aiplatform_v1.types.PrebuiltVoiceConfig): + The configuration for a prebuilt voice. + + This field is a member of `oneof`_ ``voice_config``. + replicated_voice_config (google.cloud.aiplatform_v1.types.ReplicatedVoiceConfig): + Optional. The configuration for a replicated + voice. This enables users to replicate a voice + from an audio sample. + + This field is a member of `oneof`_ ``voice_config``. + """ + + prebuilt_voice_config: "PrebuiltVoiceConfig" = proto.Field( + proto.MESSAGE, + number=1, + oneof="voice_config", + message="PrebuiltVoiceConfig", + ) + replicated_voice_config: "ReplicatedVoiceConfig" = proto.Field( + proto.MESSAGE, + number=3, + oneof="voice_config", + message="ReplicatedVoiceConfig", + ) + + +class SpeakerVoiceConfig(proto.Message): + r"""Configuration for a single speaker in a multi-speaker setup. + + Attributes: + speaker (str): + Required. The name of the speaker. This + should be the same as the speaker name used in + the prompt. + voice_config (google.cloud.aiplatform_v1.types.VoiceConfig): + Required. The configuration for the voice of + this speaker. + """ + + speaker: str = proto.Field( + proto.STRING, + number=1, + ) + voice_config: "VoiceConfig" = proto.Field( + proto.MESSAGE, + number=2, + message="VoiceConfig", + ) + + +class MultiSpeakerVoiceConfig(proto.Message): + r"""Configuration for a multi-speaker text-to-speech request. + + Attributes: + speaker_voice_configs (MutableSequence[google.cloud.aiplatform_v1.types.SpeakerVoiceConfig]): + Required. A list of configurations for the + voices of the speakers. Exactly two speaker + voice configurations must be provided. + """ + + speaker_voice_configs: MutableSequence["SpeakerVoiceConfig"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SpeakerVoiceConfig", + ) + + +class SpeechConfig(proto.Message): + r"""Configuration for speech generation. + + Attributes: + voice_config (google.cloud.aiplatform_v1.types.VoiceConfig): + The configuration for the voice to use. + language_code (str): + Optional. The language code (ISO 639-1) for + the speech synthesis. + multi_speaker_voice_config (google.cloud.aiplatform_v1.types.MultiSpeakerVoiceConfig): + The configuration for a multi-speaker text-to-speech + request. This field is mutually exclusive with + ``voice_config``. + """ + + voice_config: "VoiceConfig" = proto.Field( + proto.MESSAGE, + number=1, + message="VoiceConfig", + ) + language_code: str = proto.Field( + proto.STRING, + number=2, + ) + multi_speaker_voice_config: "MultiSpeakerVoiceConfig" = proto.Field( + proto.MESSAGE, + number=3, + message="MultiSpeakerVoiceConfig", + ) + + class ImageConfig(proto.Message): r"""Config for image generation features. @@ -489,6 +645,10 @@ class GenerationConfig(proto.Message): Optional. Routing configuration. This field is a member of `oneof`_ ``_routing_config``. + speech_config (google.cloud.aiplatform_v1.types.SpeechConfig): + Optional. The speech generation config. + + This field is a member of `oneof`_ ``_speech_config``. thinking_config (google.cloud.aiplatform_v1.types.GenerationConfig.ThinkingConfig): Optional. Config for thinking features. An error will be returned if this field is set @@ -705,6 +865,12 @@ class ThinkingConfig(proto.Message): optional=True, message=RoutingConfig, ) + speech_config: "SpeechConfig" = proto.Field( + proto.MESSAGE, + number=23, + optional=True, + message="SpeechConfig", + ) thinking_config: ThinkingConfig = proto.Field( proto.MESSAGE, number=25, diff --git a/google/cloud/aiplatform_v1/types/deployment_stage.py b/google/cloud/aiplatform_v1/types/deployment_stage.py index dfb2c2a1ce..33ebadc7c9 100644 --- a/google/cloud/aiplatform_v1/types/deployment_stage.py +++ b/google/cloud/aiplatform_v1/types/deployment_stage.py @@ -55,6 +55,10 @@ class DeploymentStage(proto.Enum): steps. DEPLOYMENT_TERMINATED (10): The deployment has terminated. + SUCCESSFULLY_DEPLOYED (11): + The deployment has succeeded. + FAILED_TO_DEPLOY (12): + The deployment has failed. """ DEPLOYMENT_STAGE_UNSPECIFIED = 0 @@ -66,6 +70,8 @@ class DeploymentStage(proto.Enum): STARTING_MODEL_SERVER = 3 FINISHING_UP = 4 DEPLOYMENT_TERMINATED = 10 + SUCCESSFULLY_DEPLOYED = 11 + FAILED_TO_DEPLOY = 12 __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/aiplatform_v1/types/feature_online_store.py b/google/cloud/aiplatform_v1/types/feature_online_store.py index 4e260383b2..27c87933d8 100644 --- a/google/cloud/aiplatform_v1/types/feature_online_store.py +++ b/google/cloud/aiplatform_v1/types/feature_online_store.py @@ -216,11 +216,11 @@ class BigtableMetadata(proto.Message): ) enable_direct_bigtable_access: bool = proto.Field( proto.BOOL, - number=2, + number=3, ) bigtable_metadata: "FeatureOnlineStore.Bigtable.BigtableMetadata" = proto.Field( proto.MESSAGE, - number=3, + number=4, message="FeatureOnlineStore.Bigtable.BigtableMetadata", ) diff --git a/google/cloud/aiplatform_v1/types/feature_view.py b/google/cloud/aiplatform_v1/types/feature_view.py index 82912bf82f..41822f6ec2 100644 --- a/google/cloud/aiplatform_v1/types/feature_view.py +++ b/google/cloud/aiplatform_v1/types/feature_view.py @@ -532,7 +532,7 @@ class BigtableMetadata(proto.Message): ) bigtable_metadata: BigtableMetadata = proto.Field( proto.MESSAGE, - number=21, + number=22, message=BigtableMetadata, ) diff --git a/google/cloud/aiplatform_v1/types/machine_resources.py b/google/cloud/aiplatform_v1/types/machine_resources.py index e6b28ce41c..470b974e10 100644 --- a/google/cloud/aiplatform_v1/types/machine_resources.py +++ b/google/cloud/aiplatform_v1/types/machine_resources.py @@ -70,6 +70,21 @@ class MachineSpec(proto.Message): accelerator_count (int): The number of accelerators to attach to the machine. + gpu_partition_size (str): + Optional. Immutable. The Nvidia GPU partition size. + + When specified, the requested accelerators will be + partitioned into smaller GPU partitions. For example, if the + request is for 8 units of NVIDIA A100 GPUs, and + gpu_partition_size="1g.10gb", the service will create 8 \* 7 + = 56 partitioned MIG instances. + + The partition size must be a value supported by the + requested accelerator. Refer to `Nvidia GPU + Partitioning `__ + for the available partition sizes. + + If set, the accelerator_count should be set to 1. tpu_topology (str): Immutable. The topology of the TPUs. Corresponds to the TPU topologies available from GKE. (Example: tpu_topology: @@ -93,6 +108,10 @@ class MachineSpec(proto.Message): proto.INT32, number=3, ) + gpu_partition_size: str = proto.Field( + proto.STRING, + number=7, + ) tpu_topology: str = proto.Field( proto.STRING, number=4, diff --git a/google/cloud/aiplatform_v1/types/prediction_service.py b/google/cloud/aiplatform_v1/types/prediction_service.py index 545c389d0a..54d45d99b7 100644 --- a/google/cloud/aiplatform_v1/types/prediction_service.py +++ b/google/cloud/aiplatform_v1/types/prediction_service.py @@ -20,10 +20,11 @@ import proto # type: ignore from google.api import httpbody_pb2 # type: ignore -from google.cloud.aiplatform_v1.types import content +from google.cloud.aiplatform_v1.types import content as gca_content from google.cloud.aiplatform_v1.types import explanation from google.cloud.aiplatform_v1.types import tool from google.cloud.aiplatform_v1.types import types +from google.cloud.aiplatform_v1.types import usage_metadata as gca_usage_metadata from google.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -53,6 +54,8 @@ "CountTokensResponse", "GenerateContentRequest", "GenerateContentResponse", + "EmbedContentRequest", + "EmbedContentResponse", }, ) @@ -739,27 +742,27 @@ class CountTokensRequest(proto.Message): number=2, message=struct_pb2.Value, ) - contents: MutableSequence[content.Content] = proto.RepeatedField( + contents: MutableSequence[gca_content.Content] = proto.RepeatedField( proto.MESSAGE, number=4, - message=content.Content, + message=gca_content.Content, ) - system_instruction: content.Content = proto.Field( + system_instruction: gca_content.Content = proto.Field( proto.MESSAGE, number=5, optional=True, - message=content.Content, + message=gca_content.Content, ) tools: MutableSequence[tool.Tool] = proto.RepeatedField( proto.MESSAGE, number=6, message=tool.Tool, ) - generation_config: content.GenerationConfig = proto.Field( + generation_config: gca_content.GenerationConfig = proto.Field( proto.MESSAGE, number=7, optional=True, - message=content.GenerationConfig, + message=gca_content.GenerationConfig, ) @@ -786,11 +789,11 @@ class CountTokensResponse(proto.Message): proto.INT32, number=2, ) - prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + prompt_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=3, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) @@ -867,16 +870,16 @@ class GenerateContentRequest(proto.Message): proto.STRING, number=5, ) - contents: MutableSequence[content.Content] = proto.RepeatedField( + contents: MutableSequence[gca_content.Content] = proto.RepeatedField( proto.MESSAGE, number=2, - message=content.Content, + message=gca_content.Content, ) - system_instruction: content.Content = proto.Field( + system_instruction: gca_content.Content = proto.Field( proto.MESSAGE, number=8, optional=True, - message=content.Content, + message=gca_content.Content, ) cached_content: str = proto.Field( proto.STRING, @@ -897,20 +900,20 @@ class GenerateContentRequest(proto.Message): proto.STRING, number=10, ) - safety_settings: MutableSequence[content.SafetySetting] = proto.RepeatedField( + safety_settings: MutableSequence[gca_content.SafetySetting] = proto.RepeatedField( proto.MESSAGE, number=3, - message=content.SafetySetting, + message=gca_content.SafetySetting, ) - model_armor_config: content.ModelArmorConfig = proto.Field( + model_armor_config: gca_content.ModelArmorConfig = proto.Field( proto.MESSAGE, number=11, - message=content.ModelArmorConfig, + message=gca_content.ModelArmorConfig, ) - generation_config: content.GenerationConfig = proto.Field( + generation_config: gca_content.GenerationConfig = proto.Field( proto.MESSAGE, number=4, - message=content.GenerationConfig, + message=gca_content.GenerationConfig, ) @@ -987,10 +990,10 @@ class BlockedReason(proto.Enum): enum="GenerateContentResponse.PromptFeedback.BlockedReason", ) ) - safety_ratings: MutableSequence[content.SafetyRating] = proto.RepeatedField( + safety_ratings: MutableSequence[gca_content.SafetyRating] = proto.RepeatedField( proto.MESSAGE, number=2, - message=content.SafetyRating, + message=gca_content.SafetyRating, ) block_reason_message: str = proto.Field( proto.STRING, @@ -1047,32 +1050,32 @@ class UsageMetadata(proto.Message): proto.INT32, number=5, ) - prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + prompt_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=9, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) - cache_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + cache_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=10, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) - candidates_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + candidates_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=11, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) - candidates: MutableSequence[content.Candidate] = proto.RepeatedField( + candidates: MutableSequence[gca_content.Candidate] = proto.RepeatedField( proto.MESSAGE, number=2, - message=content.Candidate, + message=gca_content.Candidate, ) model_version: str = proto.Field( proto.STRING, @@ -1099,4 +1102,166 @@ class UsageMetadata(proto.Message): ) +class EmbedContentRequest(proto.Message): + r"""Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + model (str): + Required. The name of the publisher model requested to serve + the prediction. Format: + ``projects/{project}/locations/{location}/publishers/*/models/*`` + + This field is a member of `oneof`_ ``_model``. + content (google.cloud.aiplatform_v1.types.Content): + Required. Input content to be embedded. + Required. + + This field is a member of `oneof`_ ``_content``. + title (str): + Optional. An optional title for the text. + + This field is a member of `oneof`_ ``_title``. + task_type (google.cloud.aiplatform_v1.types.EmbedContentRequest.EmbeddingTaskType): + Optional. The task type of the embedding. + + This field is a member of `oneof`_ ``_task_type``. + output_dimensionality (int): + Optional. Optional reduced dimension for the + output embedding. If set, excessive values in + the output embedding are truncated from the end. + + This field is a member of `oneof`_ ``_output_dimensionality``. + auto_truncate (bool): + Optional. Whether to silently truncate the + input content if it's longer than the maximum + sequence length. + + This field is a member of `oneof`_ ``_auto_truncate``. + """ + + class EmbeddingTaskType(proto.Enum): + r"""Represents a downstream task the embeddings will be used for. + + Values: + UNSPECIFIED (0): + Unset value, which will default to one of the + other enum values. + RETRIEVAL_QUERY (2): + Specifies the given text is a query in a + search/retrieval setting. + RETRIEVAL_DOCUMENT (3): + Specifies the given text is a document from + the corpus being searched. + SEMANTIC_SIMILARITY (4): + Specifies the given text will be used for + STS. + CLASSIFICATION (5): + Specifies that the given text will be + classified. + CLUSTERING (6): + Specifies that the embeddings will be used + for clustering. + QUESTION_ANSWERING (7): + Specifies that the embeddings will be used + for question answering. + FACT_VERIFICATION (8): + Specifies that the embeddings will be used + for fact verification. + CODE_RETRIEVAL_QUERY (9): + Specifies that the embeddings will be used + for code retrieval. + """ + + UNSPECIFIED = 0 + RETRIEVAL_QUERY = 2 + RETRIEVAL_DOCUMENT = 3 + SEMANTIC_SIMILARITY = 4 + CLASSIFICATION = 5 + CLUSTERING = 6 + QUESTION_ANSWERING = 7 + FACT_VERIFICATION = 8 + CODE_RETRIEVAL_QUERY = 9 + + model: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + content: gca_content.Content = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message=gca_content.Content, + ) + title: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + task_type: EmbeddingTaskType = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=EmbeddingTaskType, + ) + output_dimensionality: int = proto.Field( + proto.INT32, + number=6, + optional=True, + ) + auto_truncate: bool = proto.Field( + proto.BOOL, + number=7, + optional=True, + ) + + +class EmbedContentResponse(proto.Message): + r"""Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1.PredictionService.EmbedContent]. + + Attributes: + embedding (google.cloud.aiplatform_v1.types.EmbedContentResponse.Embedding): + The embedding generated from the input + content. + usage_metadata (google.cloud.aiplatform_v1.types.UsageMetadata): + Metadata about the response(s). + truncated (bool): + Whether the input content was truncated + before generating the embedding. + """ + + class Embedding(proto.Message): + r"""A list of floats representing an embedding. + + Attributes: + values (MutableSequence[float]): + Embedding vector values. + """ + + values: MutableSequence[float] = proto.RepeatedField( + proto.FLOAT, + number=1, + ) + + embedding: Embedding = proto.Field( + proto.MESSAGE, + number=1, + message=Embedding, + ) + usage_metadata: gca_usage_metadata.UsageMetadata = proto.Field( + proto.MESSAGE, + number=2, + message=gca_usage_metadata.UsageMetadata, + ) + truncated: bool = proto.Field( + proto.BOOL, + number=4, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/aiplatform_v1/types/reasoning_engine.py b/google/cloud/aiplatform_v1/types/reasoning_engine.py index 8c3c048116..31e7daaf12 100644 --- a/google/cloud/aiplatform_v1/types/reasoning_engine.py +++ b/google/cloud/aiplatform_v1/types/reasoning_engine.py @@ -92,9 +92,9 @@ class PackageSpec(proto.Message): Optional. The Cloud Storage URI of the ``requirements.txt`` file python_version (str): - Optional. The Python version. Currently - support 3.8, 3.9, 3.10, 3.11. If not specified, - default value is 3.10. + Optional. The Python version. Supported + values are 3.9, 3.10, 3.11, 3.12, 3.13. If not + specified, the default value is 3.10. """ pickle_object_gcs_uri: str = proto.Field( @@ -207,6 +207,11 @@ class DeploymentSpec(proto.Message): class SourceCodeSpec(proto.Message): r"""Specification for deploying from source code. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: @@ -214,6 +219,11 @@ class SourceCodeSpec(proto.Message): Source code is provided directly in the request. + This field is a member of `oneof`_ ``source``. + developer_connect_source (google.cloud.aiplatform_v1.types.ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectSource): + Source code is in a Git repository managed by + Developer Connect. + This field is a member of `oneof`_ ``source``. python_spec (google.cloud.aiplatform_v1.types.ReasoningEngineSpec.SourceCodeSpec.PythonSpec): Configuration for a Python application. @@ -236,6 +246,57 @@ class InlineSource(proto.Message): number=1, ) + class DeveloperConnectConfig(proto.Message): + r"""Specifies the configuration for fetching source code from a + Git repository that is managed by Developer Connect. This + includes the repository, revision, and directory to use. + + Attributes: + git_repository_link (str): + Required. The Developer Connect Git repository link, + formatted as + ``projects/*/locations/*/connections/*/gitRepositoryLink/*``. + dir_ (str): + Required. Directory, relative to the source + root, in which to run the build. + revision (str): + Required. The revision to fetch from the Git + repository such as a branch, a tag, a commit + SHA, or any Git ref. + """ + + git_repository_link: str = proto.Field( + proto.STRING, + number=1, + ) + dir_: str = proto.Field( + proto.STRING, + number=2, + ) + revision: str = proto.Field( + proto.STRING, + number=3, + ) + + class DeveloperConnectSource(proto.Message): + r"""Specifies source code to be fetched from a Git repository + managed through the Developer Connect service. + + Attributes: + config (google.cloud.aiplatform_v1.types.ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectConfig): + Required. The Developer Connect configuration + that defines the specific repository, revision, + and directory to use as the source code root. + """ + + config: "ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectConfig" = ( + proto.Field( + proto.MESSAGE, + number=1, + message="ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectConfig", + ) + ) + class PythonSpec(proto.Message): r"""Specification for running a Python application from source. @@ -286,6 +347,14 @@ class PythonSpec(proto.Message): oneof="source", message="ReasoningEngineSpec.SourceCodeSpec.InlineSource", ) + developer_connect_source: ( + "ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectSource" + ) = proto.Field( + proto.MESSAGE, + number=3, + oneof="source", + message="ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectSource", + ) python_spec: "ReasoningEngineSpec.SourceCodeSpec.PythonSpec" = proto.Field( proto.MESSAGE, number=2, diff --git a/google/cloud/aiplatform_v1/types/tool.py b/google/cloud/aiplatform_v1/types/tool.py index a07018da3f..83f74a8880 100644 --- a/google/cloud/aiplatform_v1/types/tool.py +++ b/google/cloud/aiplatform_v1/types/tool.py @@ -31,6 +31,9 @@ "UrlContext", "FunctionDeclaration", "FunctionCall", + "FunctionResponsePart", + "FunctionResponseBlob", + "FunctionResponseFileData", "FunctionResponse", "ExecutableCode", "CodeExecutionResult", @@ -189,6 +192,16 @@ class ComputerUse(proto.Message): Attributes: environment (google.cloud.aiplatform_v1.types.Tool.ComputerUse.Environment): Required. The environment being operated. + excluded_predefined_functions (MutableSequence[str]): + Optional. By default, `predefined + functions `__ + are included in the final model call. Some of them can be + explicitly excluded from being automatically included. This + can serve two purposes: + + 1. Using a more restricted / different action space. + 2. Improving the definitions / instructions of predefined + functions. """ class Environment(proto.Enum): @@ -210,6 +223,10 @@ class Environment(proto.Enum): number=1, enum="Tool.ComputerUse.Environment", ) + excluded_predefined_functions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) function_declarations: MutableSequence["FunctionDeclaration"] = proto.RepeatedField( proto.MESSAGE, @@ -393,6 +410,123 @@ class FunctionCall(proto.Message): ) +class FunctionResponsePart(proto.Message): + r"""A datatype containing media that is part of a ``FunctionResponse`` + message. + + A ``FunctionResponsePart`` consists of data which has an associated + datatype. A ``FunctionResponsePart`` can only contain one of the + accepted types in ``FunctionResponsePart.data``. + + A ``FunctionResponsePart`` must have a fixed IANA MIME type + identifying the type and subtype of the media if the ``inline_data`` + field is filled with raw bytes. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + inline_data (google.cloud.aiplatform_v1.types.FunctionResponseBlob): + Inline media bytes. + + This field is a member of `oneof`_ ``data``. + file_data (google.cloud.aiplatform_v1.types.FunctionResponseFileData): + URI based data. + + This field is a member of `oneof`_ ``data``. + """ + + inline_data: "FunctionResponseBlob" = proto.Field( + proto.MESSAGE, + number=1, + oneof="data", + message="FunctionResponseBlob", + ) + file_data: "FunctionResponseFileData" = proto.Field( + proto.MESSAGE, + number=2, + oneof="data", + message="FunctionResponseFileData", + ) + + +class FunctionResponseBlob(proto.Message): + r"""Raw media bytes for function response. + + Text should not be sent as raw bytes, use the 'text' field. + + Attributes: + mime_type (str): + Required. The IANA standard MIME type of the + source data. + data (bytes): + Required. Raw bytes. + display_name (str): + Optional. Display name of the blob. + + Used to provide a label or filename to distinguish blobs. + + This field is only returned in PromptMessage for prompt + management. It is currently used in the Gemini + GenerateContent calls only when server side tools + (code_execution, google_search, and url_context) are + enabled. + """ + + mime_type: str = proto.Field( + proto.STRING, + number=1, + ) + data: bytes = proto.Field( + proto.BYTES, + number=2, + ) + display_name: str = proto.Field( + proto.STRING, + number=4, + ) + + +class FunctionResponseFileData(proto.Message): + r"""URI based data for function response. + + Attributes: + mime_type (str): + Required. The IANA standard MIME type of the + source data. + file_uri (str): + Required. URI. + display_name (str): + Optional. Display name of the file data. + + Used to provide a label or filename to distinguish file + datas. + + This field is only returned in PromptMessage for prompt + management. It is currently used in the Gemini + GenerateContent calls only when server side tools + (code_execution, google_search, and url_context) are + enabled. + """ + + mime_type: str = proto.Field( + proto.STRING, + number=1, + ) + file_uri: str = proto.Field( + proto.STRING, + number=2, + ) + display_name: str = proto.Field( + proto.STRING, + number=3, + ) + + class FunctionResponse(proto.Message): r"""The result output from a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON @@ -411,6 +545,9 @@ class FunctionResponse(proto.Message): details (if any). If "output" and "error" keys are not specified, then whole "response" is treated as function output. + parts (MutableSequence[google.cloud.aiplatform_v1.types.FunctionResponsePart]): + Optional. Ordered ``Parts`` that constitute a function + response. Parts may have different IANA MIME types. """ name: str = proto.Field( @@ -422,6 +559,11 @@ class FunctionResponse(proto.Message): number=2, message=struct_pb2.Struct, ) + parts: MutableSequence["FunctionResponsePart"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="FunctionResponsePart", + ) class ExecutableCode(proto.Message): diff --git a/google/cloud/aiplatform_v1/types/tuning_job.py b/google/cloud/aiplatform_v1/types/tuning_job.py index 615ad83d78..80a35c9992 100644 --- a/google/cloud/aiplatform_v1/types/tuning_job.py +++ b/google/cloud/aiplatform_v1/types/tuning_job.py @@ -38,6 +38,7 @@ "SupervisedTuningSpec", "TunedModelRef", "TunedModelCheckpoint", + "PreTunedModel", }, ) @@ -45,6 +46,11 @@ class TuningJob(proto.Message): r"""Represents a TuningJob that runs with Google owned models. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: @@ -52,6 +58,10 @@ class TuningJob(proto.Message): The base model that is being tuned. See `Supported models `__. + This field is a member of `oneof`_ ``source_model``. + pre_tuned_model (google.cloud.aiplatform_v1.types.PreTunedModel): + The pre-tuned model for continuous tuning. + This field is a member of `oneof`_ ``source_model``. supervised_tuning_spec (google.cloud.aiplatform_v1.types.SupervisedTuningSpec): Tuning Spec for Supervised Fine Tuning. @@ -65,7 +75,10 @@ class TuningJob(proto.Message): Optional. The display name of the [TunedModel][google.cloud.aiplatform.v1.Model]. The name can be up to 128 characters long and can consist of any UTF-8 - characters. + characters. For continuous tuning, tuned_model_display_name + will by default use the same display name as the pre-tuned + model. If a new display name is provided, the tuning job + will create a new model instead of a new version. description (str): Optional. The description of the [TuningJob][google.cloud.aiplatform.v1.TuningJob]. @@ -135,6 +148,12 @@ class TuningJob(proto.Message): number=4, oneof="source_model", ) + pre_tuned_model: "PreTunedModel" = proto.Field( + proto.MESSAGE, + number=31, + oneof="source_model", + message="PreTunedModel", + ) supervised_tuning_spec: "SupervisedTuningSpec" = proto.Field( proto.MESSAGE, number=5, @@ -220,7 +239,19 @@ class TunedModel(proto.Message): Attributes: model (str): Output only. The resource name of the TunedModel. Format: - ``projects/{project}/locations/{location}/models/{model}``. + + ``projects/{project}/locations/{location}/models/{model}@{version_id}`` + + When tuning from a base model, the version ID will be 1. + + For continuous tuning, if the provided + tuned_model_display_name is set and different from parent + model's display name, the tuned model will have a new parent + model with version 1. Otherwise the version id will be + incremented by 1 from the last version ID in the parent + model. E.g., + + ``projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}`` endpoint (str): Output only. A resource name of an Endpoint. Format: ``projects/{project}/locations/{location}/endpoints/{endpoint}``. @@ -644,4 +675,42 @@ class TunedModelCheckpoint(proto.Message): ) +class PreTunedModel(proto.Message): + r"""A pre-tuned model for continuous tuning. + + Attributes: + tuned_model_name (str): + The resource name of the Model. E.g., a model resource name + with a specified version id or alias: + + ``projects/{project}/locations/{location}/models/{model}@{version_id}`` + + ``projects/{project}/locations/{location}/models/{model}@{alias}`` + + Or, omit the version id to use the default version: + + ``projects/{project}/locations/{location}/models/{model}`` + checkpoint_id (str): + Optional. The source checkpoint id. If not + specified, the default checkpoint will be used. + base_model (str): + Output only. The name of the base model this + [PreTunedModel][google.cloud.aiplatform.v1.PreTunedModel] + was tuned from. + """ + + tuned_model_name: str = proto.Field( + proto.STRING, + number=1, + ) + checkpoint_id: str = proto.Field( + proto.STRING, + number=2, + ) + base_model: str = proto.Field( + proto.STRING, + number=3, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/aiplatform_v1/types/usage_metadata.py b/google/cloud/aiplatform_v1/types/usage_metadata.py new file mode 100644 index 0000000000..7e9fe542d8 --- /dev/null +++ b/google/cloud/aiplatform_v1/types/usage_metadata.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +from google.cloud.aiplatform_v1.types import content + + +__protobuf__ = proto.module( + package="google.cloud.aiplatform.v1", + manifest={ + "UsageMetadata", + }, +) + + +class UsageMetadata(proto.Message): + r"""Usage metadata about the content generation request and + response. This message provides a detailed breakdown of token + usage and other relevant metrics. + + Attributes: + prompt_token_count (int): + The total number of tokens in the prompt. This includes any + text, images, or other media provided in the request. When + ``cached_content`` is set, this also includes the number of + tokens in the cached content. + candidates_token_count (int): + The total number of tokens in the generated + candidates. + total_token_count (int): + The total number of tokens for the entire request. This is + the sum of ``prompt_token_count``, + ``candidates_token_count``, ``tool_use_prompt_token_count``, + and ``thoughts_token_count``. + tool_use_prompt_token_count (int): + Output only. The number of tokens in the + results from tool executions, which are provided + back to the model as input, if applicable. + thoughts_token_count (int): + Output only. The number of tokens that were + part of the model's generated "thoughts" output, + if applicable. + cached_content_token_count (int): + Output only. The number of tokens in the + cached content that was used for this request. + prompt_tokens_details (MutableSequence[google.cloud.aiplatform_v1.types.ModalityTokenCount]): + Output only. A detailed breakdown of the + token count for each modality in the prompt. + cache_tokens_details (MutableSequence[google.cloud.aiplatform_v1.types.ModalityTokenCount]): + Output only. A detailed breakdown of the + token count for each modality in the cached + content. + candidates_tokens_details (MutableSequence[google.cloud.aiplatform_v1.types.ModalityTokenCount]): + Output only. A detailed breakdown of the + token count for each modality in the generated + candidates. + tool_use_prompt_tokens_details (MutableSequence[google.cloud.aiplatform_v1.types.ModalityTokenCount]): + Output only. A detailed breakdown by modality + of the token counts from the results of tool + executions, which are provided back to the model + as input. + traffic_type (google.cloud.aiplatform_v1.types.UsageMetadata.TrafficType): + Output only. The traffic type for this + request. + """ + + class TrafficType(proto.Enum): + r"""The type of traffic that this request was processed with, + indicating which quota gets consumed. + + Values: + TRAFFIC_TYPE_UNSPECIFIED (0): + Unspecified request traffic type. + ON_DEMAND (1): + Type for Pay-As-You-Go traffic. + PROVISIONED_THROUGHPUT (2): + Type for Provisioned Throughput traffic. + """ + + TRAFFIC_TYPE_UNSPECIFIED = 0 + ON_DEMAND = 1 + PROVISIONED_THROUGHPUT = 2 + + prompt_token_count: int = proto.Field( + proto.INT32, + number=1, + ) + candidates_token_count: int = proto.Field( + proto.INT32, + number=2, + ) + total_token_count: int = proto.Field( + proto.INT32, + number=3, + ) + tool_use_prompt_token_count: int = proto.Field( + proto.INT32, + number=13, + ) + thoughts_token_count: int = proto.Field( + proto.INT32, + number=14, + ) + cached_content_token_count: int = proto.Field( + proto.INT32, + number=5, + ) + prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=9, + message=content.ModalityTokenCount, + ) + ) + cache_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=10, + message=content.ModalityTokenCount, + ) + ) + candidates_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=11, + message=content.ModalityTokenCount, + ) + ) + tool_use_prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=12, + message=content.ModalityTokenCount, + ) + ) + traffic_type: TrafficType = proto.Field( + proto.ENUM, + number=8, + enum=TrafficType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/aiplatform_v1beta1/__init__.py b/google/cloud/aiplatform_v1beta1/__init__.py index 0951ca584c..edd36ddde1 100644 --- a/google/cloud/aiplatform_v1beta1/__init__.py +++ b/google/cloud/aiplatform_v1beta1/__init__.py @@ -133,13 +133,16 @@ from .types.content import LogprobsResult from .types.content import ModalityTokenCount from .types.content import ModelArmorConfig +from .types.content import MultiSpeakerVoiceConfig from .types.content import Part from .types.content import PrebuiltVoiceConfig +from .types.content import ReplicatedVoiceConfig from .types.content import RetrievalMetadata from .types.content import SafetyRating from .types.content import SafetySetting from .types.content import SearchEntryPoint from .types.content import Segment +from .types.content import SpeakerVoiceConfig from .types.content import SpeechConfig from .types.content import UrlContextMetadata from .types.content import UrlMetadata @@ -1039,6 +1042,8 @@ from .types.prediction_service import DirectPredictResponse from .types.prediction_service import DirectRawPredictRequest from .types.prediction_service import DirectRawPredictResponse +from .types.prediction_service import EmbedContentRequest +from .types.prediction_service import EmbedContentResponse from .types.prediction_service import ExplainRequest from .types.prediction_service import ExplainResponse from .types.prediction_service import GenerateContentRequest @@ -1184,6 +1189,9 @@ from .types.tool import FunctionCallingConfig from .types.tool import FunctionDeclaration from .types.tool import FunctionResponse +from .types.tool import FunctionResponseBlob +from .types.tool import FunctionResponseFileData +from .types.tool import FunctionResponsePart from .types.tool import GoogleMaps from .types.tool import GoogleSearchRetrieval from .types.tool import RagRetrievalConfig @@ -1230,6 +1238,7 @@ from .types.ui_pipeline_spec import ArtifactTypeSchema from .types.ui_pipeline_spec import RuntimeArtifact from .types.unmanaged_container_model import UnmanagedContainerModel +from .types.usage_metadata import UsageMetadata from .types.user_action_reference import UserActionReference from .types.value import Value from .types.vertex_rag_data import CorpusStatus @@ -1638,6 +1647,8 @@ "DnsPeeringConfig", "DoubleArray", "DynamicRetrievalConfig", + "EmbedContentRequest", + "EmbedContentResponse", "EncryptionSpec", "Endpoint", "EndpointServiceClient", @@ -1760,6 +1771,9 @@ "FunctionCallingConfig", "FunctionDeclaration", "FunctionResponse", + "FunctionResponseBlob", + "FunctionResponseFileData", + "FunctionResponsePart", "GcsDestination", "GcsSource", "GeminiExample", @@ -2069,6 +2083,7 @@ "ModelServiceClient", "ModelSourceInfo", "ModelVersionCheckpoint", + "MultiSpeakerVoiceConfig", "MutateDeployedIndexOperationMetadata", "MutateDeployedIndexRequest", "MutateDeployedIndexResponse", @@ -2238,6 +2253,7 @@ "RemoveDatapointsResponse", "RemoveExamplesRequest", "RemoveExamplesResponse", + "ReplicatedVoiceConfig", "ReservationAffinity", "ResourcePool", "ResourceRuntime", @@ -2314,6 +2330,7 @@ "ShieldedVmConfig", "SlackSource", "SmoothGradConfig", + "SpeakerVoiceConfig", "SpecialistPool", "SpecialistPoolServiceClient", "SpeculativeDecodingSpec", @@ -2530,6 +2547,7 @@ "UrlContext", "UrlContextMetadata", "UrlMetadata", + "UsageMetadata", "UserActionReference", "Value", "VeoHyperParameters", diff --git a/google/cloud/aiplatform_v1beta1/gapic_metadata.json b/google/cloud/aiplatform_v1beta1/gapic_metadata.json index d1c5ead1aa..0e58db26fb 100644 --- a/google/cloud/aiplatform_v1beta1/gapic_metadata.json +++ b/google/cloud/aiplatform_v1beta1/gapic_metadata.json @@ -4972,6 +4972,11 @@ "direct_raw_predict" ] }, + "EmbedContent": { + "methods": [ + "embed_content" + ] + }, "Explain": { "methods": [ "explain" @@ -5052,6 +5057,11 @@ "direct_raw_predict" ] }, + "EmbedContent": { + "methods": [ + "embed_content" + ] + }, "Explain": { "methods": [ "explain" @@ -5132,6 +5142,11 @@ "direct_raw_predict" ] }, + "EmbedContent": { + "methods": [ + "embed_content" + ] + }, "Explain": { "methods": [ "explain" diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/async_client.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/async_client.py index c61938ce46..6f3e403ec7 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/async_client.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/async_client.py @@ -50,9 +50,11 @@ from google.api import httpbody_pb2 # type: ignore from google.cloud.aiplatform_v1beta1.types import content +from google.cloud.aiplatform_v1beta1.types import content as gca_content from google.cloud.aiplatform_v1beta1.types import explanation from google.cloud.aiplatform_v1beta1.types import prediction_service from google.cloud.aiplatform_v1beta1.types import types +from google.cloud.aiplatform_v1beta1.types import usage_metadata from google.cloud.location import locations_pb2 # type: ignore from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore @@ -2225,6 +2227,127 @@ async def sample_chat_completions(): # Done; return the response. return response + async def embed_content( + self, + request: Optional[Union[prediction_service.EmbedContentRequest, dict]] = None, + *, + model: Optional[str] = None, + content: Optional[gca_content.Content] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Embed content with multimodal inputs. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import aiplatform_v1beta1 + + async def sample_embed_content(): + # Create a client + client = aiplatform_v1beta1.PredictionServiceAsyncClient() + + # Initialize request argument(s) + request = aiplatform_v1beta1.EmbedContentRequest( + ) + + # Make the request + response = await client.embed_content(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.aiplatform_v1beta1.types.EmbedContentRequest, dict]]): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + model (:class:`str`): + Required. The name of the publisher model requested to + serve the prediction. Format: + ``projects/{project}/locations/{location}/publishers/*/models/*`` + + This corresponds to the ``model`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + content (:class:`google.cloud.aiplatform_v1beta1.types.Content`): + Required. Input content to be + embedded. Required. + + This corresponds to the ``content`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.aiplatform_v1beta1.types.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [model, content] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, prediction_service.EmbedContentRequest): + request = prediction_service.EmbedContentRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if model is not None: + request.model = model + if content is not None: + request.content = content + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.embed_content + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + async def list_operations( self, request: Optional[operations_pb2.ListOperationsRequest] = None, diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py index 975f0dbb7c..1dcb89df2d 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/client.py @@ -65,9 +65,11 @@ from google.api import httpbody_pb2 # type: ignore from google.cloud.aiplatform_v1beta1.types import content +from google.cloud.aiplatform_v1beta1.types import content as gca_content from google.cloud.aiplatform_v1beta1.types import explanation from google.cloud.aiplatform_v1beta1.types import prediction_service from google.cloud.aiplatform_v1beta1.types import types +from google.cloud.aiplatform_v1beta1.types import usage_metadata from google.cloud.location import locations_pb2 # type: ignore from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import policy_pb2 # type: ignore @@ -2730,6 +2732,124 @@ def sample_chat_completions(): # Done; return the response. return response + def embed_content( + self, + request: Optional[Union[prediction_service.EmbedContentRequest, dict]] = None, + *, + model: Optional[str] = None, + content: Optional[gca_content.Content] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Embed content with multimodal inputs. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import aiplatform_v1beta1 + + def sample_embed_content(): + # Create a client + client = aiplatform_v1beta1.PredictionServiceClient() + + # Initialize request argument(s) + request = aiplatform_v1beta1.EmbedContentRequest( + ) + + # Make the request + response = client.embed_content(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.aiplatform_v1beta1.types.EmbedContentRequest, dict]): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + model (str): + Required. The name of the publisher model requested to + serve the prediction. Format: + ``projects/{project}/locations/{location}/publishers/*/models/*`` + + This corresponds to the ``model`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + content (google.cloud.aiplatform_v1beta1.types.Content): + Required. Input content to be + embedded. Required. + + This corresponds to the ``content`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.aiplatform_v1beta1.types.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [model, content] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, prediction_service.EmbedContentRequest): + request = prediction_service.EmbedContentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if model is not None: + request.model = model + if content is not None: + request.content = content + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.embed_content] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "PredictionServiceClient": return self diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/base.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/base.py index 718cfbcd89..8a4d012034 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/base.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/base.py @@ -217,6 +217,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.embed_content: gapic_v1.method.wrap_method( + self.embed_content, + default_timeout=None, + client_info=client_info, + ), self.get_location: gapic_v1.method.wrap_method( self.get_location, default_timeout=None, @@ -449,6 +454,18 @@ def chat_completions( ]: raise NotImplementedError() + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + Union[ + prediction_service.EmbedContentResponse, + Awaitable[prediction_service.EmbedContentResponse], + ], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc.py index fc22ec1230..21f183e402 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc.py @@ -784,6 +784,35 @@ def chat_completions( ) return self._stubs["chat_completions"] + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + prediction_service.EmbedContentResponse, + ]: + r"""Return a callable for the embed content method over gRPC. + + Embed content with multimodal inputs. + + Returns: + Callable[[~.EmbedContentRequest], + ~.EmbedContentResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "embed_content" not in self._stubs: + self._stubs["embed_content"] = self._logged_channel.unary_unary( + "/google.cloud.aiplatform.v1beta1.PredictionService/EmbedContent", + request_serializer=prediction_service.EmbedContentRequest.serialize, + response_deserializer=prediction_service.EmbedContentResponse.deserialize, + ) + return self._stubs["embed_content"] + def close(self): self._logged_channel.close() diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc_asyncio.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc_asyncio.py index f1a011db14..7b62d5075d 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc_asyncio.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/grpc_asyncio.py @@ -801,6 +801,35 @@ def chat_completions( ) return self._stubs["chat_completions"] + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + Awaitable[prediction_service.EmbedContentResponse], + ]: + r"""Return a callable for the embed content method over gRPC. + + Embed content with multimodal inputs. + + Returns: + Callable[[~.EmbedContentRequest], + Awaitable[~.EmbedContentResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "embed_content" not in self._stubs: + self._stubs["embed_content"] = self._logged_channel.unary_unary( + "/google.cloud.aiplatform.v1beta1.PredictionService/EmbedContent", + request_serializer=prediction_service.EmbedContentRequest.serialize, + response_deserializer=prediction_service.EmbedContentResponse.deserialize, + ) + return self._stubs["embed_content"] + def _prep_wrapped_messages(self, client_info): """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" self._wrapped_methods = { @@ -879,6 +908,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.embed_content: self._wrap_method( + self.embed_content, + default_timeout=None, + client_info=client_info, + ), self.get_location: self._wrap_method( self.get_location, default_timeout=None, diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest.py index a4b99b35b7..a9a97eed62 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest.py @@ -115,6 +115,14 @@ def post_direct_raw_predict(self, response): logging.log(f"Received response: {response}") return response + def pre_embed_content(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_embed_content(self, response): + logging.log(f"Received response: {response}") + return response + def pre_explain(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -381,6 +389,56 @@ def post_direct_raw_predict_with_metadata( """ return response, metadata + def pre_embed_content( + self, + request: prediction_service.EmbedContentRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for embed_content + + Override in a subclass to manipulate the request or metadata + before they are sent to the PredictionService server. + """ + return request, metadata + + def post_embed_content( + self, response: prediction_service.EmbedContentResponse + ) -> prediction_service.EmbedContentResponse: + """Post-rpc interceptor for embed_content + + DEPRECATED. Please use the `post_embed_content_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the PredictionService server but before + it is returned to user code. This `post_embed_content` interceptor runs + before the `post_embed_content_with_metadata` interceptor. + """ + return response + + def post_embed_content_with_metadata( + self, + response: prediction_service.EmbedContentResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentResponse, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for embed_content + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the PredictionService server but before it is returned to user code. + + We recommend only using this `post_embed_content_with_metadata` + interceptor in new development instead of the `post_embed_content` interceptor. + When both interceptors are used, this `post_embed_content_with_metadata` interceptor runs after the + `post_embed_content` interceptor. The (possibly modified) response returned by + `post_embed_content` will be passed to + `post_embed_content_with_metadata`. + """ + return response, metadata + def pre_explain( self, request: prediction_service.ExplainRequest, @@ -1733,6 +1791,162 @@ def __call__( ) return resp + class _EmbedContent( + _BasePredictionServiceRestTransport._BaseEmbedContent, PredictionServiceRestStub + ): + def __hash__(self): + return hash("PredictionServiceRestTransport.EmbedContent") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: prediction_service.EmbedContentRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Call the embed content method over HTTP. + + Args: + request (~.prediction_service.EmbedContentRequest): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.prediction_service.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + + """ + + http_options = ( + _BasePredictionServiceRestTransport._BaseEmbedContent._get_http_options() + ) + + request, metadata = self._interceptor.pre_embed_content(request, metadata) + transcoded_request = _BasePredictionServiceRestTransport._BaseEmbedContent._get_transcoded_request( + http_options, request + ) + + body = _BasePredictionServiceRestTransport._BaseEmbedContent._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BasePredictionServiceRestTransport._BaseEmbedContent._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.aiplatform_v1beta1.PredictionServiceClient.EmbedContent", + extra={ + "serviceName": "google.cloud.aiplatform.v1beta1.PredictionService", + "rpcName": "EmbedContent", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = PredictionServiceRestTransport._EmbedContent._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = prediction_service.EmbedContentResponse() + pb_resp = prediction_service.EmbedContentResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_embed_content(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_embed_content_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = prediction_service.EmbedContentResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.aiplatform_v1beta1.PredictionServiceClient.embed_content", + extra={ + "serviceName": "google.cloud.aiplatform.v1beta1.PredictionService", + "rpcName": "EmbedContent", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _Explain( _BasePredictionServiceRestTransport._BaseExplain, PredictionServiceRestStub ): @@ -3037,6 +3251,17 @@ def direct_raw_predict( # In C++ this would require a dynamic_cast return self._DirectRawPredict(self._session, self._host, self._interceptor) # type: ignore + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + prediction_service.EmbedContentResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._EmbedContent(self._session, self._host, self._interceptor) # type: ignore + @property def explain( self, diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_asyncio.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_asyncio.py index 9a575189f4..36d94ae2a2 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_asyncio.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_asyncio.py @@ -131,6 +131,14 @@ async def post_direct_raw_predict(self, response): logging.log(f"Received response: {response}") return response + async def pre_embed_content(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + async def post_embed_content(self, response): + logging.log(f"Received response: {response}") + return response + async def pre_explain(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -398,6 +406,56 @@ async def post_direct_raw_predict_with_metadata( """ return response, metadata + async def pre_embed_content( + self, + request: prediction_service.EmbedContentRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for embed_content + + Override in a subclass to manipulate the request or metadata + before they are sent to the PredictionService server. + """ + return request, metadata + + async def post_embed_content( + self, response: prediction_service.EmbedContentResponse + ) -> prediction_service.EmbedContentResponse: + """Post-rpc interceptor for embed_content + + DEPRECATED. Please use the `post_embed_content_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the PredictionService server but before + it is returned to user code. This `post_embed_content` interceptor runs + before the `post_embed_content_with_metadata` interceptor. + """ + return response + + async def post_embed_content_with_metadata( + self, + response: prediction_service.EmbedContentResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + prediction_service.EmbedContentResponse, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for embed_content + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the PredictionService server but before it is returned to user code. + + We recommend only using this `post_embed_content_with_metadata` + interceptor in new development instead of the `post_embed_content` interceptor. + When both interceptors are used, this `post_embed_content_with_metadata` interceptor runs after the + `post_embed_content` interceptor. The (possibly modified) response returned by + `post_embed_content` will be passed to + `post_embed_content_with_metadata`. + """ + return response, metadata + async def pre_explain( self, request: prediction_service.ExplainRequest, @@ -1141,6 +1199,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.embed_content: self._wrap_method( + self.embed_content, + default_timeout=None, + client_info=client_info, + ), self.get_location: self._wrap_method( self.get_location, default_timeout=None, @@ -1900,6 +1963,173 @@ async def __call__( return resp + class _EmbedContent( + _BasePredictionServiceRestTransport._BaseEmbedContent, + AsyncPredictionServiceRestStub, + ): + def __hash__(self): + return hash("AsyncPredictionServiceRestTransport.EmbedContent") + + @staticmethod + async def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = await getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + async def __call__( + self, + request: prediction_service.EmbedContentRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> prediction_service.EmbedContentResponse: + r"""Call the embed content method over HTTP. + + Args: + request (~.prediction_service.EmbedContentRequest): + The request object. Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.prediction_service.EmbedContentResponse: + Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + + """ + + http_options = ( + _BasePredictionServiceRestTransport._BaseEmbedContent._get_http_options() + ) + + request, metadata = await self._interceptor.pre_embed_content( + request, metadata + ) + transcoded_request = _BasePredictionServiceRestTransport._BaseEmbedContent._get_transcoded_request( + http_options, request + ) + + body = _BasePredictionServiceRestTransport._BaseEmbedContent._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BasePredictionServiceRestTransport._BaseEmbedContent._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.aiplatform_v1beta1.PredictionServiceClient.EmbedContent", + extra={ + "serviceName": "google.cloud.aiplatform.v1beta1.PredictionService", + "rpcName": "EmbedContent", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + await AsyncPredictionServiceRestTransport._EmbedContent._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + body, + ) + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + content = await response.read() + payload = json.loads(content.decode("utf-8")) + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + raise core_exceptions.format_http_response_error(response, method, request_url, payload) # type: ignore + + # Return the response + resp = prediction_service.EmbedContentResponse() + pb_resp = prediction_service.EmbedContentResponse.pb(resp) + content = await response.read() + json_format.Parse(content, pb_resp, ignore_unknown_fields=True) + resp = await self._interceptor.post_embed_content(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = await self._interceptor.post_embed_content_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = prediction_service.EmbedContentResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": "OK", # need to obtain this properly + } + _LOGGER.debug( + "Received response for google.cloud.aiplatform_v1beta1.PredictionServiceAsyncClient.embed_content", + extra={ + "serviceName": "google.cloud.aiplatform.v1beta1.PredictionService", + "rpcName": "EmbedContent", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + + return resp + class _Explain( _BasePredictionServiceRestTransport._BaseExplain, AsyncPredictionServiceRestStub ): @@ -3242,6 +3472,15 @@ def direct_raw_predict( ]: return self._DirectRawPredict(self._session, self._host, self._interceptor) # type: ignore + @property + def embed_content( + self, + ) -> Callable[ + [prediction_service.EmbedContentRequest], + prediction_service.EmbedContentResponse, + ]: + return self._EmbedContent(self._session, self._host, self._interceptor) # type: ignore + @property def explain( self, diff --git a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_base.py b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_base.py index 197c44a77e..5753e3ec4e 100644 --- a/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_base.py +++ b/google/cloud/aiplatform_v1beta1/services/prediction_service/transports/rest_base.py @@ -337,6 +337,48 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseEmbedContent: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta1/{model=projects/*/locations/*/publishers/*/models/*}:embedContent", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = prediction_service.EmbedContentRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseExplain: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/async_client.py b/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/async_client.py index 1708bed0ca..2d7240a279 100644 --- a/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/async_client.py +++ b/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/async_client.py @@ -90,6 +90,12 @@ class ReasoningEngineServiceAsyncClient: endpoint_path = staticmethod(ReasoningEngineServiceClient.endpoint_path) parse_endpoint_path = staticmethod(ReasoningEngineServiceClient.parse_endpoint_path) + git_repository_link_path = staticmethod( + ReasoningEngineServiceClient.git_repository_link_path + ) + parse_git_repository_link_path = staticmethod( + ReasoningEngineServiceClient.parse_git_repository_link_path + ) network_attachment_path = staticmethod( ReasoningEngineServiceClient.network_attachment_path ) diff --git a/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/client.py b/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/client.py index 1bab3f8abe..1f0541cb98 100644 --- a/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/client.py +++ b/google/cloud/aiplatform_v1beta1/services/reasoning_engine_service/client.py @@ -246,6 +246,30 @@ def parse_endpoint_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def git_repository_link_path( + project: str, + location: str, + connection: str, + git_repository_link: str, + ) -> str: + """Returns a fully-qualified git_repository_link string.""" + return "projects/{project}/locations/{location}/connections/{connection}/gitRepositoryLinks/{git_repository_link}".format( + project=project, + location=location, + connection=connection, + git_repository_link=git_repository_link, + ) + + @staticmethod + def parse_git_repository_link_path(path: str) -> Dict[str, str]: + """Parses a git_repository_link path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/connections/(?P.+?)/gitRepositoryLinks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def network_attachment_path( project: str, diff --git a/google/cloud/aiplatform_v1beta1/types/__init__.py b/google/cloud/aiplatform_v1beta1/types/__init__.py index 5de61eb8dd..6b6d6666c4 100644 --- a/google/cloud/aiplatform_v1beta1/types/__init__.py +++ b/google/cloud/aiplatform_v1beta1/types/__init__.py @@ -52,13 +52,16 @@ LogprobsResult, ModalityTokenCount, ModelArmorConfig, + MultiSpeakerVoiceConfig, Part, PrebuiltVoiceConfig, + ReplicatedVoiceConfig, RetrievalMetadata, SafetyRating, SafetySetting, SearchEntryPoint, Segment, + SpeakerVoiceConfig, SpeechConfig, UrlContextMetadata, UrlMetadata, @@ -1138,6 +1141,8 @@ DirectPredictResponse, DirectRawPredictRequest, DirectRawPredictResponse, + EmbedContentRequest, + EmbedContentResponse, ExplainRequest, ExplainResponse, GenerateContentRequest, @@ -1325,6 +1330,9 @@ FunctionCallingConfig, FunctionDeclaration, FunctionResponse, + FunctionResponseBlob, + FunctionResponseFileData, + FunctionResponsePart, GoogleMaps, GoogleSearchRetrieval, RagRetrievalConfig, @@ -1382,6 +1390,9 @@ from .unmanaged_container_model import ( UnmanagedContainerModel, ) +from .usage_metadata import ( + UsageMetadata, +) from .user_action_reference import ( UserActionReference, ) @@ -1488,13 +1499,16 @@ "LogprobsResult", "ModalityTokenCount", "ModelArmorConfig", + "MultiSpeakerVoiceConfig", "Part", "PrebuiltVoiceConfig", + "ReplicatedVoiceConfig", "RetrievalMetadata", "SafetyRating", "SafetySetting", "SearchEntryPoint", "Segment", + "SpeakerVoiceConfig", "SpeechConfig", "UrlContextMetadata", "UrlMetadata", @@ -2378,6 +2392,8 @@ "DirectPredictResponse", "DirectRawPredictRequest", "DirectRawPredictResponse", + "EmbedContentRequest", + "EmbedContentResponse", "ExplainRequest", "ExplainResponse", "GenerateContentRequest", @@ -2523,6 +2539,9 @@ "FunctionCallingConfig", "FunctionDeclaration", "FunctionResponse", + "FunctionResponseBlob", + "FunctionResponseFileData", + "FunctionResponsePart", "GoogleMaps", "GoogleSearchRetrieval", "RagRetrievalConfig", @@ -2569,6 +2588,7 @@ "ArtifactTypeSchema", "RuntimeArtifact", "UnmanagedContainerModel", + "UsageMetadata", "UserActionReference", "Value", "CorpusStatus", diff --git a/google/cloud/aiplatform_v1beta1/types/content.py b/google/cloud/aiplatform_v1beta1/types/content.py index 59c5b57daa..5d37519815 100644 --- a/google/cloud/aiplatform_v1beta1/types/content.py +++ b/google/cloud/aiplatform_v1beta1/types/content.py @@ -38,7 +38,10 @@ "FileData", "VideoMetadata", "PrebuiltVoiceConfig", + "ReplicatedVoiceConfig", "VoiceConfig", + "SpeakerVoiceConfig", + "MultiSpeakerVoiceConfig", "SpeechConfig", "ImageConfig", "GenerationConfig", @@ -363,15 +366,47 @@ class PrebuiltVoiceConfig(proto.Message): ) +class ReplicatedVoiceConfig(proto.Message): + r"""The configuration for the replicated voice to use. + + Attributes: + mime_type (str): + Optional. The mimetype of the voice sample. Currently only + mime_type=audio/pcm is supported, which is raw mono 16-bit + signed little-endian pcm data, with 24k sampling rate. + voice_sample_audio (bytes): + Optional. The sample of the custom voice. + """ + + mime_type: str = proto.Field( + proto.STRING, + number=1, + ) + voice_sample_audio: bytes = proto.Field( + proto.BYTES, + number=2, + ) + + class VoiceConfig(proto.Message): - r"""The configuration for the voice to use. + r"""Configuration for a voice. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: prebuilt_voice_config (google.cloud.aiplatform_v1beta1.types.PrebuiltVoiceConfig): - The configuration for the prebuilt voice to - use. + The configuration for a prebuilt voice. + + This field is a member of `oneof`_ ``voice_config``. + replicated_voice_config (google.cloud.aiplatform_v1beta1.types.ReplicatedVoiceConfig): + Optional. The configuration for a replicated + voice. This enables users to replicate a voice + from an audio sample. This field is a member of `oneof`_ ``voice_config``. """ @@ -382,14 +417,68 @@ class VoiceConfig(proto.Message): oneof="voice_config", message="PrebuiltVoiceConfig", ) + replicated_voice_config: "ReplicatedVoiceConfig" = proto.Field( + proto.MESSAGE, + number=3, + oneof="voice_config", + message="ReplicatedVoiceConfig", + ) + + +class SpeakerVoiceConfig(proto.Message): + r"""Configuration for a single speaker in a multi-speaker setup. + + Attributes: + speaker (str): + Required. The name of the speaker. This + should be the same as the speaker name used in + the prompt. + voice_config (google.cloud.aiplatform_v1beta1.types.VoiceConfig): + Required. The configuration for the voice of + this speaker. + """ + + speaker: str = proto.Field( + proto.STRING, + number=1, + ) + voice_config: "VoiceConfig" = proto.Field( + proto.MESSAGE, + number=2, + message="VoiceConfig", + ) + + +class MultiSpeakerVoiceConfig(proto.Message): + r"""Configuration for a multi-speaker text-to-speech request. + + Attributes: + speaker_voice_configs (MutableSequence[google.cloud.aiplatform_v1beta1.types.SpeakerVoiceConfig]): + Required. A list of configurations for the + voices of the speakers. Exactly two speaker + voice configurations must be provided. + """ + + speaker_voice_configs: MutableSequence["SpeakerVoiceConfig"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SpeakerVoiceConfig", + ) class SpeechConfig(proto.Message): - r"""The speech generation config. + r"""Configuration for speech generation. Attributes: voice_config (google.cloud.aiplatform_v1beta1.types.VoiceConfig): - The configuration for the speaker to use. + The configuration for the voice to use. + language_code (str): + Optional. The language code (ISO 639-1) for + the speech synthesis. + multi_speaker_voice_config (google.cloud.aiplatform_v1beta1.types.MultiSpeakerVoiceConfig): + The configuration for a multi-speaker text-to-speech + request. This field is mutually exclusive with + ``voice_config``. """ voice_config: "VoiceConfig" = proto.Field( @@ -397,6 +486,15 @@ class SpeechConfig(proto.Message): number=1, message="VoiceConfig", ) + language_code: str = proto.Field( + proto.STRING, + number=2, + ) + multi_speaker_voice_config: "MultiSpeakerVoiceConfig" = proto.Field( + proto.MESSAGE, + number=3, + message="MultiSpeakerVoiceConfig", + ) class ImageConfig(proto.Message): diff --git a/google/cloud/aiplatform_v1beta1/types/deployment_stage.py b/google/cloud/aiplatform_v1beta1/types/deployment_stage.py index 08790976ea..b08a82f10a 100644 --- a/google/cloud/aiplatform_v1beta1/types/deployment_stage.py +++ b/google/cloud/aiplatform_v1beta1/types/deployment_stage.py @@ -55,6 +55,10 @@ class DeploymentStage(proto.Enum): steps. DEPLOYMENT_TERMINATED (10): The deployment has terminated. + SUCCESSFULLY_DEPLOYED (11): + The deployment has succeeded. + FAILED_TO_DEPLOY (12): + The deployment has failed. """ DEPLOYMENT_STAGE_UNSPECIFIED = 0 @@ -66,6 +70,8 @@ class DeploymentStage(proto.Enum): STARTING_MODEL_SERVER = 3 FINISHING_UP = 4 DEPLOYMENT_TERMINATED = 10 + SUCCESSFULLY_DEPLOYED = 11 + FAILED_TO_DEPLOY = 12 __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/aiplatform_v1beta1/types/feature_online_store.py b/google/cloud/aiplatform_v1beta1/types/feature_online_store.py index 38aaaeba40..c9e7533723 100644 --- a/google/cloud/aiplatform_v1beta1/types/feature_online_store.py +++ b/google/cloud/aiplatform_v1beta1/types/feature_online_store.py @@ -221,11 +221,11 @@ class BigtableMetadata(proto.Message): ) enable_direct_bigtable_access: bool = proto.Field( proto.BOOL, - number=2, + number=3, ) bigtable_metadata: "FeatureOnlineStore.Bigtable.BigtableMetadata" = proto.Field( proto.MESSAGE, - number=3, + number=4, message="FeatureOnlineStore.Bigtable.BigtableMetadata", ) diff --git a/google/cloud/aiplatform_v1beta1/types/feature_view.py b/google/cloud/aiplatform_v1beta1/types/feature_view.py index 3d3e216470..8127602f3e 100644 --- a/google/cloud/aiplatform_v1beta1/types/feature_view.py +++ b/google/cloud/aiplatform_v1beta1/types/feature_view.py @@ -680,7 +680,7 @@ class BigtableMetadata(proto.Message): ) bigtable_metadata: BigtableMetadata = proto.Field( proto.MESSAGE, - number=21, + number=22, message=BigtableMetadata, ) diff --git a/google/cloud/aiplatform_v1beta1/types/machine_resources.py b/google/cloud/aiplatform_v1beta1/types/machine_resources.py index 379a685dd6..4184838778 100644 --- a/google/cloud/aiplatform_v1beta1/types/machine_resources.py +++ b/google/cloud/aiplatform_v1beta1/types/machine_resources.py @@ -246,7 +246,7 @@ class ScaleToZeroSpec(proto.Message): [MinValue=300] (5 minutes) [MaxValue=28800] (8 hours) idle_scaledown_period (google.protobuf.duration_pb2.Duration): Optional. Duration of no traffic before scaling to zero. - [MinValue=3600] (5 minutes) [MaxValue=28800] (8 hours) + [MinValue=300] (5 minutes) [MaxValue=28800] (8 hours) """ min_scaleup_period: duration_pb2.Duration = proto.Field( diff --git a/google/cloud/aiplatform_v1beta1/types/notebook_software_config.py b/google/cloud/aiplatform_v1beta1/types/notebook_software_config.py index 06df2335f5..2e340b640d 100644 --- a/google/cloud/aiplatform_v1beta1/types/notebook_software_config.py +++ b/google/cloud/aiplatform_v1beta1/types/notebook_software_config.py @@ -33,29 +33,35 @@ class PostStartupScriptConfig(proto.Message): - r""" + r"""Post-startup script config. Attributes: post_startup_script (str): - + Optional. Post-startup script to run after + runtime is started. post_startup_script_url (str): - + Optional. Post-startup script url to + download. Example: https://bucket/script.sh post_startup_script_behavior (google.cloud.aiplatform_v1beta1.types.PostStartupScriptConfig.PostStartupScriptBehavior): - + Optional. Post-startup script behavior that + defines download and execution behavior. """ class PostStartupScriptBehavior(proto.Enum): - r""" + r"""Represents a notebook runtime post-startup script behavior. Values: POST_STARTUP_SCRIPT_BEHAVIOR_UNSPECIFIED (0): - No description available. + Unspecified post-startup script behavior. RUN_ONCE (1): - No description available. + Run the post-startup script only once, during + runtime creation. RUN_EVERY_START (2): - No description available. + Run the post-startup script after every + start. DOWNLOAD_AND_RUN_EVERY_START (3): - No description available. + After every start, download the post-startup + script from its source and run it. """ POST_STARTUP_SCRIPT_BEHAVIOR_UNSPECIFIED = 0 @@ -120,7 +126,7 @@ class NotebookSoftwareConfig(proto.Message): Optional. Environment variables to be passed to the container. Maximum limit is 100. post_startup_script_config (google.cloud.aiplatform_v1beta1.types.PostStartupScriptConfig): - + Optional. Post-startup script config. """ colab_image: "ColabImage" = proto.Field( diff --git a/google/cloud/aiplatform_v1beta1/types/prediction_service.py b/google/cloud/aiplatform_v1beta1/types/prediction_service.py index 5bce4ddc9c..dea6f9a146 100644 --- a/google/cloud/aiplatform_v1beta1/types/prediction_service.py +++ b/google/cloud/aiplatform_v1beta1/types/prediction_service.py @@ -20,10 +20,11 @@ import proto # type: ignore from google.api import httpbody_pb2 # type: ignore -from google.cloud.aiplatform_v1beta1.types import content +from google.cloud.aiplatform_v1beta1.types import content as gca_content from google.cloud.aiplatform_v1beta1.types import explanation from google.cloud.aiplatform_v1beta1.types import tool from google.cloud.aiplatform_v1beta1.types import types +from google.cloud.aiplatform_v1beta1.types import usage_metadata as gca_usage_metadata from google.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -57,6 +58,8 @@ "PredictLongRunningResponse", "PredictLongRunningMetadata", "GenerateVideoResponse", + "EmbedContentRequest", + "EmbedContentResponse", }, ) @@ -795,27 +798,27 @@ class CountTokensRequest(proto.Message): number=2, message=struct_pb2.Value, ) - contents: MutableSequence[content.Content] = proto.RepeatedField( + contents: MutableSequence[gca_content.Content] = proto.RepeatedField( proto.MESSAGE, number=4, - message=content.Content, + message=gca_content.Content, ) - system_instruction: content.Content = proto.Field( + system_instruction: gca_content.Content = proto.Field( proto.MESSAGE, number=5, optional=True, - message=content.Content, + message=gca_content.Content, ) tools: MutableSequence[tool.Tool] = proto.RepeatedField( proto.MESSAGE, number=6, message=tool.Tool, ) - generation_config: content.GenerationConfig = proto.Field( + generation_config: gca_content.GenerationConfig = proto.Field( proto.MESSAGE, number=7, optional=True, - message=content.GenerationConfig, + message=gca_content.GenerationConfig, ) @@ -843,11 +846,11 @@ class CountTokensResponse(proto.Message): proto.INT32, number=2, ) - prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + prompt_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=3, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) @@ -924,16 +927,16 @@ class GenerateContentRequest(proto.Message): proto.STRING, number=5, ) - contents: MutableSequence[content.Content] = proto.RepeatedField( + contents: MutableSequence[gca_content.Content] = proto.RepeatedField( proto.MESSAGE, number=2, - message=content.Content, + message=gca_content.Content, ) - system_instruction: content.Content = proto.Field( + system_instruction: gca_content.Content = proto.Field( proto.MESSAGE, number=8, optional=True, - message=content.Content, + message=gca_content.Content, ) cached_content: str = proto.Field( proto.STRING, @@ -954,20 +957,20 @@ class GenerateContentRequest(proto.Message): proto.STRING, number=10, ) - safety_settings: MutableSequence[content.SafetySetting] = proto.RepeatedField( + safety_settings: MutableSequence[gca_content.SafetySetting] = proto.RepeatedField( proto.MESSAGE, number=3, - message=content.SafetySetting, + message=gca_content.SafetySetting, ) - model_armor_config: content.ModelArmorConfig = proto.Field( + model_armor_config: gca_content.ModelArmorConfig = proto.Field( proto.MESSAGE, number=11, - message=content.ModelArmorConfig, + message=gca_content.ModelArmorConfig, ) - generation_config: content.GenerationConfig = proto.Field( + generation_config: gca_content.GenerationConfig = proto.Field( proto.MESSAGE, number=4, - message=content.GenerationConfig, + message=gca_content.GenerationConfig, ) @@ -1041,10 +1044,10 @@ class BlockedReason(proto.Enum): enum="GenerateContentResponse.PromptFeedback.BlockedReason", ) ) - safety_ratings: MutableSequence[content.SafetyRating] = proto.RepeatedField( + safety_ratings: MutableSequence[gca_content.SafetyRating] = proto.RepeatedField( proto.MESSAGE, number=2, - message=content.SafetyRating, + message=gca_content.SafetyRating, ) block_reason_message: str = proto.Field( proto.STRING, @@ -1101,32 +1104,32 @@ class UsageMetadata(proto.Message): proto.INT32, number=5, ) - prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + prompt_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=9, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) - cache_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + cache_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=10, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) - candidates_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + candidates_tokens_details: MutableSequence[gca_content.ModalityTokenCount] = ( proto.RepeatedField( proto.MESSAGE, number=11, - message=content.ModalityTokenCount, + message=gca_content.ModalityTokenCount, ) ) - candidates: MutableSequence[content.Candidate] = proto.RepeatedField( + candidates: MutableSequence[gca_content.Candidate] = proto.RepeatedField( proto.MESSAGE, number=2, - message=content.Candidate, + message=gca_content.Candidate, ) model_version: str = proto.Field( proto.STRING, @@ -1235,4 +1238,166 @@ class GenerateVideoResponse(proto.Message): ) +class EmbedContentRequest(proto.Message): + r"""Request message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + model (str): + Required. The name of the publisher model requested to serve + the prediction. Format: + ``projects/{project}/locations/{location}/publishers/*/models/*`` + + This field is a member of `oneof`_ ``_model``. + content (google.cloud.aiplatform_v1beta1.types.Content): + Required. Input content to be embedded. + Required. + + This field is a member of `oneof`_ ``_content``. + title (str): + Optional. An optional title for the text. + + This field is a member of `oneof`_ ``_title``. + task_type (google.cloud.aiplatform_v1beta1.types.EmbedContentRequest.EmbeddingTaskType): + Optional. The task type of the embedding. + + This field is a member of `oneof`_ ``_task_type``. + output_dimensionality (int): + Optional. Optional reduced dimension for the + output embedding. If set, excessive values in + the output embedding are truncated from the end. + + This field is a member of `oneof`_ ``_output_dimensionality``. + auto_truncate (bool): + Optional. Whether to silently truncate the + input content if it's longer than the maximum + sequence length. + + This field is a member of `oneof`_ ``_auto_truncate``. + """ + + class EmbeddingTaskType(proto.Enum): + r"""Represents a downstream task the embeddings will be used for. + + Values: + UNSPECIFIED (0): + Unset value, which will default to one of the + other enum values. + RETRIEVAL_QUERY (2): + Specifies the given text is a query in a + search/retrieval setting. + RETRIEVAL_DOCUMENT (3): + Specifies the given text is a document from + the corpus being searched. + SEMANTIC_SIMILARITY (4): + Specifies the given text will be used for + STS. + CLASSIFICATION (5): + Specifies that the given text will be + classified. + CLUSTERING (6): + Specifies that the embeddings will be used + for clustering. + QUESTION_ANSWERING (7): + Specifies that the embeddings will be used + for question answering. + FACT_VERIFICATION (8): + Specifies that the embeddings will be used + for fact verification. + CODE_RETRIEVAL_QUERY (9): + Specifies that the embeddings will be used + for code retrieval. + """ + + UNSPECIFIED = 0 + RETRIEVAL_QUERY = 2 + RETRIEVAL_DOCUMENT = 3 + SEMANTIC_SIMILARITY = 4 + CLASSIFICATION = 5 + CLUSTERING = 6 + QUESTION_ANSWERING = 7 + FACT_VERIFICATION = 8 + CODE_RETRIEVAL_QUERY = 9 + + model: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + content: gca_content.Content = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message=gca_content.Content, + ) + title: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + task_type: EmbeddingTaskType = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=EmbeddingTaskType, + ) + output_dimensionality: int = proto.Field( + proto.INT32, + number=6, + optional=True, + ) + auto_truncate: bool = proto.Field( + proto.BOOL, + number=7, + optional=True, + ) + + +class EmbedContentResponse(proto.Message): + r"""Response message for + [PredictionService.EmbedContent][google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent]. + + Attributes: + embedding (google.cloud.aiplatform_v1beta1.types.EmbedContentResponse.Embedding): + The embedding generated from the input + content. + usage_metadata (google.cloud.aiplatform_v1beta1.types.UsageMetadata): + Metadata about the response(s). + truncated (bool): + Whether the input content was truncated + before generating the embedding. + """ + + class Embedding(proto.Message): + r"""A list of floats representing an embedding. + + Attributes: + values (MutableSequence[float]): + Embedding vector values. + """ + + values: MutableSequence[float] = proto.RepeatedField( + proto.FLOAT, + number=1, + ) + + embedding: Embedding = proto.Field( + proto.MESSAGE, + number=1, + message=Embedding, + ) + usage_metadata: gca_usage_metadata.UsageMetadata = proto.Field( + proto.MESSAGE, + number=2, + message=gca_usage_metadata.UsageMetadata, + ) + truncated: bool = proto.Field( + proto.BOOL, + number=4, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/aiplatform_v1beta1/types/reasoning_engine.py b/google/cloud/aiplatform_v1beta1/types/reasoning_engine.py index 6c7a74a4ac..ab04198efe 100644 --- a/google/cloud/aiplatform_v1beta1/types/reasoning_engine.py +++ b/google/cloud/aiplatform_v1beta1/types/reasoning_engine.py @@ -94,9 +94,9 @@ class PackageSpec(proto.Message): Optional. The Cloud Storage URI of the ``requirements.txt`` file python_version (str): - Optional. The Python version. Currently - support 3.8, 3.9, 3.10, 3.11. If not specified, - default value is 3.10. + Optional. The Python version. Supported + values are 3.9, 3.10, 3.11, 3.12, 3.13. If not + specified, the default value is 3.10. """ pickle_object_gcs_uri: str = proto.Field( @@ -209,6 +209,11 @@ class DeploymentSpec(proto.Message): class SourceCodeSpec(proto.Message): r"""Specification for deploying from source code. + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: @@ -216,6 +221,11 @@ class SourceCodeSpec(proto.Message): Source code is provided directly in the request. + This field is a member of `oneof`_ ``source``. + developer_connect_source (google.cloud.aiplatform_v1beta1.types.ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectSource): + Source code is in a Git repository managed by + Developer Connect. + This field is a member of `oneof`_ ``source``. python_spec (google.cloud.aiplatform_v1beta1.types.ReasoningEngineSpec.SourceCodeSpec.PythonSpec): Configuration for a Python application. @@ -238,6 +248,57 @@ class InlineSource(proto.Message): number=1, ) + class DeveloperConnectConfig(proto.Message): + r"""Specifies the configuration for fetching source code from a + Git repository that is managed by Developer Connect. This + includes the repository, revision, and directory to use. + + Attributes: + git_repository_link (str): + Required. The Developer Connect Git repository link, + formatted as + ``projects/*/locations/*/connections/*/gitRepositoryLink/*``. + dir_ (str): + Required. Directory, relative to the source + root, in which to run the build. + revision (str): + Required. The revision to fetch from the Git + repository such as a branch, a tag, a commit + SHA, or any Git ref. + """ + + git_repository_link: str = proto.Field( + proto.STRING, + number=1, + ) + dir_: str = proto.Field( + proto.STRING, + number=2, + ) + revision: str = proto.Field( + proto.STRING, + number=3, + ) + + class DeveloperConnectSource(proto.Message): + r"""Specifies source code to be fetched from a Git repository + managed through the Developer Connect service. + + Attributes: + config (google.cloud.aiplatform_v1beta1.types.ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectConfig): + Required. The Developer Connect configuration + that defines the specific repository, revision, + and directory to use as the source code root. + """ + + config: "ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectConfig" = ( + proto.Field( + proto.MESSAGE, + number=1, + message="ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectConfig", + ) + ) + class PythonSpec(proto.Message): r"""Specification for running a Python application from source. @@ -288,6 +349,14 @@ class PythonSpec(proto.Message): oneof="source", message="ReasoningEngineSpec.SourceCodeSpec.InlineSource", ) + developer_connect_source: ( + "ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectSource" + ) = proto.Field( + proto.MESSAGE, + number=3, + oneof="source", + message="ReasoningEngineSpec.SourceCodeSpec.DeveloperConnectSource", + ) python_spec: "ReasoningEngineSpec.SourceCodeSpec.PythonSpec" = proto.Field( proto.MESSAGE, number=2, diff --git a/google/cloud/aiplatform_v1beta1/types/session.py b/google/cloud/aiplatform_v1beta1/types/session.py index 31ab47c669..1339bd5cad 100644 --- a/google/cloud/aiplatform_v1beta1/types/session.py +++ b/google/cloud/aiplatform_v1beta1/types/session.py @@ -274,9 +274,6 @@ class EventActions(proto.Message): Optional. Indicates that the event is updating an artifact. key is the filename, value is the version. - transfer_to_agent (bool): - Deprecated. If set, the event transfers to - the specified agent. escalate (bool): Optional. The agent is escalating to a higher level agent. @@ -307,10 +304,6 @@ class EventActions(proto.Message): proto.INT32, number=3, ) - transfer_to_agent: bool = proto.Field( - proto.BOOL, - number=5, - ) escalate: bool = proto.Field( proto.BOOL, number=6, diff --git a/google/cloud/aiplatform_v1beta1/types/session_service.py b/google/cloud/aiplatform_v1beta1/types/session_service.py index ad4e10e9f6..86d762f892 100644 --- a/google/cloud/aiplatform_v1beta1/types/session_service.py +++ b/google/cloud/aiplatform_v1beta1/types/session_service.py @@ -121,9 +121,9 @@ class ListSessionsRequest(proto.Message): call. filter (str): Optional. The standard list filter. Supported fields: \* - ``display_name`` + ``display_name`` \* ``user_id`` - Example: ``display_name=abc``. + Example: ``display_name="abc"``, ``user_id="123"``. order_by (str): Optional. A comma-separated list of fields to order by, sorted in ascending order. Use "desc" after a field name for @@ -256,6 +256,14 @@ class ListEventsRequest(proto.Message): timestamp is in RFC 3339 format) More detail in `AIP-160 `__. + order_by (str): + Optional. A comma-separated list of fields to order by, + sorted in ascending order. Use "desc" after a field name for + descending. Supported fields: + + - ``timestamp`` + + Example: ``timestamp desc``. """ parent: str = proto.Field( @@ -274,6 +282,10 @@ class ListEventsRequest(proto.Message): proto.STRING, number=4, ) + order_by: str = proto.Field( + proto.STRING, + number=5, + ) class ListEventsResponse(proto.Message): diff --git a/google/cloud/aiplatform_v1beta1/types/tool.py b/google/cloud/aiplatform_v1beta1/types/tool.py index 82be2fc989..8e21310e66 100644 --- a/google/cloud/aiplatform_v1beta1/types/tool.py +++ b/google/cloud/aiplatform_v1beta1/types/tool.py @@ -32,6 +32,9 @@ "ToolUseExample", "FunctionDeclaration", "FunctionCall", + "FunctionResponsePart", + "FunctionResponseBlob", + "FunctionResponseFileData", "FunctionResponse", "ExecutableCode", "CodeExecutionResult", @@ -190,6 +193,16 @@ class ComputerUse(proto.Message): Attributes: environment (google.cloud.aiplatform_v1beta1.types.Tool.ComputerUse.Environment): Required. The environment being operated. + excluded_predefined_functions (MutableSequence[str]): + Optional. By default, `predefined + functions `__ + are included in the final model call. Some of them can be + explicitly excluded from being automatically included. This + can serve two purposes: + + 1. Using a more restricted / different action space. + 2. Improving the definitions / instructions of predefined + functions. """ class Environment(proto.Enum): @@ -211,6 +224,10 @@ class Environment(proto.Enum): number=1, enum="Tool.ComputerUse.Environment", ) + excluded_predefined_functions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) function_declarations: MutableSequence["FunctionDeclaration"] = proto.RepeatedField( proto.MESSAGE, @@ -490,6 +507,123 @@ class FunctionCall(proto.Message): ) +class FunctionResponsePart(proto.Message): + r"""A datatype containing media that is part of a ``FunctionResponse`` + message. + + A ``FunctionResponsePart`` consists of data which has an associated + datatype. A ``FunctionResponsePart`` can only contain one of the + accepted types in ``FunctionResponsePart.data``. + + A ``FunctionResponsePart`` must have a fixed IANA MIME type + identifying the type and subtype of the media if the ``inline_data`` + field is filled with raw bytes. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + inline_data (google.cloud.aiplatform_v1beta1.types.FunctionResponseBlob): + Inline media bytes. + + This field is a member of `oneof`_ ``data``. + file_data (google.cloud.aiplatform_v1beta1.types.FunctionResponseFileData): + URI based data. + + This field is a member of `oneof`_ ``data``. + """ + + inline_data: "FunctionResponseBlob" = proto.Field( + proto.MESSAGE, + number=1, + oneof="data", + message="FunctionResponseBlob", + ) + file_data: "FunctionResponseFileData" = proto.Field( + proto.MESSAGE, + number=2, + oneof="data", + message="FunctionResponseFileData", + ) + + +class FunctionResponseBlob(proto.Message): + r"""Raw media bytes for function response. + + Text should not be sent as raw bytes, use the 'text' field. + + Attributes: + mime_type (str): + Required. The IANA standard MIME type of the + source data. + data (bytes): + Required. Raw bytes. + display_name (str): + Optional. Display name of the blob. + + Used to provide a label or filename to distinguish blobs. + + This field is only returned in PromptMessage for prompt + management. It is currently used in the Gemini + GenerateContent calls only when server side tools + (code_execution, google_search, and url_context) are + enabled. + """ + + mime_type: str = proto.Field( + proto.STRING, + number=1, + ) + data: bytes = proto.Field( + proto.BYTES, + number=2, + ) + display_name: str = proto.Field( + proto.STRING, + number=4, + ) + + +class FunctionResponseFileData(proto.Message): + r"""URI based data for function response. + + Attributes: + mime_type (str): + Required. The IANA standard MIME type of the + source data. + file_uri (str): + Required. URI. + display_name (str): + Optional. Display name of the file data. + + Used to provide a label or filename to distinguish file + datas. + + This field is only returned in PromptMessage for prompt + management. It is currently used in the Gemini + GenerateContent calls only when server side tools + (code_execution, google_search, and url_context) are + enabled. + """ + + mime_type: str = proto.Field( + proto.STRING, + number=1, + ) + file_uri: str = proto.Field( + proto.STRING, + number=2, + ) + display_name: str = proto.Field( + proto.STRING, + number=3, + ) + + class FunctionResponse(proto.Message): r"""The result output from a [FunctionCall] that contains a string representing the [FunctionDeclaration.name] and a structured JSON @@ -512,6 +646,9 @@ class FunctionResponse(proto.Message): details (if any). If "output" and "error" keys are not specified, then whole "response" is treated as function output. + parts (MutableSequence[google.cloud.aiplatform_v1beta1.types.FunctionResponsePart]): + Optional. Ordered ``Parts`` that constitute a function + response. Parts may have different IANA MIME types. """ id: str = proto.Field( @@ -527,6 +664,11 @@ class FunctionResponse(proto.Message): number=2, message=struct_pb2.Struct, ) + parts: MutableSequence["FunctionResponsePart"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="FunctionResponsePart", + ) class ExecutableCode(proto.Message): diff --git a/google/cloud/aiplatform_v1beta1/types/usage_metadata.py b/google/cloud/aiplatform_v1beta1/types/usage_metadata.py new file mode 100644 index 0000000000..7d62068076 --- /dev/null +++ b/google/cloud/aiplatform_v1beta1/types/usage_metadata.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +from google.cloud.aiplatform_v1beta1.types import content + + +__protobuf__ = proto.module( + package="google.cloud.aiplatform.v1beta1", + manifest={ + "UsageMetadata", + }, +) + + +class UsageMetadata(proto.Message): + r"""Usage metadata about the content generation request and + response. This message provides a detailed breakdown of token + usage and other relevant metrics. + + Attributes: + prompt_token_count (int): + The total number of tokens in the prompt. This includes any + text, images, or other media provided in the request. When + ``cached_content`` is set, this also includes the number of + tokens in the cached content. + candidates_token_count (int): + The total number of tokens in the generated + candidates. + total_token_count (int): + The total number of tokens for the entire request. This is + the sum of ``prompt_token_count``, + ``candidates_token_count``, ``tool_use_prompt_token_count``, + and ``thoughts_token_count``. + tool_use_prompt_token_count (int): + Output only. The number of tokens in the + results from tool executions, which are provided + back to the model as input, if applicable. + thoughts_token_count (int): + Output only. The number of tokens that were + part of the model's generated "thoughts" output, + if applicable. + cached_content_token_count (int): + Output only. The number of tokens in the + cached content that was used for this request. + prompt_tokens_details (MutableSequence[google.cloud.aiplatform_v1beta1.types.ModalityTokenCount]): + Output only. A detailed breakdown of the + token count for each modality in the prompt. + cache_tokens_details (MutableSequence[google.cloud.aiplatform_v1beta1.types.ModalityTokenCount]): + Output only. A detailed breakdown of the + token count for each modality in the cached + content. + candidates_tokens_details (MutableSequence[google.cloud.aiplatform_v1beta1.types.ModalityTokenCount]): + Output only. A detailed breakdown of the + token count for each modality in the generated + candidates. + tool_use_prompt_tokens_details (MutableSequence[google.cloud.aiplatform_v1beta1.types.ModalityTokenCount]): + Output only. A detailed breakdown by modality + of the token counts from the results of tool + executions, which are provided back to the model + as input. + traffic_type (google.cloud.aiplatform_v1beta1.types.UsageMetadata.TrafficType): + Output only. The traffic type for this + request. + """ + + class TrafficType(proto.Enum): + r"""The type of traffic that this request was processed with, + indicating which quota gets consumed. + + Values: + TRAFFIC_TYPE_UNSPECIFIED (0): + Unspecified request traffic type. + ON_DEMAND (1): + Type for Pay-As-You-Go traffic. + PROVISIONED_THROUGHPUT (2): + Type for Provisioned Throughput traffic. + """ + + TRAFFIC_TYPE_UNSPECIFIED = 0 + ON_DEMAND = 1 + PROVISIONED_THROUGHPUT = 2 + + prompt_token_count: int = proto.Field( + proto.INT32, + number=1, + ) + candidates_token_count: int = proto.Field( + proto.INT32, + number=2, + ) + total_token_count: int = proto.Field( + proto.INT32, + number=3, + ) + tool_use_prompt_token_count: int = proto.Field( + proto.INT32, + number=13, + ) + thoughts_token_count: int = proto.Field( + proto.INT32, + number=14, + ) + cached_content_token_count: int = proto.Field( + proto.INT32, + number=5, + ) + prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=9, + message=content.ModalityTokenCount, + ) + ) + cache_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=10, + message=content.ModalityTokenCount, + ) + ) + candidates_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=11, + message=content.ModalityTokenCount, + ) + ) + tool_use_prompt_tokens_details: MutableSequence[content.ModalityTokenCount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=12, + message=content.ModalityTokenCount, + ) + ) + traffic_type: TrafficType = proto.Field( + proto.ENUM, + number=8, + enum=TrafficType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/samples/generated_samples/aiplatform_v1_generated_prediction_service_embed_content_async.py b/samples/generated_samples/aiplatform_v1_generated_prediction_service_embed_content_async.py new file mode 100644 index 0000000000..919c1243b1 --- /dev/null +++ b/samples/generated_samples/aiplatform_v1_generated_prediction_service_embed_content_async.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for EmbedContent +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-aiplatform + + +# [START aiplatform_v1_generated_PredictionService_EmbedContent_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import aiplatform_v1 + + +async def sample_embed_content(): + # Create a client + client = aiplatform_v1.PredictionServiceAsyncClient() + + # Initialize request argument(s) + request = aiplatform_v1.EmbedContentRequest( + ) + + # Make the request + response = await client.embed_content(request=request) + + # Handle the response + print(response) + +# [END aiplatform_v1_generated_PredictionService_EmbedContent_async] diff --git a/samples/generated_samples/aiplatform_v1_generated_prediction_service_embed_content_sync.py b/samples/generated_samples/aiplatform_v1_generated_prediction_service_embed_content_sync.py new file mode 100644 index 0000000000..174c624141 --- /dev/null +++ b/samples/generated_samples/aiplatform_v1_generated_prediction_service_embed_content_sync.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for EmbedContent +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-aiplatform + + +# [START aiplatform_v1_generated_PredictionService_EmbedContent_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import aiplatform_v1 + + +def sample_embed_content(): + # Create a client + client = aiplatform_v1.PredictionServiceClient() + + # Initialize request argument(s) + request = aiplatform_v1.EmbedContentRequest( + ) + + # Make the request + response = client.embed_content(request=request) + + # Handle the response + print(response) + +# [END aiplatform_v1_generated_PredictionService_EmbedContent_sync] diff --git a/samples/generated_samples/aiplatform_v1beta1_generated_prediction_service_embed_content_async.py b/samples/generated_samples/aiplatform_v1beta1_generated_prediction_service_embed_content_async.py new file mode 100644 index 0000000000..5e0e37b291 --- /dev/null +++ b/samples/generated_samples/aiplatform_v1beta1_generated_prediction_service_embed_content_async.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for EmbedContent +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-aiplatform + + +# [START aiplatform_v1beta1_generated_PredictionService_EmbedContent_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import aiplatform_v1beta1 + + +async def sample_embed_content(): + # Create a client + client = aiplatform_v1beta1.PredictionServiceAsyncClient() + + # Initialize request argument(s) + request = aiplatform_v1beta1.EmbedContentRequest( + ) + + # Make the request + response = await client.embed_content(request=request) + + # Handle the response + print(response) + +# [END aiplatform_v1beta1_generated_PredictionService_EmbedContent_async] diff --git a/samples/generated_samples/aiplatform_v1beta1_generated_prediction_service_embed_content_sync.py b/samples/generated_samples/aiplatform_v1beta1_generated_prediction_service_embed_content_sync.py new file mode 100644 index 0000000000..33fa3b3110 --- /dev/null +++ b/samples/generated_samples/aiplatform_v1beta1_generated_prediction_service_embed_content_sync.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for EmbedContent +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-aiplatform + + +# [START aiplatform_v1beta1_generated_PredictionService_EmbedContent_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import aiplatform_v1beta1 + + +def sample_embed_content(): + # Create a client + client = aiplatform_v1beta1.PredictionServiceClient() + + # Initialize request argument(s) + request = aiplatform_v1beta1.EmbedContentRequest( + ) + + # Make the request + response = client.embed_content(request=request) + + # Handle the response + print(response) + +# [END aiplatform_v1beta1_generated_PredictionService_EmbedContent_sync] diff --git a/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1.json b/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1.json index 836c774580..35d3487b2b 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-aiplatform", - "version": "1.128.0" + "version": "0.0.0" }, "snippets": [ { @@ -39860,6 +39860,175 @@ ], "title": "aiplatform_v1_generated_prediction_service_direct_raw_predict_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.aiplatform_v1.PredictionServiceAsyncClient", + "shortName": "PredictionServiceAsyncClient" + }, + "fullName": "google.cloud.aiplatform_v1.PredictionServiceAsyncClient.embed_content", + "method": { + "fullName": "google.cloud.aiplatform.v1.PredictionService.EmbedContent", + "service": { + "fullName": "google.cloud.aiplatform.v1.PredictionService", + "shortName": "PredictionService" + }, + "shortName": "EmbedContent" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.aiplatform_v1.types.EmbedContentRequest" + }, + { + "name": "model", + "type": "str" + }, + { + "name": "content", + "type": "google.cloud.aiplatform_v1.types.Content" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.aiplatform_v1.types.EmbedContentResponse", + "shortName": "embed_content" + }, + "description": "Sample for EmbedContent", + "file": "aiplatform_v1_generated_prediction_service_embed_content_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "aiplatform_v1_generated_PredictionService_EmbedContent_async", + "segments": [ + { + "end": 50, + "start": 27, + "type": "FULL" + }, + { + "end": 50, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 44, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "aiplatform_v1_generated_prediction_service_embed_content_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.aiplatform_v1.PredictionServiceClient", + "shortName": "PredictionServiceClient" + }, + "fullName": "google.cloud.aiplatform_v1.PredictionServiceClient.embed_content", + "method": { + "fullName": "google.cloud.aiplatform.v1.PredictionService.EmbedContent", + "service": { + "fullName": "google.cloud.aiplatform.v1.PredictionService", + "shortName": "PredictionService" + }, + "shortName": "EmbedContent" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.aiplatform_v1.types.EmbedContentRequest" + }, + { + "name": "model", + "type": "str" + }, + { + "name": "content", + "type": "google.cloud.aiplatform_v1.types.Content" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.aiplatform_v1.types.EmbedContentResponse", + "shortName": "embed_content" + }, + "description": "Sample for EmbedContent", + "file": "aiplatform_v1_generated_prediction_service_embed_content_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "aiplatform_v1_generated_PredictionService_EmbedContent_sync", + "segments": [ + { + "end": 50, + "start": 27, + "type": "FULL" + }, + { + "end": 50, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 44, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "aiplatform_v1_generated_prediction_service_embed_content_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1beta1.json b/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1beta1.json index 7c0a83a9a3..2a9e00ef91 100644 --- a/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1beta1.json +++ b/samples/generated_samples/snippet_metadata_google.cloud.aiplatform.v1beta1.json @@ -8,7 +8,7 @@ ], "language": "PYTHON", "name": "google-cloud-aiplatform", - "version": "1.128.0" + "version": "0.0.0" }, "snippets": [ { @@ -48771,6 +48771,175 @@ ], "title": "aiplatform_v1beta1_generated_prediction_service_direct_raw_predict_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.aiplatform_v1beta1.PredictionServiceAsyncClient", + "shortName": "PredictionServiceAsyncClient" + }, + "fullName": "google.cloud.aiplatform_v1beta1.PredictionServiceAsyncClient.embed_content", + "method": { + "fullName": "google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent", + "service": { + "fullName": "google.cloud.aiplatform.v1beta1.PredictionService", + "shortName": "PredictionService" + }, + "shortName": "EmbedContent" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.aiplatform_v1beta1.types.EmbedContentRequest" + }, + { + "name": "model", + "type": "str" + }, + { + "name": "content", + "type": "google.cloud.aiplatform_v1beta1.types.Content" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.aiplatform_v1beta1.types.EmbedContentResponse", + "shortName": "embed_content" + }, + "description": "Sample for EmbedContent", + "file": "aiplatform_v1beta1_generated_prediction_service_embed_content_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "aiplatform_v1beta1_generated_PredictionService_EmbedContent_async", + "segments": [ + { + "end": 50, + "start": 27, + "type": "FULL" + }, + { + "end": 50, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 44, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "aiplatform_v1beta1_generated_prediction_service_embed_content_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.aiplatform_v1beta1.PredictionServiceClient", + "shortName": "PredictionServiceClient" + }, + "fullName": "google.cloud.aiplatform_v1beta1.PredictionServiceClient.embed_content", + "method": { + "fullName": "google.cloud.aiplatform.v1beta1.PredictionService.EmbedContent", + "service": { + "fullName": "google.cloud.aiplatform.v1beta1.PredictionService", + "shortName": "PredictionService" + }, + "shortName": "EmbedContent" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.aiplatform_v1beta1.types.EmbedContentRequest" + }, + { + "name": "model", + "type": "str" + }, + { + "name": "content", + "type": "google.cloud.aiplatform_v1beta1.types.Content" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.aiplatform_v1beta1.types.EmbedContentResponse", + "shortName": "embed_content" + }, + "description": "Sample for EmbedContent", + "file": "aiplatform_v1beta1_generated_prediction_service_embed_content_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "aiplatform_v1beta1_generated_PredictionService_EmbedContent_sync", + "segments": [ + { + "end": 50, + "start": 27, + "type": "FULL" + }, + { + "end": 50, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 44, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "aiplatform_v1beta1_generated_prediction_service_embed_content_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/tests/unit/gapic/aiplatform_v1/test_deployment_resource_pool_service.py b/tests/unit/gapic/aiplatform_v1/test_deployment_resource_pool_service.py index b27d95d38d..2a8b69c0b5 100644 --- a/tests/unit/gapic/aiplatform_v1/test_deployment_resource_pool_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_deployment_resource_pool_service.py @@ -6109,6 +6109,7 @@ def test_update_deployment_resource_pool_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7923,6 +7924,7 @@ async def test_update_deployment_resource_pool_rest_asyncio_call_success(request "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_endpoint_service.py b/tests/unit/gapic/aiplatform_v1/test_endpoint_service.py index ed70d5a2a3..598514d2b3 100644 --- a/tests/unit/gapic/aiplatform_v1/test_endpoint_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_endpoint_service.py @@ -7010,6 +7010,7 @@ def test_create_endpoint_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7638,6 +7639,7 @@ def test_update_endpoint_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -9481,6 +9483,7 @@ async def test_create_endpoint_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -10166,6 +10169,7 @@ async def test_update_endpoint_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_gen_ai_cache_service.py b/tests/unit/gapic/aiplatform_v1/test_gen_ai_cache_service.py index 5a0da4a120..399d967c2e 100644 --- a/tests/unit/gapic/aiplatform_v1/test_gen_ai_cache_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_gen_ai_cache_service.py @@ -4618,7 +4618,24 @@ def test_create_cached_content_rest_call_success(request_type): "file_uri": "file_uri_value", }, "function_call": {"name": "name_value", "args": {"fields": {}}}, - "function_response": {"name": "name_value", "response": {}}, + "function_response": { + "name": "name_value", + "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], + }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, "thought": True, @@ -4733,7 +4750,13 @@ def test_create_cached_content_rest_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { @@ -5125,7 +5148,24 @@ def test_update_cached_content_rest_call_success(request_type): "file_uri": "file_uri_value", }, "function_call": {"name": "name_value", "args": {"fields": {}}}, - "function_response": {"name": "name_value", "response": {}}, + "function_response": { + "name": "name_value", + "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], + }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, "thought": True, @@ -5240,7 +5280,13 @@ def test_update_cached_content_rest_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { @@ -6494,7 +6540,24 @@ async def test_create_cached_content_rest_asyncio_call_success(request_type): "file_uri": "file_uri_value", }, "function_call": {"name": "name_value", "args": {"fields": {}}}, - "function_response": {"name": "name_value", "response": {}}, + "function_response": { + "name": "name_value", + "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], + }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, "thought": True, @@ -6609,7 +6672,13 @@ async def test_create_cached_content_rest_asyncio_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { @@ -7037,7 +7106,24 @@ async def test_update_cached_content_rest_asyncio_call_success(request_type): "file_uri": "file_uri_value", }, "function_call": {"name": "name_value", "args": {"fields": {}}}, - "function_response": {"name": "name_value", "response": {}}, + "function_response": { + "name": "name_value", + "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], + }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, "thought": True, @@ -7152,7 +7238,13 @@ async def test_update_cached_content_rest_asyncio_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { diff --git a/tests/unit/gapic/aiplatform_v1/test_gen_ai_tuning_service.py b/tests/unit/gapic/aiplatform_v1/test_gen_ai_tuning_service.py index 21e5de6937..bd8d2f1f72 100644 --- a/tests/unit/gapic/aiplatform_v1/test_gen_ai_tuning_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_gen_ai_tuning_service.py @@ -4533,6 +4533,11 @@ def test_create_tuning_job_rest_call_success(request_type): request_init = {"parent": "projects/sample1/locations/sample2"} request_init["tuning_job"] = { "base_model": "base_model_value", + "pre_tuned_model": { + "tuned_model_name": "tuned_model_name_value", + "checkpoint_id": "checkpoint_id_value", + "base_model": "base_model_value", + }, "supervised_tuning_spec": { "training_dataset_uri": "training_dataset_uri_value", "validation_dataset_uri": "validation_dataset_uri_value", @@ -4616,6 +4621,20 @@ def test_create_tuning_job_rest_call_success(request_type): "function_response": { "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": { "language": 1, @@ -6134,6 +6153,11 @@ async def test_create_tuning_job_rest_asyncio_call_success(request_type): request_init = {"parent": "projects/sample1/locations/sample2"} request_init["tuning_job"] = { "base_model": "base_model_value", + "pre_tuned_model": { + "tuned_model_name": "tuned_model_name_value", + "checkpoint_id": "checkpoint_id_value", + "base_model": "base_model_value", + }, "supervised_tuning_spec": { "training_dataset_uri": "training_dataset_uri_value", "validation_dataset_uri": "validation_dataset_uri_value", @@ -6217,6 +6241,20 @@ async def test_create_tuning_job_rest_asyncio_call_success(request_type): "function_response": { "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": { "language": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_index_endpoint_service.py b/tests/unit/gapic/aiplatform_v1/test_index_endpoint_service.py index 79535ab5a3..e39a5514a3 100644 --- a/tests/unit/gapic/aiplatform_v1/test_index_endpoint_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_index_endpoint_service.py @@ -6471,6 +6471,7 @@ def test_create_index_endpoint_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7057,6 +7058,7 @@ def test_update_index_endpoint_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7754,6 +7756,7 @@ def test_mutate_deployed_index_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -8861,6 +8864,7 @@ async def test_create_index_endpoint_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -9496,6 +9500,7 @@ async def test_update_index_endpoint_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -10259,6 +10264,7 @@ async def test_mutate_deployed_index_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_job_service.py b/tests/unit/gapic/aiplatform_v1/test_job_service.py index 685ab4f40b..9cc8943822 100644 --- a/tests/unit/gapic/aiplatform_v1/test_job_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_job_service.py @@ -24399,6 +24399,7 @@ def test_create_custom_job_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -26057,6 +26058,7 @@ def test_create_hyperparameter_tuning_job_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -26943,6 +26945,7 @@ def test_create_nas_job_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -28084,6 +28087,7 @@ def test_create_batch_prediction_job_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -31833,6 +31837,7 @@ async def test_create_custom_job_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -33656,6 +33661,7 @@ async def test_create_hyperparameter_tuning_job_rest_asyncio_call_success(reques "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -34640,6 +34646,7 @@ async def test_create_nas_job_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -35902,6 +35909,7 @@ async def test_create_batch_prediction_job_rest_asyncio_call_success(request_typ "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_notebook_service.py b/tests/unit/gapic/aiplatform_v1/test_notebook_service.py index 463536f05b..7f10f2dee6 100644 --- a/tests/unit/gapic/aiplatform_v1/test_notebook_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_notebook_service.py @@ -11938,6 +11938,7 @@ def test_create_notebook_runtime_template_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -12617,6 +12618,7 @@ def test_update_notebook_runtime_template_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -13832,6 +13834,7 @@ def test_create_notebook_execution_job_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -15510,6 +15513,7 @@ async def test_create_notebook_runtime_template_rest_asyncio_call_success(reques "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -16272,6 +16276,7 @@ async def test_update_notebook_runtime_template_rest_asyncio_call_success(reques "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -17633,6 +17638,7 @@ async def test_create_notebook_execution_job_rest_asyncio_call_success(request_t "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_persistent_resource_service.py b/tests/unit/gapic/aiplatform_v1/test_persistent_resource_service.py index bee6cd7798..0031444d89 100644 --- a/tests/unit/gapic/aiplatform_v1/test_persistent_resource_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_persistent_resource_service.py @@ -5300,6 +5300,7 @@ def test_create_persistent_resource_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -6006,6 +6007,7 @@ def test_update_persistent_resource_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7213,6 +7215,7 @@ async def test_create_persistent_resource_rest_asyncio_call_success(request_type "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7983,6 +7986,7 @@ async def test_update_persistent_resource_rest_asyncio_call_success(request_type "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1/test_prediction_service.py b/tests/unit/gapic/aiplatform_v1/test_prediction_service.py index 03256746a8..dffa3f994f 100644 --- a/tests/unit/gapic/aiplatform_v1/test_prediction_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_prediction_service.py @@ -71,12 +71,14 @@ ) from google.cloud.aiplatform_v1.services.prediction_service import transports from google.cloud.aiplatform_v1.types import content +from google.cloud.aiplatform_v1.types import content as gca_content from google.cloud.aiplatform_v1.types import explanation from google.cloud.aiplatform_v1.types import io from google.cloud.aiplatform_v1.types import openapi from google.cloud.aiplatform_v1.types import prediction_service from google.cloud.aiplatform_v1.types import tool from google.cloud.aiplatform_v1.types import types +from google.cloud.aiplatform_v1.types import usage_metadata from google.cloud.location import locations_pb2 from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import options_pb2 # type: ignore @@ -4497,6 +4499,341 @@ async def test_stream_generate_content_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + prediction_service.EmbedContentRequest, + dict, + ], +) +def test_embed_content(request_type, transport: str = "grpc"): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = prediction_service.EmbedContentResponse( + truncated=True, + ) + response = client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = prediction_service.EmbedContentRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True + + +def test_embed_content_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = prediction_service.EmbedContentRequest( + model="model_value", + title="title_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.embed_content(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == prediction_service.EmbedContentRequest( + model="model_value", + title="title_value", + ) + + +def test_embed_content_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.embed_content in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.embed_content] = mock_rpc + request = {} + client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.embed_content(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_embed_content_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.embed_content + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.embed_content + ] = mock_rpc + + request = {} + await client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.embed_content(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_embed_content_async( + transport: str = "grpc_asyncio", request_type=prediction_service.EmbedContentRequest +): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse( + truncated=True, + ) + ) + response = await client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = prediction_service.EmbedContentRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True + + +@pytest.mark.asyncio +async def test_embed_content_async_from_dict(): + await test_embed_content_async(request_type=dict) + + +def test_embed_content_field_headers(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = prediction_service.EmbedContentRequest() + + request.model = "model_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value = prediction_service.EmbedContentResponse() + client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "model=model_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_embed_content_field_headers_async(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = prediction_service.EmbedContentRequest() + + request.model = "model_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse() + ) + await client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "model=model_value", + ) in kw["metadata"] + + +def test_embed_content_flattened(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = prediction_service.EmbedContentResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.embed_content( + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].model + mock_val = "model_value" + assert arg == mock_val + arg = args[0].content + mock_val = gca_content.Content(role="role_value") + assert arg == mock_val + + +def test_embed_content_flattened_error(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.embed_content( + prediction_service.EmbedContentRequest(), + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + +@pytest.mark.asyncio +async def test_embed_content_flattened_async(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = prediction_service.EmbedContentResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.embed_content( + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].model + mock_val = "model_value" + assert arg == mock_val + arg = args[0].content + mock_val = gca_content.Content(role="role_value") + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_embed_content_flattened_error_async(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.embed_content( + prediction_service.EmbedContentRequest(), + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + def test_predict_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -6063,6 +6400,104 @@ def test_stream_generate_content_rest_flattened_error(transport: str = "rest"): ) +def test_embed_content_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.embed_content in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.embed_content] = mock_rpc + + request = {} + client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.embed_content(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_embed_content_rest_flattened(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = prediction_service.EmbedContentResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } + + # get truthy value for each flattened field + mock_args = dict( + model="model_value", + content=gca_content.Content(role="role_value"), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = prediction_service.EmbedContentResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.embed_content(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1/{model=projects/*/locations/*/publishers/*/models/*}:embedContent" + % client.transport._host, + args[1], + ) + + +def test_embed_content_rest_flattened_error(transport: str = "rest"): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.embed_content( + prediction_service.EmbedContentRequest(), + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + def test_stream_direct_predict_rest_error(): client = PredictionServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" @@ -6418,6 +6853,27 @@ def test_stream_generate_content_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_embed_content_empty_call_grpc(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value = prediction_service.EmbedContentResponse() + client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_transport_kind_grpc_asyncio(): transport = PredictionServiceAsyncClient.get_transport_class("grpc_asyncio")( credentials=async_anonymous_credentials() @@ -6681,6 +7137,33 @@ async def test_stream_generate_content_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_embed_content_empty_call_grpc_asyncio(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse( + truncated=True, + ) + ) + await client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_transport_kind_rest(): transport = PredictionServiceClient.get_transport_class("rest")( credentials=ga_credentials.AnonymousCredentials() @@ -7608,13 +8091,145 @@ def test_explain_rest_interceptors(null_interceptor): ) as post, mock.patch.object( transports.PredictionServiceRestInterceptor, "post_explain_with_metadata" ) as post_with_metadata, mock.patch.object( - transports.PredictionServiceRestInterceptor, "pre_explain" + transports.PredictionServiceRestInterceptor, "pre_explain" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = prediction_service.ExplainRequest.pb( + prediction_service.ExplainRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = prediction_service.ExplainResponse.to_json( + prediction_service.ExplainResponse() + ) + req.return_value.content = return_value + + request = prediction_service.ExplainRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = prediction_service.ExplainResponse() + post_with_metadata.return_value = prediction_service.ExplainResponse(), metadata + + client.explain( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + +def test_generate_content_rest_bad_request( + request_type=prediction_service.GenerateContentRequest, +): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"model": "projects/sample1/locations/sample2/endpoints/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.generate_content(request) + + +@pytest.mark.parametrize( + "request_type", + [ + prediction_service.GenerateContentRequest, + dict, + ], +) +def test_generate_content_rest_call_success(request_type): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"model": "projects/sample1/locations/sample2/endpoints/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = prediction_service.GenerateContentResponse( + model_version="model_version_value", + response_id="response_id_value", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = prediction_service.GenerateContentResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.generate_content(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.GenerateContentResponse) + assert response.model_version == "model_version_value" + assert response.response_id == "response_id_value" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_generate_content_rest_interceptors(null_interceptor): + transport = transports.PredictionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=( + None if null_interceptor else transports.PredictionServiceRestInterceptor() + ), + ) + client = PredictionServiceClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.PredictionServiceRestInterceptor, "post_generate_content" + ) as post, mock.patch.object( + transports.PredictionServiceRestInterceptor, + "post_generate_content_with_metadata", + ) as post_with_metadata, mock.patch.object( + transports.PredictionServiceRestInterceptor, "pre_generate_content" ) as pre: pre.assert_not_called() post.assert_not_called() post_with_metadata.assert_not_called() - pb_message = prediction_service.ExplainRequest.pb( - prediction_service.ExplainRequest() + pb_message = prediction_service.GenerateContentRequest.pb( + prediction_service.GenerateContentRequest() ) transcode.return_value = { "method": "post", @@ -7626,21 +8241,24 @@ def test_explain_rest_interceptors(null_interceptor): req.return_value = mock.Mock() req.return_value.status_code = 200 req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - return_value = prediction_service.ExplainResponse.to_json( - prediction_service.ExplainResponse() + return_value = prediction_service.GenerateContentResponse.to_json( + prediction_service.GenerateContentResponse() ) req.return_value.content = return_value - request = prediction_service.ExplainRequest() + request = prediction_service.GenerateContentRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = prediction_service.ExplainResponse() - post_with_metadata.return_value = prediction_service.ExplainResponse(), metadata + post.return_value = prediction_service.GenerateContentResponse() + post_with_metadata.return_value = ( + prediction_service.GenerateContentResponse(), + metadata, + ) - client.explain( + client.generate_content( request, metadata=[ ("key", "val"), @@ -7653,7 +8271,7 @@ def test_explain_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() -def test_generate_content_rest_bad_request( +def test_stream_generate_content_rest_bad_request( request_type=prediction_service.GenerateContentRequest, ): client = PredictionServiceClient( @@ -7675,7 +8293,7 @@ def test_generate_content_rest_bad_request( response_value.request = mock.Mock() req.return_value = response_value req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - client.generate_content(request) + client.stream_generate_content(request) @pytest.mark.parametrize( @@ -7685,7 +8303,7 @@ def test_generate_content_rest_bad_request( dict, ], ) -def test_generate_content_rest_call_success(request_type): +def test_stream_generate_content_rest_call_success(request_type): client = PredictionServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -7709,10 +8327,14 @@ def test_generate_content_rest_call_success(request_type): # Convert return value to protobuf type return_value = prediction_service.GenerateContentResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) - response_value.content = json_return_value.encode("UTF-8") + json_return_value = "[{}]".format(json_return_value) + response_value.iter_content = mock.Mock(return_value=iter(json_return_value)) req.return_value = response_value req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - response = client.generate_content(request) + response = client.stream_generate_content(request) + + assert isinstance(response, Iterable) + response = next(response) # Establish that the response is the type that we expect. assert isinstance(response, prediction_service.GenerateContentResponse) @@ -7721,7 +8343,7 @@ def test_generate_content_rest_call_success(request_type): @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_generate_content_rest_interceptors(null_interceptor): +def test_stream_generate_content_rest_interceptors(null_interceptor): transport = transports.PredictionServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=( @@ -7735,12 +8357,12 @@ def test_generate_content_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.PredictionServiceRestInterceptor, "post_generate_content" + transports.PredictionServiceRestInterceptor, "post_stream_generate_content" ) as post, mock.patch.object( transports.PredictionServiceRestInterceptor, - "post_generate_content_with_metadata", + "post_stream_generate_content_with_metadata", ) as post_with_metadata, mock.patch.object( - transports.PredictionServiceRestInterceptor, "pre_generate_content" + transports.PredictionServiceRestInterceptor, "pre_stream_generate_content" ) as pre: pre.assert_not_called() post.assert_not_called() @@ -7761,7 +8383,7 @@ def test_generate_content_rest_interceptors(null_interceptor): return_value = prediction_service.GenerateContentResponse.to_json( prediction_service.GenerateContentResponse() ) - req.return_value.content = return_value + req.return_value.iter_content = mock.Mock(return_value=iter(return_value)) request = prediction_service.GenerateContentRequest() metadata = [ @@ -7775,7 +8397,7 @@ def test_generate_content_rest_interceptors(null_interceptor): metadata, ) - client.generate_content( + client.stream_generate_content( request, metadata=[ ("key", "val"), @@ -7788,14 +8410,16 @@ def test_generate_content_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() -def test_stream_generate_content_rest_bad_request( - request_type=prediction_service.GenerateContentRequest, +def test_embed_content_rest_bad_request( + request_type=prediction_service.EmbedContentRequest, ): client = PredictionServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) # send a request that will satisfy transcoding - request_init = {"model": "projects/sample1/locations/sample2/endpoints/sample3"} + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -7810,31 +8434,32 @@ def test_stream_generate_content_rest_bad_request( response_value.request = mock.Mock() req.return_value = response_value req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - client.stream_generate_content(request) + client.embed_content(request) @pytest.mark.parametrize( "request_type", [ - prediction_service.GenerateContentRequest, + prediction_service.EmbedContentRequest, dict, ], ) -def test_stream_generate_content_rest_call_success(request_type): +def test_embed_content_rest_call_success(request_type): client = PredictionServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) # send a request that will satisfy transcoding - request_init = {"model": "projects/sample1/locations/sample2/endpoints/sample3"} + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = prediction_service.GenerateContentResponse( - model_version="model_version_value", - response_id="response_id_value", + return_value = prediction_service.EmbedContentResponse( + truncated=True, ) # Wrap the value into a proper Response obj @@ -7842,25 +8467,20 @@ def test_stream_generate_content_rest_call_success(request_type): response_value.status_code = 200 # Convert return value to protobuf type - return_value = prediction_service.GenerateContentResponse.pb(return_value) + return_value = prediction_service.EmbedContentResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) - json_return_value = "[{}]".format(json_return_value) - response_value.iter_content = mock.Mock(return_value=iter(json_return_value)) + response_value.content = json_return_value.encode("UTF-8") req.return_value = response_value req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - response = client.stream_generate_content(request) - - assert isinstance(response, Iterable) - response = next(response) + response = client.embed_content(request) # Establish that the response is the type that we expect. - assert isinstance(response, prediction_service.GenerateContentResponse) - assert response.model_version == "model_version_value" - assert response.response_id == "response_id_value" + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_stream_generate_content_rest_interceptors(null_interceptor): +def test_embed_content_rest_interceptors(null_interceptor): transport = transports.PredictionServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=( @@ -7874,18 +8494,17 @@ def test_stream_generate_content_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.PredictionServiceRestInterceptor, "post_stream_generate_content" + transports.PredictionServiceRestInterceptor, "post_embed_content" ) as post, mock.patch.object( - transports.PredictionServiceRestInterceptor, - "post_stream_generate_content_with_metadata", + transports.PredictionServiceRestInterceptor, "post_embed_content_with_metadata" ) as post_with_metadata, mock.patch.object( - transports.PredictionServiceRestInterceptor, "pre_stream_generate_content" + transports.PredictionServiceRestInterceptor, "pre_embed_content" ) as pre: pre.assert_not_called() post.assert_not_called() post_with_metadata.assert_not_called() - pb_message = prediction_service.GenerateContentRequest.pb( - prediction_service.GenerateContentRequest() + pb_message = prediction_service.EmbedContentRequest.pb( + prediction_service.EmbedContentRequest() ) transcode.return_value = { "method": "post", @@ -7897,24 +8516,24 @@ def test_stream_generate_content_rest_interceptors(null_interceptor): req.return_value = mock.Mock() req.return_value.status_code = 200 req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - return_value = prediction_service.GenerateContentResponse.to_json( - prediction_service.GenerateContentResponse() + return_value = prediction_service.EmbedContentResponse.to_json( + prediction_service.EmbedContentResponse() ) - req.return_value.iter_content = mock.Mock(return_value=iter(return_value)) + req.return_value.content = return_value - request = prediction_service.GenerateContentRequest() + request = prediction_service.EmbedContentRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = prediction_service.GenerateContentResponse() + post.return_value = prediction_service.EmbedContentResponse() post_with_metadata.return_value = ( - prediction_service.GenerateContentResponse(), + prediction_service.EmbedContentResponse(), metadata, ) - client.stream_generate_content( + client.embed_content( request, metadata=[ ("key", "val"), @@ -8747,6 +9366,26 @@ def test_stream_generate_content_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_embed_content_empty_call_rest(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_transport_kind_rest_asyncio(): if not HAS_ASYNC_REST_EXTRA: pytest.skip( @@ -10180,6 +10819,161 @@ async def test_stream_generate_content_rest_asyncio_interceptors(null_intercepto post_with_metadata.assert_called_once() +@pytest.mark.asyncio +async def test_embed_content_rest_asyncio_bad_request( + request_type=prediction_service.EmbedContentRequest, +): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), transport="rest_asyncio" + ) + # send a request that will satisfy transcoding + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(AsyncAuthorizedSession, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.read = mock.AsyncMock(return_value=b"{}") + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + await client.embed_content(request) + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + prediction_service.EmbedContentRequest, + dict, + ], +) +async def test_embed_content_rest_asyncio_call_success(request_type): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), transport="rest_asyncio" + ) + + # send a request that will satisfy transcoding + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = prediction_service.EmbedContentResponse( + truncated=True, + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = prediction_service.EmbedContentResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.read = mock.AsyncMock( + return_value=json_return_value.encode("UTF-8") + ) + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = await client.embed_content(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True + + +@pytest.mark.asyncio +@pytest.mark.parametrize("null_interceptor", [True, False]) +async def test_embed_content_rest_asyncio_interceptors(null_interceptor): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + transport = transports.AsyncPredictionServiceRestTransport( + credentials=async_anonymous_credentials(), + interceptor=( + None + if null_interceptor + else transports.AsyncPredictionServiceRestInterceptor() + ), + ) + client = PredictionServiceAsyncClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.AsyncPredictionServiceRestInterceptor, "post_embed_content" + ) as post, mock.patch.object( + transports.AsyncPredictionServiceRestInterceptor, + "post_embed_content_with_metadata", + ) as post_with_metadata, mock.patch.object( + transports.AsyncPredictionServiceRestInterceptor, "pre_embed_content" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = prediction_service.EmbedContentRequest.pb( + prediction_service.EmbedContentRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = prediction_service.EmbedContentResponse.to_json( + prediction_service.EmbedContentResponse() + ) + req.return_value.read = mock.AsyncMock(return_value=return_value) + + request = prediction_service.EmbedContentRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = prediction_service.EmbedContentResponse() + post_with_metadata.return_value = ( + prediction_service.EmbedContentResponse(), + metadata, + ) + + await client.embed_content( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + @pytest.mark.asyncio async def test_get_location_rest_asyncio_bad_request( request_type=locations_pb2.GetLocationRequest, @@ -11161,6 +11955,31 @@ async def test_stream_generate_content_empty_call_rest_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_embed_content_empty_call_rest_asyncio(): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="rest_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + await client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_unsupported_parameter_rest_asyncio(): if not HAS_ASYNC_REST_EXTRA: pytest.skip( @@ -11221,6 +12040,7 @@ def test_prediction_service_base_transport(): "explain", "generate_content", "stream_generate_content", + "embed_content", "set_iam_policy", "get_iam_policy", "test_iam_permissions", @@ -11540,6 +12360,9 @@ def test_prediction_service_client_transport_session_collision(transport_name): session1 = client1.transport.stream_generate_content._session session2 = client2.transport.stream_generate_content._session assert session1 != session2 + session1 = client1.transport.embed_content._session + session2 = client2.transport.embed_content._session + assert session1 != session2 def test_prediction_service_grpc_transport_channel(): diff --git a/tests/unit/gapic/aiplatform_v1/test_reasoning_engine_service.py b/tests/unit/gapic/aiplatform_v1/test_reasoning_engine_service.py index 54cb2b7e2c..3b207b2a4c 100644 --- a/tests/unit/gapic/aiplatform_v1/test_reasoning_engine_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_reasoning_engine_service.py @@ -4614,6 +4614,13 @@ def test_create_reasoning_engine_rest_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -5152,6 +5159,13 @@ def test_update_reasoning_engine_rest_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -6312,6 +6326,13 @@ async def test_create_reasoning_engine_rest_asyncio_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -6904,6 +6925,13 @@ async def test_update_reasoning_engine_rest_asyncio_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -8676,10 +8704,41 @@ def test_reasoning_engine_service_grpc_lro_async_client(): assert transport.operations_client is transport.operations_client -def test_network_attachment_path(): +def test_git_repository_link_path(): project = "squid" - region = "clam" - networkattachment = "whelk" + location = "clam" + connection = "whelk" + git_repository_link = "octopus" + expected = "projects/{project}/locations/{location}/connections/{connection}/gitRepositoryLinks/{git_repository_link}".format( + project=project, + location=location, + connection=connection, + git_repository_link=git_repository_link, + ) + actual = ReasoningEngineServiceClient.git_repository_link_path( + project, location, connection, git_repository_link + ) + assert expected == actual + + +def test_parse_git_repository_link_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + "connection": "cuttlefish", + "git_repository_link": "mussel", + } + path = ReasoningEngineServiceClient.git_repository_link_path(**expected) + + # Check that the path construction is reversible. + actual = ReasoningEngineServiceClient.parse_git_repository_link_path(path) + assert expected == actual + + +def test_network_attachment_path(): + project = "winkle" + region = "nautilus" + networkattachment = "scallop" expected = "projects/{project}/regions/{region}/networkAttachments/{networkattachment}".format( project=project, region=region, @@ -8693,9 +8752,9 @@ def test_network_attachment_path(): def test_parse_network_attachment_path(): expected = { - "project": "octopus", - "region": "oyster", - "networkattachment": "nudibranch", + "project": "abalone", + "region": "squid", + "networkattachment": "clam", } path = ReasoningEngineServiceClient.network_attachment_path(**expected) @@ -8705,9 +8764,9 @@ def test_parse_network_attachment_path(): def test_reasoning_engine_path(): - project = "cuttlefish" - location = "mussel" - reasoning_engine = "winkle" + project = "whelk" + location = "octopus" + reasoning_engine = "oyster" expected = "projects/{project}/locations/{location}/reasoningEngines/{reasoning_engine}".format( project=project, location=location, @@ -8721,9 +8780,9 @@ def test_reasoning_engine_path(): def test_parse_reasoning_engine_path(): expected = { - "project": "nautilus", - "location": "scallop", - "reasoning_engine": "abalone", + "project": "nudibranch", + "location": "cuttlefish", + "reasoning_engine": "mussel", } path = ReasoningEngineServiceClient.reasoning_engine_path(**expected) @@ -8733,7 +8792,7 @@ def test_parse_reasoning_engine_path(): def test_common_billing_account_path(): - billing_account = "squid" + billing_account = "winkle" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -8743,7 +8802,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "clam", + "billing_account": "nautilus", } path = ReasoningEngineServiceClient.common_billing_account_path(**expected) @@ -8753,7 +8812,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "whelk" + folder = "scallop" expected = "folders/{folder}".format( folder=folder, ) @@ -8763,7 +8822,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "octopus", + "folder": "abalone", } path = ReasoningEngineServiceClient.common_folder_path(**expected) @@ -8773,7 +8832,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "oyster" + organization = "squid" expected = "organizations/{organization}".format( organization=organization, ) @@ -8783,7 +8842,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "nudibranch", + "organization": "clam", } path = ReasoningEngineServiceClient.common_organization_path(**expected) @@ -8793,7 +8852,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "cuttlefish" + project = "whelk" expected = "projects/{project}".format( project=project, ) @@ -8803,7 +8862,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "mussel", + "project": "octopus", } path = ReasoningEngineServiceClient.common_project_path(**expected) @@ -8813,8 +8872,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "winkle" - location = "nautilus" + project = "oyster" + location = "nudibranch" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -8825,8 +8884,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "scallop", - "location": "abalone", + "project": "cuttlefish", + "location": "mussel", } path = ReasoningEngineServiceClient.common_location_path(**expected) diff --git a/tests/unit/gapic/aiplatform_v1/test_schedule_service.py b/tests/unit/gapic/aiplatform_v1/test_schedule_service.py index b51c1243c6..012a753838 100644 --- a/tests/unit/gapic/aiplatform_v1/test_schedule_service.py +++ b/tests/unit/gapic/aiplatform_v1/test_schedule_service.py @@ -5735,6 +5735,7 @@ def test_create_schedule_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -6762,6 +6763,7 @@ def test_update_schedule_rest_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -7979,6 +7981,7 @@ async def test_create_schedule_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, @@ -9118,6 +9121,7 @@ async def test_update_schedule_rest_asyncio_call_success(request_type): "machine_type": "machine_type_value", "accelerator_type": 1, "accelerator_count": 1805, + "gpu_partition_size": "gpu_partition_size_value", "tpu_topology": "tpu_topology_value", "reservation_affinity": { "reservation_affinity_type": 1, diff --git a/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_cache_service.py b/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_cache_service.py index 784e4d8427..4cac26f191 100644 --- a/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_cache_service.py +++ b/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_cache_service.py @@ -4626,6 +4626,20 @@ def test_create_cached_content_rest_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, @@ -4744,7 +4758,13 @@ def test_create_cached_content_rest_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { @@ -5144,6 +5164,20 @@ def test_update_cached_content_rest_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, @@ -5262,7 +5296,13 @@ def test_update_cached_content_rest_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { @@ -6524,6 +6564,20 @@ async def test_create_cached_content_rest_asyncio_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, @@ -6642,7 +6696,13 @@ async def test_create_cached_content_rest_asyncio_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { @@ -7078,6 +7138,20 @@ async def test_update_cached_content_rest_asyncio_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, @@ -7196,7 +7270,13 @@ async def test_update_cached_content_rest_asyncio_call_success(request_type): }, "code_execution": {}, "url_context": {}, - "computer_use": {"environment": 1}, + "computer_use": { + "environment": 1, + "excluded_predefined_functions": [ + "excluded_predefined_functions_value1", + "excluded_predefined_functions_value2", + ], + }, } ], "tool_config": { diff --git a/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_tuning_service.py b/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_tuning_service.py index 4506f9d553..5141afbbe1 100644 --- a/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_tuning_service.py +++ b/tests/unit/gapic/aiplatform_v1beta1/test_gen_ai_tuning_service.py @@ -4722,6 +4722,20 @@ def test_create_tuning_job_rest_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": { "language": 1, @@ -6473,6 +6487,20 @@ async def test_create_tuning_job_rest_asyncio_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": { "language": 1, diff --git a/tests/unit/gapic/aiplatform_v1beta1/test_prediction_service.py b/tests/unit/gapic/aiplatform_v1beta1/test_prediction_service.py index ef01db8dcc..0e27e414ec 100644 --- a/tests/unit/gapic/aiplatform_v1beta1/test_prediction_service.py +++ b/tests/unit/gapic/aiplatform_v1beta1/test_prediction_service.py @@ -71,12 +71,14 @@ ) from google.cloud.aiplatform_v1beta1.services.prediction_service import transports from google.cloud.aiplatform_v1beta1.types import content +from google.cloud.aiplatform_v1beta1.types import content as gca_content from google.cloud.aiplatform_v1beta1.types import explanation from google.cloud.aiplatform_v1beta1.types import io from google.cloud.aiplatform_v1beta1.types import openapi from google.cloud.aiplatform_v1beta1.types import prediction_service from google.cloud.aiplatform_v1beta1.types import tool from google.cloud.aiplatform_v1beta1.types import types +from google.cloud.aiplatform_v1beta1.types import usage_metadata from google.cloud.location import locations_pb2 from google.iam.v1 import iam_policy_pb2 # type: ignore from google.iam.v1 import options_pb2 # type: ignore @@ -5164,6 +5166,341 @@ async def test_chat_completions_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + prediction_service.EmbedContentRequest, + dict, + ], +) +def test_embed_content(request_type, transport: str = "grpc"): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = prediction_service.EmbedContentResponse( + truncated=True, + ) + response = client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = prediction_service.EmbedContentRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True + + +def test_embed_content_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = prediction_service.EmbedContentRequest( + model="model_value", + title="title_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.embed_content(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == prediction_service.EmbedContentRequest( + model="model_value", + title="title_value", + ) + + +def test_embed_content_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.embed_content in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.embed_content] = mock_rpc + request = {} + client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.embed_content(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_embed_content_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.embed_content + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.embed_content + ] = mock_rpc + + request = {} + await client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.embed_content(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_embed_content_async( + transport: str = "grpc_asyncio", request_type=prediction_service.EmbedContentRequest +): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse( + truncated=True, + ) + ) + response = await client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = prediction_service.EmbedContentRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True + + +@pytest.mark.asyncio +async def test_embed_content_async_from_dict(): + await test_embed_content_async(request_type=dict) + + +def test_embed_content_field_headers(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = prediction_service.EmbedContentRequest() + + request.model = "model_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value = prediction_service.EmbedContentResponse() + client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "model=model_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_embed_content_field_headers_async(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = prediction_service.EmbedContentRequest() + + request.model = "model_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse() + ) + await client.embed_content(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "model=model_value", + ) in kw["metadata"] + + +def test_embed_content_flattened(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = prediction_service.EmbedContentResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.embed_content( + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].model + mock_val = "model_value" + assert arg == mock_val + arg = args[0].content + mock_val = gca_content.Content(role="role_value") + assert arg == mock_val + + +def test_embed_content_flattened_error(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.embed_content( + prediction_service.EmbedContentRequest(), + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + +@pytest.mark.asyncio +async def test_embed_content_flattened_async(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = prediction_service.EmbedContentResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.embed_content( + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].model + mock_val = "model_value" + assert arg == mock_val + arg = args[0].content + mock_val = gca_content.Content(role="role_value") + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_embed_content_flattened_error_async(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.embed_content( + prediction_service.EmbedContentRequest(), + model="model_value", + content=gca_content.Content(role="role_value"), + ) + + def test_predict_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -6990,54 +7327,153 @@ def test_chat_completions_rest_required_fields( ) request = request_type(**request_init) - # Designate an appropriate value for the returned response. - return_value = httpbody_pb2.HttpBody() - # Mock the http request call within the method and fake a response. - with mock.patch.object(Session, "request") as req: - # We need to mock transcode() because providing default values - # for required fields will fail the real version if the http_options - # expect actual values for those fields. - with mock.patch.object(path_template, "transcode") as transcode: - # A uri without fields and an empty body will force all the - # request fields to show up in the query_params. - pb_request = request_type.pb(request) - transcode_result = { - "uri": "v1/sample_method", - "method": "post", - "query_params": pb_request, - } - transcode_result["body"] = pb_request - transcode.return_value = transcode_result + # Designate an appropriate value for the returned response. + return_value = httpbody_pb2.HttpBody() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + json_return_value = json_format.MessageToJson(return_value) + json_return_value = "[{}]".format(json_return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + with mock.patch.object(response_value, "iter_content") as iter_content: + iter_content.return_value = iter(json_return_value) + response = client.chat_completions(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_chat_completions_rest_unset_required_fields(): + transport = transports.PredictionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.chat_completions._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("endpoint",))) + + +def test_chat_completions_rest_flattened(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = httpbody_pb2.HttpBody() + + # get arguments that satisfy an http rule for this method + sample_request = { + "endpoint": "projects/sample1/locations/sample2/endpoints/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + endpoint="endpoint_value", + http_body=httpbody_pb2.HttpBody(content_type="content_type_value"), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + json_return_value = "[{}]".format(json_return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + with mock.patch.object(response_value, "iter_content") as iter_content: + iter_content.return_value = iter(json_return_value) + client.chat_completions(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1beta1/{endpoint=projects/*/locations/*/endpoints/*}/chat/completions" + % client.transport._host, + args[1], + ) + + +def test_chat_completions_rest_flattened_error(transport: str = "rest"): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.chat_completions( + prediction_service.ChatCompletionsRequest(), + endpoint="endpoint_value", + http_body=httpbody_pb2.HttpBody(content_type="content_type_value"), + ) + - response_value = Response() - response_value.status_code = 200 +def test_embed_content_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) - json_return_value = json_format.MessageToJson(return_value) - json_return_value = "[{}]".format(json_return_value) + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() - response_value._content = json_return_value.encode("UTF-8") - req.return_value = response_value - req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + # Ensure method has been cached + assert client._transport.embed_content in client._transport._wrapped_methods - with mock.patch.object(response_value, "iter_content") as iter_content: - iter_content.return_value = iter(json_return_value) - response = client.chat_completions(request) + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.embed_content] = mock_rpc - expected_params = [("$alt", "json;enum-encoding=int")] - actual_params = req.call_args.kwargs["params"] - assert expected_params == actual_params + request = {} + client.embed_content(request) + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 -def test_chat_completions_rest_unset_required_fields(): - transport = transports.PredictionServiceRestTransport( - credentials=ga_credentials.AnonymousCredentials - ) + client.embed_content(request) - unset_fields = transport.chat_completions._get_unset_required_fields({}) - assert set(unset_fields) == (set(()) & set(("endpoint",))) + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 -def test_chat_completions_rest_flattened(): +def test_embed_content_rest_flattened(): client = PredictionServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -7046,45 +7482,44 @@ def test_chat_completions_rest_flattened(): # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = httpbody_pb2.HttpBody() + return_value = prediction_service.EmbedContentResponse() # get arguments that satisfy an http rule for this method sample_request = { - "endpoint": "projects/sample1/locations/sample2/endpoints/sample3" + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" } # get truthy value for each flattened field mock_args = dict( - endpoint="endpoint_value", - http_body=httpbody_pb2.HttpBody(content_type="content_type_value"), + model="model_value", + content=gca_content.Content(role="role_value"), ) mock_args.update(sample_request) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = prediction_service.EmbedContentResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) - json_return_value = "[{}]".format(json_return_value) response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - with mock.patch.object(response_value, "iter_content") as iter_content: - iter_content.return_value = iter(json_return_value) - client.chat_completions(**mock_args) + client.embed_content(**mock_args) # Establish that the underlying call was made with the expected # request object values. assert len(req.mock_calls) == 1 _, args, _ = req.mock_calls[0] assert path_template.validate( - "%s/v1beta1/{endpoint=projects/*/locations/*/endpoints/*}/chat/completions" + "%s/v1beta1/{model=projects/*/locations/*/publishers/*/models/*}:embedContent" % client.transport._host, args[1], ) -def test_chat_completions_rest_flattened_error(transport: str = "rest"): +def test_embed_content_rest_flattened_error(transport: str = "rest"): client = PredictionServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -7093,10 +7528,10 @@ def test_chat_completions_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.chat_completions( - prediction_service.ChatCompletionsRequest(), - endpoint="endpoint_value", - http_body=httpbody_pb2.HttpBody(content_type="content_type_value"), + client.embed_content( + prediction_service.EmbedContentRequest(), + model="model_value", + content=gca_content.Content(role="role_value"), ) @@ -7497,6 +7932,27 @@ def test_chat_completions_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_embed_content_empty_call_grpc(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + call.return_value = prediction_service.EmbedContentResponse() + client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_transport_kind_grpc_asyncio(): transport = PredictionServiceAsyncClient.get_transport_class("grpc_asyncio")( credentials=async_anonymous_credentials() @@ -7812,6 +8268,33 @@ async def test_chat_completions_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_embed_content_empty_call_grpc_asyncio(): + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + prediction_service.EmbedContentResponse( + truncated=True, + ) + ) + await client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_transport_kind_rest(): transport = PredictionServiceClient.get_transport_class("rest")( credentials=ga_credentials.AnonymousCredentials() @@ -9272,73 +9755,205 @@ def get_message_fields(field): subfields_not_in_runtime = [] - # For each item in the sample request, create a list of sub fields which are not present at runtime - # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime - for field, value in request_init["http_body"].items(): # pragma: NO COVER - result = None - is_repeated = False - # For repeated fields - if isinstance(value, list) and len(value): - is_repeated = True - result = value[0] - # For fields where the type is another message - if isinstance(value, dict): - result = value + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init["http_body"].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range(0, len(request_init["http_body"][field])): + del request_init["http_body"][field][i][subfield] + else: + del request_init["http_body"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = httpbody_pb2.HttpBody( + content_type="content_type_value", + data=b"data_blob", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + json_return_value = "[{}]".format(json_return_value) + response_value.iter_content = mock.Mock(return_value=iter(json_return_value)) + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.chat_completions(request) + + assert isinstance(response, Iterable) + response = next(response) + + # Establish that the response is the type that we expect. + assert isinstance(response, httpbody_pb2.HttpBody) + assert response.content_type == "content_type_value" + assert response.data == b"data_blob" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_chat_completions_rest_interceptors(null_interceptor): + transport = transports.PredictionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=( + None if null_interceptor else transports.PredictionServiceRestInterceptor() + ), + ) + client = PredictionServiceClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.PredictionServiceRestInterceptor, "post_chat_completions" + ) as post, mock.patch.object( + transports.PredictionServiceRestInterceptor, + "post_chat_completions_with_metadata", + ) as post_with_metadata, mock.patch.object( + transports.PredictionServiceRestInterceptor, "pre_chat_completions" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = prediction_service.ChatCompletionsRequest.pb( + prediction_service.ChatCompletionsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = json_format.MessageToJson(httpbody_pb2.HttpBody()) + req.return_value.iter_content = mock.Mock(return_value=iter(return_value)) + + request = prediction_service.ChatCompletionsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = httpbody_pb2.HttpBody() + post_with_metadata.return_value = httpbody_pb2.HttpBody(), metadata + + client.chat_completions( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + +def test_embed_content_rest_bad_request( + request_type=prediction_service.EmbedContentRequest, +): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.embed_content(request) + - if result and hasattr(result, "keys"): - for subfield in result.keys(): - if (field, subfield) not in runtime_nested_fields: - subfields_not_in_runtime.append( - { - "field": field, - "subfield": subfield, - "is_repeated": is_repeated, - } - ) +@pytest.mark.parametrize( + "request_type", + [ + prediction_service.EmbedContentRequest, + dict, + ], +) +def test_embed_content_rest_call_success(request_type): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) - # Remove fields from the sample request which are not present in the runtime version of the dependency - # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime - for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER - field = subfield_to_delete.get("field") - field_repeated = subfield_to_delete.get("is_repeated") - subfield = subfield_to_delete.get("subfield") - if subfield: - if field_repeated: - for i in range(0, len(request_init["http_body"][field])): - del request_init["http_body"][field][i][subfield] - else: - del request_init["http_body"][field][subfield] + # send a request that will satisfy transcoding + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } request = request_type(**request_init) # Mock the http request call within the method and fake a response. with mock.patch.object(type(client.transport._session), "request") as req: # Designate an appropriate value for the returned response. - return_value = httpbody_pb2.HttpBody( - content_type="content_type_value", - data=b"data_blob", + return_value = prediction_service.EmbedContentResponse( + truncated=True, ) # Wrap the value into a proper Response obj response_value = mock.Mock() response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = prediction_service.EmbedContentResponse.pb(return_value) json_return_value = json_format.MessageToJson(return_value) - json_return_value = "[{}]".format(json_return_value) - response_value.iter_content = mock.Mock(return_value=iter(json_return_value)) + response_value.content = json_return_value.encode("UTF-8") req.return_value = response_value req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - response = client.chat_completions(request) - - assert isinstance(response, Iterable) - response = next(response) + response = client.embed_content(request) # Establish that the response is the type that we expect. - assert isinstance(response, httpbody_pb2.HttpBody) - assert response.content_type == "content_type_value" - assert response.data == b"data_blob" + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_chat_completions_rest_interceptors(null_interceptor): +def test_embed_content_rest_interceptors(null_interceptor): transport = transports.PredictionServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=( @@ -9352,18 +9967,17 @@ def test_chat_completions_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.PredictionServiceRestInterceptor, "post_chat_completions" + transports.PredictionServiceRestInterceptor, "post_embed_content" ) as post, mock.patch.object( - transports.PredictionServiceRestInterceptor, - "post_chat_completions_with_metadata", + transports.PredictionServiceRestInterceptor, "post_embed_content_with_metadata" ) as post_with_metadata, mock.patch.object( - transports.PredictionServiceRestInterceptor, "pre_chat_completions" + transports.PredictionServiceRestInterceptor, "pre_embed_content" ) as pre: pre.assert_not_called() post.assert_not_called() post_with_metadata.assert_not_called() - pb_message = prediction_service.ChatCompletionsRequest.pb( - prediction_service.ChatCompletionsRequest() + pb_message = prediction_service.EmbedContentRequest.pb( + prediction_service.EmbedContentRequest() ) transcode.return_value = { "method": "post", @@ -9375,19 +9989,24 @@ def test_chat_completions_rest_interceptors(null_interceptor): req.return_value = mock.Mock() req.return_value.status_code = 200 req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - return_value = json_format.MessageToJson(httpbody_pb2.HttpBody()) - req.return_value.iter_content = mock.Mock(return_value=iter(return_value)) + return_value = prediction_service.EmbedContentResponse.to_json( + prediction_service.EmbedContentResponse() + ) + req.return_value.content = return_value - request = prediction_service.ChatCompletionsRequest() + request = prediction_service.EmbedContentRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = httpbody_pb2.HttpBody() - post_with_metadata.return_value = httpbody_pb2.HttpBody(), metadata + post.return_value = prediction_service.EmbedContentResponse() + post_with_metadata.return_value = ( + prediction_service.EmbedContentResponse(), + metadata, + ) - client.chat_completions( + client.embed_content( request, metadata=[ ("key", "val"), @@ -10260,6 +10879,26 @@ def test_chat_completions_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_embed_content_empty_call_rest(): + client = PredictionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_transport_kind_rest_asyncio(): if not HAS_ASYNC_REST_EXTRA: pytest.skip( @@ -12070,6 +12709,161 @@ async def test_chat_completions_rest_asyncio_interceptors(null_interceptor): post_with_metadata.assert_called_once() +@pytest.mark.asyncio +async def test_embed_content_rest_asyncio_bad_request( + request_type=prediction_service.EmbedContentRequest, +): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), transport="rest_asyncio" + ) + # send a request that will satisfy transcoding + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(AsyncAuthorizedSession, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.read = mock.AsyncMock(return_value=b"{}") + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + await client.embed_content(request) + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + prediction_service.EmbedContentRequest, + dict, + ], +) +async def test_embed_content_rest_asyncio_call_success(request_type): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), transport="rest_asyncio" + ) + + # send a request that will satisfy transcoding + request_init = { + "model": "projects/sample1/locations/sample2/publishers/sample3/models/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = prediction_service.EmbedContentResponse( + truncated=True, + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = prediction_service.EmbedContentResponse.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value.read = mock.AsyncMock( + return_value=json_return_value.encode("UTF-8") + ) + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = await client.embed_content(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, prediction_service.EmbedContentResponse) + assert response.truncated is True + + +@pytest.mark.asyncio +@pytest.mark.parametrize("null_interceptor", [True, False]) +async def test_embed_content_rest_asyncio_interceptors(null_interceptor): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + transport = transports.AsyncPredictionServiceRestTransport( + credentials=async_anonymous_credentials(), + interceptor=( + None + if null_interceptor + else transports.AsyncPredictionServiceRestInterceptor() + ), + ) + client = PredictionServiceAsyncClient(transport=transport) + + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.AsyncPredictionServiceRestInterceptor, "post_embed_content" + ) as post, mock.patch.object( + transports.AsyncPredictionServiceRestInterceptor, + "post_embed_content_with_metadata", + ) as post_with_metadata, mock.patch.object( + transports.AsyncPredictionServiceRestInterceptor, "pre_embed_content" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = prediction_service.EmbedContentRequest.pb( + prediction_service.EmbedContentRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = prediction_service.EmbedContentResponse.to_json( + prediction_service.EmbedContentResponse() + ) + req.return_value.read = mock.AsyncMock(return_value=return_value) + + request = prediction_service.EmbedContentRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = prediction_service.EmbedContentResponse() + post_with_metadata.return_value = ( + prediction_service.EmbedContentResponse(), + metadata, + ) + + await client.embed_content( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + @pytest.mark.asyncio async def test_get_location_rest_asyncio_bad_request( request_type=locations_pb2.GetLocationRequest, @@ -13101,6 +13895,31 @@ async def test_chat_completions_empty_call_rest_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_embed_content_empty_call_rest_asyncio(): + if not HAS_ASYNC_REST_EXTRA: + pytest.skip( + "the library must be installed with the `async_rest` extra to test this feature." + ) + client = PredictionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="rest_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.embed_content), "__call__") as call: + await client.embed_content(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = prediction_service.EmbedContentRequest() + + assert args[0] == request_msg + + def test_unsupported_parameter_rest_asyncio(): if not HAS_ASYNC_REST_EXTRA: pytest.skip( @@ -13163,6 +13982,7 @@ def test_prediction_service_base_transport(): "generate_content", "stream_generate_content", "chat_completions", + "embed_content", "set_iam_policy", "get_iam_policy", "test_iam_permissions", @@ -13488,6 +14308,9 @@ def test_prediction_service_client_transport_session_collision(transport_name): session1 = client1.transport.chat_completions._session session2 = client2.transport.chat_completions._session assert session1 != session2 + session1 = client1.transport.embed_content._session + session2 = client2.transport.embed_content._session + assert session1 != session2 def test_prediction_service_grpc_transport_channel(): diff --git a/tests/unit/gapic/aiplatform_v1beta1/test_reasoning_engine_service.py b/tests/unit/gapic/aiplatform_v1beta1/test_reasoning_engine_service.py index 135f6d252f..189d77b27e 100644 --- a/tests/unit/gapic/aiplatform_v1beta1/test_reasoning_engine_service.py +++ b/tests/unit/gapic/aiplatform_v1beta1/test_reasoning_engine_service.py @@ -4617,6 +4617,13 @@ def test_create_reasoning_engine_rest_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -5171,6 +5178,13 @@ def test_update_reasoning_engine_rest_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -6347,6 +6361,13 @@ async def test_create_reasoning_engine_rest_asyncio_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -6955,6 +6976,13 @@ async def test_update_reasoning_engine_rest_asyncio_call_success(request_type): "spec": { "source_code_spec": { "inline_source": {"source_archive": b"source_archive_blob"}, + "developer_connect_source": { + "config": { + "git_repository_link": "git_repository_link_value", + "dir_": "dir__value", + "revision": "revision_value", + } + }, "python_spec": { "version": "version_value", "entrypoint_module": "entrypoint_module_value", @@ -8769,10 +8797,41 @@ def test_parse_endpoint_path(): assert expected == actual -def test_network_attachment_path(): +def test_git_repository_link_path(): project = "cuttlefish" - region = "mussel" - networkattachment = "winkle" + location = "mussel" + connection = "winkle" + git_repository_link = "nautilus" + expected = "projects/{project}/locations/{location}/connections/{connection}/gitRepositoryLinks/{git_repository_link}".format( + project=project, + location=location, + connection=connection, + git_repository_link=git_repository_link, + ) + actual = ReasoningEngineServiceClient.git_repository_link_path( + project, location, connection, git_repository_link + ) + assert expected == actual + + +def test_parse_git_repository_link_path(): + expected = { + "project": "scallop", + "location": "abalone", + "connection": "squid", + "git_repository_link": "clam", + } + path = ReasoningEngineServiceClient.git_repository_link_path(**expected) + + # Check that the path construction is reversible. + actual = ReasoningEngineServiceClient.parse_git_repository_link_path(path) + assert expected == actual + + +def test_network_attachment_path(): + project = "whelk" + region = "octopus" + networkattachment = "oyster" expected = "projects/{project}/regions/{region}/networkAttachments/{networkattachment}".format( project=project, region=region, @@ -8786,9 +8845,9 @@ def test_network_attachment_path(): def test_parse_network_attachment_path(): expected = { - "project": "nautilus", - "region": "scallop", - "networkattachment": "abalone", + "project": "nudibranch", + "region": "cuttlefish", + "networkattachment": "mussel", } path = ReasoningEngineServiceClient.network_attachment_path(**expected) @@ -8798,9 +8857,9 @@ def test_parse_network_attachment_path(): def test_reasoning_engine_path(): - project = "squid" - location = "clam" - reasoning_engine = "whelk" + project = "winkle" + location = "nautilus" + reasoning_engine = "scallop" expected = "projects/{project}/locations/{location}/reasoningEngines/{reasoning_engine}".format( project=project, location=location, @@ -8814,9 +8873,9 @@ def test_reasoning_engine_path(): def test_parse_reasoning_engine_path(): expected = { - "project": "octopus", - "location": "oyster", - "reasoning_engine": "nudibranch", + "project": "abalone", + "location": "squid", + "reasoning_engine": "clam", } path = ReasoningEngineServiceClient.reasoning_engine_path(**expected) @@ -8826,7 +8885,7 @@ def test_parse_reasoning_engine_path(): def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -8836,7 +8895,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "octopus", } path = ReasoningEngineServiceClient.common_billing_account_path(**expected) @@ -8846,7 +8905,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -8856,7 +8915,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "nudibranch", } path = ReasoningEngineServiceClient.common_folder_path(**expected) @@ -8866,7 +8925,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -8876,7 +8935,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "mussel", } path = ReasoningEngineServiceClient.common_organization_path(**expected) @@ -8886,7 +8945,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -8896,7 +8955,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "nautilus", } path = ReasoningEngineServiceClient.common_project_path(**expected) @@ -8906,8 +8965,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -8918,8 +8977,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "squid", + "location": "clam", } path = ReasoningEngineServiceClient.common_location_path(**expected) diff --git a/tests/unit/gapic/aiplatform_v1beta1/test_session_service.py b/tests/unit/gapic/aiplatform_v1beta1/test_session_service.py index a12faa4603..1adec0ce5b 100644 --- a/tests/unit/gapic/aiplatform_v1beta1/test_session_service.py +++ b/tests/unit/gapic/aiplatform_v1beta1/test_session_service.py @@ -3058,6 +3058,7 @@ def test_list_events_non_empty_request_with_auto_populated_field(): parent="parent_value", page_token="page_token_value", filter="filter_value", + order_by="order_by_value", ) # Mock the actual call within the gRPC stub, and fake the request. @@ -3072,6 +3073,7 @@ def test_list_events_non_empty_request_with_auto_populated_field(): parent="parent_value", page_token="page_token_value", filter="filter_value", + order_by="order_by_value", ) @@ -4925,6 +4927,7 @@ def test_list_events_rest_required_fields( assert not set(unset_fields) - set( ( "filter", + "order_by", "page_size", "page_token", ) @@ -4987,6 +4990,7 @@ def test_list_events_rest_unset_required_fields(): set( ( "filter", + "orderBy", "pageSize", "pageToken", ) @@ -6785,6 +6789,20 @@ def test_append_event_rest_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, @@ -6802,7 +6820,6 @@ def test_append_event_rest_call_success(request_type): "skip_summarization": True, "state_delta": {}, "artifact_delta": {}, - "transfer_to_agent": True, "escalate": True, "requested_auth_configs": {}, "transfer_agent": "transfer_agent_value", @@ -8983,6 +9000,20 @@ async def test_append_event_rest_asyncio_call_success(request_type): "id": "id_value", "name": "name_value", "response": {}, + "parts": [ + { + "inline_data": { + "mime_type": "mime_type_value", + "data": b"data_blob", + "display_name": "display_name_value", + }, + "file_data": { + "mime_type": "mime_type_value", + "file_uri": "file_uri_value", + "display_name": "display_name_value", + }, + } + ], }, "executable_code": {"language": 1, "code": "code_value"}, "code_execution_result": {"outcome": 1, "output": "output_value"}, @@ -9000,7 +9031,6 @@ async def test_append_event_rest_asyncio_call_success(request_type): "skip_summarization": True, "state_delta": {}, "artifact_delta": {}, - "transfer_to_agent": True, "escalate": True, "requested_auth_configs": {}, "transfer_agent": "transfer_agent_value",