diff --git a/components/google-cloud/RELEASE.md b/components/google-cloud/RELEASE.md index d147d37f5dbe..361d7d938537 100644 --- a/components/google-cloud/RELEASE.md +++ b/components/google-cloud/RELEASE.md @@ -14,6 +14,7 @@ * Group `preview.llm.rlhf_pipeline` components for better readability. * Add environment variable support to GCPC's `create_custom_training_job_from_component` (both `v1` and `preview` namespaces) * Apply latest GCPC image vulnerability resolutions (base OS and software updates). +* Add Vertex model get component(v1.model.ModelGetOp). ## Release 2.5.0 * Upload tensorboard metrics from `preview.llm.rlhf_pipeline` if a `tensorboard_resource_id` is provided at runtime. diff --git a/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/__init__.py b/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/__init__.py new file mode 100644 index 000000000000..c3da8400006b --- /dev/null +++ b/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2022 The Kubeflow Authors. All Rights Reserved. +# +# 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. +"""Google Cloud Pipeline Components - Get Model Launcher and Remote Runner.""" diff --git a/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/launcher.py b/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/launcher.py new file mode 100644 index 000000000000..781a4a44ac21 --- /dev/null +++ b/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/launcher.py @@ -0,0 +1,70 @@ +# Copyright 2022 The Kubeflow Authors. All Rights Reserved. +# +# 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. +"""GCP launcher for Get Model based on the AI Platform SDK.""" + +import argparse +import logging +import sys + +from google_cloud_pipeline_components.container.v1.model.get_model import remote_runner + + +def _parse_args(args): + """Parse command line arguments.""" + parser = argparse.ArgumentParser( + prog='Vertex Pipelines get model launcher', description='' + ) + parser.add_argument( + '--executor_input', + dest='executor_input', + type=str, + # executor_input is only needed for components that emit output artifacts. + required=True, + default=argparse.SUPPRESS, + ) + parser.add_argument('--project', dest='project', type=str, default=None) + parser.add_argument('--location', dest='location', type=str, default=None) + + group_args = parser.add_mutually_exclusive_group(required=True) + group_args.add_argument( + '--model_name', dest='model_name', type=str, default=None + ) + parsed_args, _ = parser.parse_known_args(args) + return vars(parsed_args) + + +def main(argv): + """Main entry. + + Expected input args are as follows: + model_name - Required. Provided string resource name to create a model + artifact. + project - Required. Project to get this Model from. + location - Required. Location to get this Model from. + + Args: + argv: A list of system arguments. + """ + parsed_args = _parse_args(argv) + print(parsed_args.model_name) + logging.info('model_name: %s', parsed_args.model_name) + print(parsed_args.project) + logging.info('project: %s', parsed_args.project) + print(parsed_args.location) + logging.info('location: %s', parsed_args.location) + remote_runner.get_model(**parsed_args) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/remote_runner.py b/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/remote_runner.py new file mode 100644 index 000000000000..e0860e3ad768 --- /dev/null +++ b/components/google-cloud/google_cloud_pipeline_components/container/v1/model/get_model/remote_runner.py @@ -0,0 +1,60 @@ +# Copyright 2021 The Kubeflow Authors. All Rights Reserved. +# +# 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. +"""Remote runner for Get Model based on the AI Platform SDK.""" + + +from google.api_core import gapic_v1 +from google.cloud import aiplatform +from google_cloud_pipeline_components.container.utils import artifact_utils +from google_cloud_pipeline_components.types import artifact_types + + +def get_model( + executor_input, + model_name: str, + project: str, + location: str, +): + """Get model.""" + if not location or not project: + raise ValueError( + 'Model resource name must be in the format' + ' projects/{project}/locations/{location}/models/{model_name}' + ) + api_endpoint = location + '-aiplatform.googleapis.com' + vertex_uri_prefix = f'https://{api_endpoint}/v1/' + model_resource_name = ( + f'projects/{project}/locations/{location}/models/{model_name}' + ) + + client = aiplatform.gapic.ModelServiceClient( + client_info=gapic_v1.client_info.ClientInfo( + user_agent='googles-cloud-pipeline-components' + ), + client_options={ + 'api_endpoint': api_endpoint, + }, + ) + get_model_response = client.get_model(name=model_resource_name) + + resp_model_name_without_version = get_model_response.name.split('@', 1)[0] + model_resource_name = ( + f'{resp_model_name_without_version}@{get_model_response.version_id}' + ) + + vertex_model = artifact_types.VertexModel.create( + 'model', vertex_uri_prefix + model_resource_name, model_resource_name + ) + # TODO(b/266848949): Output Artifact should use correct MLMD artifact. + artifact_utils.update_output_artifacts(executor_input, [vertex_model]) diff --git a/components/google-cloud/google_cloud_pipeline_components/v1/model/__init__.py b/components/google-cloud/google_cloud_pipeline_components/v1/model/__init__.py index 2295c68d5325..5577af884844 100644 --- a/components/google-cloud/google_cloud_pipeline_components/v1/model/__init__.py +++ b/components/google-cloud/google_cloud_pipeline_components/v1/model/__init__.py @@ -17,10 +17,12 @@ from google_cloud_pipeline_components.v1.model.delete_model.component import model_delete as ModelDeleteOp from google_cloud_pipeline_components.v1.model.export_model.component import model_export as ModelExportOp +from google_cloud_pipeline_components.v1.model.get_model.component import model_get as ModelGetOp from google_cloud_pipeline_components.v1.model.upload_model.component import model_upload as ModelUploadOp __all__ = [ 'ModelExportOp', 'ModelUploadOp', 'ModelDeleteOp', + 'ModelGetOp', ] diff --git a/components/google-cloud/google_cloud_pipeline_components/v1/model/get_model/__init__.py b/components/google-cloud/google_cloud_pipeline_components/v1/model/get_model/__init__.py new file mode 100644 index 000000000000..b87e91244223 --- /dev/null +++ b/components/google-cloud/google_cloud_pipeline_components/v1/model/get_model/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Kubeflow Authors. All Rights Reserved. +# +# 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. +"""Google Cloud Pipeline Get Vertex Model Component.""" diff --git a/components/google-cloud/google_cloud_pipeline_components/v1/model/get_model/component.py b/components/google-cloud/google_cloud_pipeline_components/v1/model/get_model/component.py new file mode 100644 index 000000000000..e9cedc5359e8 --- /dev/null +++ b/components/google-cloud/google_cloud_pipeline_components/v1/model/get_model/component.py @@ -0,0 +1,63 @@ +# Copyright 2023 The Kubeflow Authors. All Rights Reserved. +# +# 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 google_cloud_pipeline_components import _image +from google_cloud_pipeline_components import _placeholders +from google_cloud_pipeline_components.types.artifact_types import VertexModel +from kfp.dsl import container_component +from kfp.dsl import ContainerSpec +from kfp.dsl import Output +from kfp.dsl import OutputPath + + +@container_component +def model_get( + model: Output[VertexModel], + model_name: str, + project: str = _placeholders.PROJECT_ID_PLACEHOLDER, + location: str = 'us-central1', +): + # fmt: off + """Gets a model artifact or string inputs to an existing Vertex model. + + Args: + project: Project to get this Model from. Defaults to the project in which the PipelineJob is run. + model_name: Vertex model resource name in the format of + projects/{project}/locations/{location}/models/{model} or + projects/{project}/locations/{location}/models/{model}@{model_version_id + or model_version_alias}.If no version ID or alias is specified, the "default" version will be returned. + location: Optional location to get this Model from. If not set, defaults to `us-central1`. + + Returns: + model: Artifact of the Vertex Model. + """ + # fmt: on + return ContainerSpec( + image=_image.GCPC_IMAGE_TAG, + command=[ + 'python3', + '-u', + '-m', + 'google_cloud_pipeline_components.container.v1.model.get_model.launcher', + ], + args=[ + '--project', + project, + '--location', + location, + '--model_name', + model_name, + '--executor_input', + '{{$}}', + ], + )