2727from google .genai ._common import get_value_by_path as getv
2828from google .genai ._common import set_value_by_path as setv
2929
30+ from . import _prompt_optimizer_utils
3031from . import types
3132
3233
@@ -574,6 +575,7 @@ def _wait_for_completion(self, job_name: str) -> None:
574575 raise RuntimeError (f"Job failed with state: { job .state } " )
575576 else :
576577 logger .info (f"Job completed with state: { job .state } " )
578+ return job
577579
578580 def optimize (
579581 self ,
@@ -584,17 +586,11 @@ def optimize(
584586
585587 Args:
586588 method: The method for optimizing multiple prompts.
587- config: The config to use. Config consists of the following fields: -
588- config_path: The gcs path to the config file, e.g.
589- gs://bucket/config.json. - service_account: Optional. The service
590- account to use for the custom job. Cannot be provided at the same
591- time as 'service_account_project_number'. -
592- service_account_project_number: Optional. The project number used to
593- construct the default service account:
594- f"{service_account_project_number}-compute@developer.gserviceaccount.com"
595- Cannot be provided at the same time as 'service_account'. -
596- wait_for_completion: Optional. Whether to wait for the job to
597- complete. Default is True.
589+ config: PromptOptimizerVAPOConfig instance containing the
590+ configuration for prompt optimization.
591+
592+ Returns:
593+ The custom job that was created.
598594 """
599595
600596 if method != "vapo" :
@@ -631,23 +627,7 @@ def optimize(
631627 }
632628 ]
633629
634- if config .service_account :
635- if config .service_account_project_number :
636- raise ValueError (
637- "Only one of service_account or"
638- " service_account_project_number can be provided."
639- )
640- service_account = config .service_account
641- elif config .project_number :
642- service_account = (
643- f"{ config .service_account_project_number } "
644- "-compute@developer.gserviceaccount.com"
645- )
646- else :
647- raise ValueError (
648- "Either service_account or service_account_project_number is"
649- " required."
650- )
630+ service_account = _prompt_optimizer_utils ._get_service_account (config )
651631
652632 job_spec = types .CustomJobSpec (
653633 worker_pool_specs = worker_pool_specs ,
@@ -672,11 +652,11 @@ def optimize(
672652 logger .info ("Job created: %s" , job .name )
673653
674654 # Construct the dashboard URL
675- dashboard_url = f"https://pantheon.corp .google.com/vertex-ai/locations/{ region } /training/{ job_id } /cpu?e=13802955& project={ project } "
655+ dashboard_url = f"https://console.cloud .google.com/vertex-ai/locations/{ region } /training/{ job_id } /cpu?project={ project } "
676656 logger .info ("View the job status at: %s" , dashboard_url )
677657
678658 if wait_for_completion :
679- self ._wait_for_completion (job_id )
659+ job = self ._wait_for_completion (job_id )
680660 return job
681661
682662
@@ -843,3 +823,92 @@ async def _get_custom_job(
843823
844824 self ._api_client ._verify_response (return_value )
845825 return return_value
826+
827+ async def optimize (
828+ self ,
829+ method : str ,
830+ config : types .PromptOptimizerVAPOConfigOrDict ,
831+ ) -> types .CustomJob :
832+ """Call async Vertex AI Prompt Optimizer (VAPO).
833+
834+ # Todo: b/428953357 - Add example in the README.
835+ Example usage:
836+ client = vertexai.Client(project=PROJECT_NAME, location='us-central1')
837+ vapo_config = vertexai.types.PromptOptimizerVAPOConfig(
838+ config_path="gs://you-bucket-name/your-config.json",
839+ service_account=service_account,
840+ wait_for_completion=True
841+ )
842+ job = await client.aio.prompt_optimizer.optimize(
843+ method="vapo", config=vapo_config)
844+
845+ Args:
846+ method: The method for optimizing multiple prompts (currently only
847+ vapo is supported).
848+ config: PromptOptimizerVAPOConfig instance containing the
849+ configuration for prompt optimization.
850+
851+ Returns:
852+ The custom job that was created.
853+ """
854+ if method != "vapo" :
855+ raise ValueError ("Only vapo methods is currently supported." )
856+
857+ if isinstance (config , dict ):
858+ config = types .PromptOptimizerVAPOConfig (** config )
859+
860+ timestamp = datetime .datetime .now ().strftime ("%Y%m%d-%H%M%S" )
861+ display_name = f"vapo-optimizer-{ timestamp } "
862+
863+ if not config .config_path :
864+ raise ValueError ("Config path is required." )
865+ bucket = "/" .join (config .config_path .split ("/" )[:- 1 ])
866+
867+ container_uri = "us-docker.pkg.dev/vertex-ai/cair/vaipo:preview_v1_0"
868+
869+ region = self ._api_client .location
870+ project = self ._api_client .project
871+ container_args = {
872+ "config" : config .config_path ,
873+ }
874+ args = ["--%s=%s" % (k , v ) for k , v in container_args .items ()]
875+ worker_pool_specs = [
876+ {
877+ "replica_count" : 1 ,
878+ "container_spec" : {
879+ "image_uri" : container_uri ,
880+ "args" : args ,
881+ },
882+ "machine_spec" : {
883+ "machine_type" : "n1-standard-4" ,
884+ },
885+ }
886+ ]
887+
888+ service_account = _prompt_optimizer_utils ._get_service_account (config )
889+
890+ job_spec = types .CustomJobSpec (
891+ worker_pool_specs = worker_pool_specs ,
892+ base_output_directory = types .GcsDestination (output_uri_prefix = bucket ),
893+ service_account = service_account ,
894+ )
895+
896+ custom_job = types .CustomJob (
897+ display_name = display_name ,
898+ job_spec = job_spec ,
899+ )
900+
901+ job = await self ._create_custom_job_resource (
902+ custom_job = custom_job ,
903+ )
904+
905+ # Get the job id for the dashboard url and display to the user.
906+ job_resource_name = job .name
907+ job_id = job_resource_name .split ("/" )[- 1 ]
908+ logger .info ("Job created: %s" , job .name )
909+
910+ # Construct the dashboard URL to show to the user.
911+ dashboard_url = f"https://console.cloud.google.com/vertex-ai/locations/{ region } /training/{ job_id } /cpu?project={ project } "
912+ logger .info ("View the job status at: %s" , dashboard_url )
913+
914+ return job
0 commit comments