google-cloud-agentplatform 1.165.1.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. agentplatform/__init__.py +72 -0
  2. agentplatform/_genai/__init__.py +43 -0
  3. agentplatform/_genai/_agent_engines_utils.py +2341 -0
  4. agentplatform/_genai/_bigquery_utils.py +49 -0
  5. agentplatform/_genai/_datasets_utils.py +344 -0
  6. agentplatform/_genai/_evals_builtin_tools.py +209 -0
  7. agentplatform/_genai/_evals_common.py +4268 -0
  8. agentplatform/_genai/_evals_constant.py +122 -0
  9. agentplatform/_genai/_evals_data_converters.py +926 -0
  10. agentplatform/_genai/_evals_metric_handlers.py +1783 -0
  11. agentplatform/_genai/_evals_metric_loaders.py +401 -0
  12. agentplatform/_genai/_evals_utils.py +1043 -0
  13. agentplatform/_genai/_evals_visualization.py +2070 -0
  14. agentplatform/_genai/_gcs_utils.py +262 -0
  15. agentplatform/_genai/_logging_utils.py +47 -0
  16. agentplatform/_genai/_memory_bank_utils.py +206 -0
  17. agentplatform/_genai/_observability_data_converter.py +186 -0
  18. agentplatform/_genai/_operations_utils.py +94 -0
  19. agentplatform/_genai/_prompt_management_utils.py +147 -0
  20. agentplatform/_genai/_prompt_optimizer_utils.py +215 -0
  21. agentplatform/_genai/_skills_utils.py +69 -0
  22. agentplatform/_genai/_transformers.py +628 -0
  23. agentplatform/_genai/a2a_task_events.py +509 -0
  24. agentplatform/_genai/a2a_tasks.py +861 -0
  25. agentplatform/_genai/agent_engines.py +3931 -0
  26. agentplatform/_genai/client.py +519 -0
  27. agentplatform/_genai/datasets.py +3045 -0
  28. agentplatform/_genai/endpoints.py +1149 -0
  29. agentplatform/_genai/evals.py +6883 -0
  30. agentplatform/_genai/example_stores.py +1445 -0
  31. agentplatform/_genai/feedback_contexts.py +700 -0
  32. agentplatform/_genai/feedback_entries.py +1644 -0
  33. agentplatform/_genai/live.py +64 -0
  34. agentplatform/_genai/live_agent_engines.py +179 -0
  35. agentplatform/_genai/memories.py +2962 -0
  36. agentplatform/_genai/memory_banks.py +1927 -0
  37. agentplatform/_genai/memory_revisions.py +465 -0
  38. agentplatform/_genai/model_garden.py +2638 -0
  39. agentplatform/_genai/prompt_optimizer.py +995 -0
  40. agentplatform/_genai/prompts.py +4515 -0
  41. agentplatform/_genai/rag.py +4961 -0
  42. agentplatform/_genai/runtime_revisions.py +1257 -0
  43. agentplatform/_genai/runtimes.py +78 -0
  44. agentplatform/_genai/sandbox_snapshots.py +1015 -0
  45. agentplatform/_genai/sandbox_templates.py +1088 -0
  46. agentplatform/_genai/sandboxes.py +1604 -0
  47. agentplatform/_genai/session_events.py +543 -0
  48. agentplatform/_genai/sessions.py +1449 -0
  49. agentplatform/_genai/skill_revisions.py +377 -0
  50. agentplatform/_genai/skills.py +1708 -0
  51. agentplatform/_genai/types/__init__.py +4695 -0
  52. agentplatform/_genai/types/agent_engines.py +16 -0
  53. agentplatform/_genai/types/common.py +32784 -0
  54. agentplatform/_genai/types/evals.py +1031 -0
  55. agentplatform/_genai/types/prompt_optimizer.py +107 -0
  56. agentplatform/_genai/types/prompts.py +107 -0
  57. agentplatform/version.py +17 -0
  58. google_cloud_agentplatform-1.165.1.dev0.dist-info/METADATA +79 -0
  59. google_cloud_agentplatform-1.165.1.dev0.dist-info/RECORD +62 -0
  60. google_cloud_agentplatform-1.165.1.dev0.dist-info/WHEEL +5 -0
  61. google_cloud_agentplatform-1.165.1.dev0.dist-info/licenses/LICENSE +202 -0
  62. google_cloud_agentplatform-1.165.1.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,995 @@
1
+ # Copyright 2025 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+
16
+ # Code generated by the Google Gen AI SDK generator DO NOT EDIT.
17
+
18
+ import json
19
+ import logging
20
+ import time
21
+ from typing import Any, Optional, Union
22
+ from urllib.parse import urlencode
23
+
24
+ from google.genai import _api_module
25
+ from google.genai import _common
26
+ from google.genai import types as genai_types
27
+ from google.genai._common import get_value_by_path as getv
28
+ from google.genai._common import set_value_by_path as setv
29
+
30
+ from . import _logging_utils
31
+ from . import _prompt_optimizer_utils
32
+ from . import prompts
33
+ from . import types
34
+
35
+ logger = logging.getLogger("agentplatform_genai.promptoptimizer")
36
+
37
+
38
+ def _CustomJobParameters_to_vertex(
39
+ from_object: Union[dict[str, Any], object],
40
+ parent_object: Optional[dict[str, Any]] = None,
41
+ ) -> dict[str, Any]:
42
+ to_object: dict[str, Any] = {}
43
+ if getv(from_object, ["custom_job"]) is not None:
44
+ setv(
45
+ parent_object,
46
+ ["customJob"],
47
+ _CustomJob_to_vertex(getv(from_object, ["custom_job"]), to_object),
48
+ )
49
+
50
+ if getv(from_object, ["config"]) is not None:
51
+ setv(to_object, ["config"], getv(from_object, ["config"]))
52
+
53
+ return to_object
54
+
55
+
56
+ def _CustomJob_from_vertex(
57
+ from_object: Union[dict[str, Any], object],
58
+ parent_object: Optional[dict[str, Any]] = None,
59
+ ) -> dict[str, Any]:
60
+ to_object: dict[str, Any] = {}
61
+ if getv(parent_object, ["displayName"]) is not None:
62
+ setv(to_object, ["display_name"], getv(parent_object, ["displayName"]))
63
+
64
+ if getv(parent_object, ["jobSpec"]) is not None:
65
+ setv(to_object, ["job_spec"], getv(parent_object, ["jobSpec"]))
66
+
67
+ if getv(parent_object, ["encryptionSpec"]) is not None:
68
+ setv(to_object, ["encryption_spec"], getv(parent_object, ["encryptionSpec"]))
69
+
70
+ if getv(from_object, ["state"]) is not None:
71
+ setv(to_object, ["state"], getv(from_object, ["state"]))
72
+
73
+ if getv(parent_object, ["error"]) is not None:
74
+ setv(to_object, ["error"], getv(parent_object, ["error"]))
75
+
76
+ if getv(from_object, ["createTime"]) is not None:
77
+ setv(to_object, ["create_time"], getv(from_object, ["createTime"]))
78
+
79
+ if getv(from_object, ["endTime"]) is not None:
80
+ setv(to_object, ["end_time"], getv(from_object, ["endTime"]))
81
+
82
+ if getv(from_object, ["labels"]) is not None:
83
+ setv(to_object, ["labels"], getv(from_object, ["labels"]))
84
+
85
+ if getv(from_object, ["name"]) is not None:
86
+ setv(to_object, ["name"], getv(from_object, ["name"]))
87
+
88
+ if getv(from_object, ["satisfiesPzi"]) is not None:
89
+ setv(to_object, ["satisfies_pzi"], getv(from_object, ["satisfiesPzi"]))
90
+
91
+ if getv(from_object, ["satisfiesPzs"]) is not None:
92
+ setv(to_object, ["satisfies_pzs"], getv(from_object, ["satisfiesPzs"]))
93
+
94
+ if getv(from_object, ["startTime"]) is not None:
95
+ setv(to_object, ["start_time"], getv(from_object, ["startTime"]))
96
+
97
+ if getv(from_object, ["updateTime"]) is not None:
98
+ setv(to_object, ["update_time"], getv(from_object, ["updateTime"]))
99
+
100
+ if getv(from_object, ["webAccessUris"]) is not None:
101
+ setv(to_object, ["web_access_uris"], getv(from_object, ["webAccessUris"]))
102
+
103
+ return to_object
104
+
105
+
106
+ def _CustomJob_to_vertex(
107
+ from_object: Union[dict[str, Any], object],
108
+ parent_object: Optional[dict[str, Any]] = None,
109
+ ) -> dict[str, Any]:
110
+ to_object: dict[str, Any] = {}
111
+ if getv(from_object, ["display_name"]) is not None:
112
+ setv(parent_object, ["displayName"], getv(from_object, ["display_name"]))
113
+
114
+ if getv(from_object, ["job_spec"]) is not None:
115
+ setv(parent_object, ["jobSpec"], getv(from_object, ["job_spec"]))
116
+
117
+ if getv(from_object, ["encryption_spec"]) is not None:
118
+ setv(parent_object, ["encryptionSpec"], getv(from_object, ["encryption_spec"]))
119
+
120
+ if getv(from_object, ["state"]) is not None:
121
+ setv(to_object, ["state"], getv(from_object, ["state"]))
122
+
123
+ if getv(from_object, ["error"]) is not None:
124
+ setv(parent_object, ["error"], getv(from_object, ["error"]))
125
+
126
+ if getv(from_object, ["create_time"]) is not None:
127
+ setv(to_object, ["createTime"], getv(from_object, ["create_time"]))
128
+
129
+ if getv(from_object, ["end_time"]) is not None:
130
+ setv(to_object, ["endTime"], getv(from_object, ["end_time"]))
131
+
132
+ if getv(from_object, ["labels"]) is not None:
133
+ setv(to_object, ["labels"], getv(from_object, ["labels"]))
134
+
135
+ if getv(from_object, ["name"]) is not None:
136
+ setv(to_object, ["name"], getv(from_object, ["name"]))
137
+
138
+ if getv(from_object, ["satisfies_pzi"]) is not None:
139
+ setv(to_object, ["satisfiesPzi"], getv(from_object, ["satisfies_pzi"]))
140
+
141
+ if getv(from_object, ["satisfies_pzs"]) is not None:
142
+ setv(to_object, ["satisfiesPzs"], getv(from_object, ["satisfies_pzs"]))
143
+
144
+ if getv(from_object, ["start_time"]) is not None:
145
+ setv(to_object, ["startTime"], getv(from_object, ["start_time"]))
146
+
147
+ if getv(from_object, ["update_time"]) is not None:
148
+ setv(to_object, ["updateTime"], getv(from_object, ["update_time"]))
149
+
150
+ if getv(from_object, ["web_access_uris"]) is not None:
151
+ setv(to_object, ["webAccessUris"], getv(from_object, ["web_access_uris"]))
152
+
153
+ return to_object
154
+
155
+
156
+ def _GetCustomJobParameters_to_vertex(
157
+ from_object: Union[dict[str, Any], object],
158
+ parent_object: Optional[dict[str, Any]] = None,
159
+ ) -> dict[str, Any]:
160
+ to_object: dict[str, Any] = {}
161
+ if getv(from_object, ["name"]) is not None:
162
+ setv(to_object, ["_url", "name"], getv(from_object, ["name"]))
163
+
164
+ if getv(from_object, ["config"]) is not None:
165
+ setv(to_object, ["config"], getv(from_object, ["config"]))
166
+
167
+ return to_object
168
+
169
+
170
+ def _OptimizeConfig_to_vertex(
171
+ from_object: Union[dict[str, Any], object],
172
+ parent_object: Optional[dict[str, Any]] = None,
173
+ ) -> dict[str, Any]:
174
+ to_object: dict[str, Any] = {}
175
+
176
+ if getv(from_object, ["optimization_target"]) is not None:
177
+ setv(
178
+ parent_object,
179
+ ["optimizationTarget"],
180
+ getv(from_object, ["optimization_target"]),
181
+ )
182
+
183
+ return to_object
184
+
185
+
186
+ def _OptimizeRequestParameters_to_vertex(
187
+ from_object: Union[dict[str, Any], object],
188
+ parent_object: Optional[dict[str, Any]] = None,
189
+ ) -> dict[str, Any]:
190
+ to_object: dict[str, Any] = {}
191
+ if getv(from_object, ["content"]) is not None:
192
+ setv(to_object, ["content"], getv(from_object, ["content"]))
193
+
194
+ if getv(from_object, ["config"]) is not None:
195
+ setv(
196
+ to_object,
197
+ ["config"],
198
+ _OptimizeConfig_to_vertex(getv(from_object, ["config"]), to_object),
199
+ )
200
+
201
+ return to_object
202
+
203
+
204
+ class PromptOptimizer(_api_module.BaseModule):
205
+ """Prompt Optimizer"""
206
+
207
+ def _optimize_prompt(
208
+ self,
209
+ *,
210
+ content: Optional[genai_types.ContentOrDict] = None,
211
+ config: Optional[types.OptimizeConfigOrDict] = None,
212
+ ) -> types.OptimizeResponseEndpoint:
213
+ """
214
+ Optimize a single prompt.
215
+ """
216
+
217
+ parameter_model = types._OptimizeRequestParameters(
218
+ content=content,
219
+ config=config,
220
+ )
221
+
222
+ request_url_dict: Optional[dict[str, str]]
223
+ if not self._api_client.vertexai:
224
+ raise ValueError(
225
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
226
+ )
227
+ else:
228
+ request_dict = _OptimizeRequestParameters_to_vertex(parameter_model)
229
+ request_url_dict = request_dict.get("_url")
230
+ if request_url_dict:
231
+ path = "tuningJobs:optimizePrompt".format_map(request_url_dict)
232
+ else:
233
+ path = "tuningJobs:optimizePrompt"
234
+
235
+ query_params = request_dict.get("_query")
236
+ if query_params:
237
+ path = f"{path}?{urlencode(query_params)}"
238
+ # TODO: remove the hack that pops config.
239
+ request_dict.pop("config", None)
240
+
241
+ http_options: Optional[types.HttpOptions] = None
242
+ if (
243
+ parameter_model.config is not None
244
+ and parameter_model.config.http_options is not None
245
+ ):
246
+ http_options = parameter_model.config.http_options
247
+
248
+ request_dict = _common.convert_to_dict(request_dict)
249
+ request_dict = _common.encode_unserializable_types(request_dict)
250
+
251
+ response = self._api_client.request("post", path, request_dict, http_options)
252
+
253
+ response_dict = {} if not response.body else json.loads(response.body)
254
+
255
+ return_value = types.OptimizeResponseEndpoint._from_response(
256
+ response=response_dict,
257
+ kwargs=(
258
+ {
259
+ "config": {
260
+ "response_schema": getattr(
261
+ parameter_model.config, "response_schema", None
262
+ ),
263
+ "response_json_schema": getattr(
264
+ parameter_model.config, "response_json_schema", None
265
+ ),
266
+ "include_all_fields": getattr(
267
+ parameter_model.config, "include_all_fields", None
268
+ ),
269
+ }
270
+ }
271
+ if getattr(parameter_model, "config", None)
272
+ else {}
273
+ ),
274
+ )
275
+
276
+ self._api_client._verify_response(return_value)
277
+ return return_value
278
+
279
+ def _create_custom_job_resource(
280
+ self,
281
+ *,
282
+ custom_job: types.CustomJobOrDict,
283
+ config: Optional[types.VertexBaseConfigOrDict] = None,
284
+ ) -> types.CustomJob:
285
+ """
286
+ Creates a custom job.
287
+ """
288
+
289
+ parameter_model = types._CustomJobParameters(
290
+ custom_job=custom_job,
291
+ config=config,
292
+ )
293
+
294
+ request_url_dict: Optional[dict[str, str]]
295
+ if not self._api_client.vertexai:
296
+ raise ValueError(
297
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
298
+ )
299
+ else:
300
+ request_dict = _CustomJobParameters_to_vertex(parameter_model)
301
+ request_url_dict = request_dict.get("_url")
302
+ if request_url_dict:
303
+ path = "customJobs".format_map(request_url_dict)
304
+ else:
305
+ path = "customJobs"
306
+
307
+ query_params = request_dict.get("_query")
308
+ if query_params:
309
+ path = f"{path}?{urlencode(query_params)}"
310
+ # TODO: remove the hack that pops config.
311
+ request_dict.pop("config", None)
312
+
313
+ http_options: Optional[types.HttpOptions] = None
314
+ if (
315
+ parameter_model.config is not None
316
+ and parameter_model.config.http_options is not None
317
+ ):
318
+ http_options = parameter_model.config.http_options
319
+
320
+ request_dict = _common.convert_to_dict(request_dict)
321
+ request_dict = _common.encode_unserializable_types(request_dict)
322
+
323
+ response = self._api_client.request("post", path, request_dict, http_options)
324
+
325
+ response_dict = {} if not response.body else json.loads(response.body)
326
+
327
+ if self._api_client.vertexai:
328
+ response_dict = _CustomJob_from_vertex(response_dict)
329
+
330
+ return_value = types.CustomJob._from_response(
331
+ response=response_dict,
332
+ kwargs=(
333
+ {
334
+ "config": {
335
+ "response_schema": getattr(
336
+ parameter_model.config, "response_schema", None
337
+ ),
338
+ "response_json_schema": getattr(
339
+ parameter_model.config, "response_json_schema", None
340
+ ),
341
+ "include_all_fields": getattr(
342
+ parameter_model.config, "include_all_fields", None
343
+ ),
344
+ }
345
+ }
346
+ if getattr(parameter_model, "config", None)
347
+ else {}
348
+ ),
349
+ )
350
+
351
+ self._api_client._verify_response(return_value)
352
+ return return_value
353
+
354
+ def _get_custom_job(
355
+ self, *, name: str, config: Optional[types.VertexBaseConfigOrDict] = None
356
+ ) -> types.CustomJob:
357
+ """
358
+ Gets a custom job.
359
+ """
360
+
361
+ parameter_model = types._GetCustomJobParameters(
362
+ name=name,
363
+ config=config,
364
+ )
365
+
366
+ request_url_dict: Optional[dict[str, str]]
367
+ if not self._api_client.vertexai:
368
+ raise ValueError(
369
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
370
+ )
371
+ else:
372
+ request_dict = _GetCustomJobParameters_to_vertex(parameter_model)
373
+ request_url_dict = request_dict.get("_url")
374
+ if request_url_dict:
375
+ path = "customJobs/{name}".format_map(request_url_dict)
376
+ else:
377
+ path = "customJobs/{name}"
378
+
379
+ query_params = request_dict.get("_query")
380
+ if query_params:
381
+ path = f"{path}?{urlencode(query_params)}"
382
+ # TODO: remove the hack that pops config.
383
+ request_dict.pop("config", None)
384
+
385
+ http_options: Optional[types.HttpOptions] = None
386
+ if (
387
+ parameter_model.config is not None
388
+ and parameter_model.config.http_options is not None
389
+ ):
390
+ http_options = parameter_model.config.http_options
391
+
392
+ request_dict = _common.convert_to_dict(request_dict)
393
+ request_dict = _common.encode_unserializable_types(request_dict)
394
+
395
+ response = self._api_client.request("get", path, request_dict, http_options)
396
+
397
+ response_dict = {} if not response.body else json.loads(response.body)
398
+
399
+ if self._api_client.vertexai:
400
+ response_dict = _CustomJob_from_vertex(response_dict)
401
+
402
+ return_value = types.CustomJob._from_response(
403
+ response=response_dict,
404
+ kwargs=(
405
+ {
406
+ "config": {
407
+ "response_schema": getattr(
408
+ parameter_model.config, "response_schema", None
409
+ ),
410
+ "response_json_schema": getattr(
411
+ parameter_model.config, "response_json_schema", None
412
+ ),
413
+ "include_all_fields": getattr(
414
+ parameter_model.config, "include_all_fields", None
415
+ ),
416
+ }
417
+ }
418
+ if getattr(parameter_model, "config", None)
419
+ else {}
420
+ ),
421
+ )
422
+
423
+ self._api_client._verify_response(return_value)
424
+ return return_value
425
+
426
+ """Prompt Optimizer PO-Data."""
427
+
428
+ def _wait_for_completion(self, job_name: str) -> types.CustomJob:
429
+
430
+ JOB_COMPLETE_STATES = [
431
+ genai_types.JobState.JOB_STATE_SUCCEEDED,
432
+ genai_types.JobState.JOB_STATE_FAILED,
433
+ genai_types.JobState.JOB_STATE_CANCELLED,
434
+ genai_types.JobState.JOB_STATE_PAUSED,
435
+ ]
436
+ JOB_ERROR_STATES = [
437
+ genai_types.JobState.JOB_STATE_FAILED,
438
+ genai_types.JobState.JOB_STATE_CANCELLED,
439
+ ]
440
+
441
+ log_wait = 5
442
+ wait_multiplier = 2
443
+ max_wait_time = 60
444
+ previous_time = time.time()
445
+
446
+ job = self._get_custom_job(name=job_name)
447
+
448
+ while job.state not in JOB_COMPLETE_STATES:
449
+ current_time = time.time()
450
+ if current_time - previous_time >= log_wait:
451
+ logger.info(f"Waiting for job to complete. Current state: {job.state}")
452
+ log_wait = min(log_wait * wait_multiplier, max_wait_time)
453
+ previous_time = current_time
454
+ time.sleep(log_wait)
455
+ job = self._get_custom_job(name=job_name)
456
+
457
+ logger.info(f"Job state: {job.state}")
458
+
459
+ if job.state in JOB_ERROR_STATES:
460
+ raise RuntimeError(f"Job failed with state: {job.state}")
461
+ else:
462
+ logger.info(f"Job completed with state: {job.state}")
463
+ return job
464
+
465
+ @_logging_utils.show_deprecation_warning_once(
466
+ "The prompt_optimizer.optimize method is deprecated. Please use"
467
+ " prompts.launch_optimization_job instead."
468
+ )
469
+ def optimize(
470
+ self,
471
+ method: types.PromptOptimizerMethod,
472
+ config: types.PromptOptimizerConfigOrDict,
473
+ ) -> types.CustomJob:
474
+ """Call PO-Data optimizer.
475
+
476
+ Args:
477
+ method: The method for optimizing multiple prompts. Supported methods:
478
+ VAPO, OPTIMIZATION_TARGET_GEMINI_NANO.
479
+ config: PromptOptimizerConfig instance containing the
480
+ configuration for prompt optimization.
481
+ Returns:
482
+ The custom job that was created.
483
+ """
484
+ prompts_module = prompts.Prompts(api_client_=self._api_client)
485
+
486
+ return prompts_module.launch_optimization_job( # type: ignore[no-any-return]
487
+ method=method, config=config
488
+ )
489
+
490
+ @_logging_utils.show_deprecation_warning_once(
491
+ "The prompt_optimizer.optimize_prompt method is deprecated. Please use"
492
+ " prompts.optimize instead."
493
+ )
494
+ def optimize_prompt(
495
+ self,
496
+ *,
497
+ prompt: str,
498
+ config: Optional[types.OptimizeConfigOrDict] = None,
499
+ ) -> types.OptimizeResponse:
500
+ """Makes an API request to _optimize_prompt and returns the parsed response.
501
+
502
+ Example usage:
503
+ client = agentplatform.Client(project=PROJECT_NAME, location='us-central1')
504
+ prompt = "Generate system instructions for analyzing medical articles"
505
+ response = client.prompt_optimizer.optimize_prompt(prompt=prompt)
506
+ print(response.suggested_prompt)
507
+
508
+ Args:
509
+ prompt: The prompt to optimize.
510
+ config: Optional.The configuration for prompt optimization. To optimize
511
+ prompts from Android API provide
512
+ types.OptimizeConfig(
513
+ optimization_target=types.OptimizeTarget.OPTIMIZATION_TARGET_GEMINI_NANO
514
+ )
515
+ For few-shot optimization, provide:
516
+
517
+ optim_target = types.OptimizeTarget.OPTIMIZATION_TARGET_FEW_SHOT_RUBRICS
518
+ or
519
+ optim_target = types.OptimizeTarget.OPTIMIZATION_TARGET_FEW_SHOT_TARGET_RESPONSE
520
+ types.OptimizeConfig(
521
+ optimization_target=optim_target,
522
+ examples_dataframe=dataframe
523
+ )
524
+ OPTIMIZATION_TARGET_FEW_SHOT_RUBRICS indicates that the few-shot
525
+ examples include specific scoring rubrics and their corresponding
526
+ evaluations.
527
+ OPTIMIZATION_TARGET_FEW_SHOT_TARGET_RESPONSE indicates that the few-shot
528
+ examples include a ground-truth target response.
529
+ Returns:
530
+ The parsed response from the API request.
531
+ """
532
+ prompts_module = prompts.Prompts(api_client_=self._api_client)
533
+
534
+ return prompts_module.optimize( # type: ignore[no-any-return]
535
+ prompt=prompt, config=config
536
+ )
537
+
538
+ def _custom_optimize_prompt(
539
+ self,
540
+ *,
541
+ content: Optional[genai_types.ContentOrDict] = None,
542
+ config: Optional[types.OptimizeConfigOrDict] = None,
543
+ ) -> types.OptimizeResponse:
544
+ """Optimize a single prompt.
545
+
546
+ Sends a request to the tuningJobs:optimizePrompt streaming endpoint.
547
+ Then gathers the response, concatenates into one string and returns
548
+ the parsed response.
549
+ """
550
+ if isinstance(config, dict):
551
+ config.pop("examples_dataframe", None)
552
+ elif config and hasattr(config, "examples_dataframe"):
553
+ del config.examples_dataframe
554
+
555
+ parameter_model = types._OptimizeRequestParameters(
556
+ content=content,
557
+ config=config,
558
+ )
559
+ request_url_dict: Optional[dict[str, str]]
560
+ if not self._api_client.vertexai:
561
+ raise ValueError("This method is only supported in the Vertex AI client.")
562
+ else:
563
+ request_dict = _OptimizeRequestParameters_to_vertex(parameter_model)
564
+ request_url_dict = request_dict.get("_url")
565
+ if request_url_dict:
566
+ path = "tuningJobs:optimizePrompt".format_map(request_url_dict)
567
+ else:
568
+ path = "tuningJobs:optimizePrompt"
569
+
570
+ query_params = request_dict.get("_query")
571
+ if query_params:
572
+ path = f"{path}?{urlencode(query_params)}"
573
+ # TODO: remove the hack that pops config.
574
+ request_dict.pop("config", None)
575
+
576
+ http_options: Optional[genai_types.HttpOptions] = None
577
+ if (
578
+ parameter_model.config is not None
579
+ and parameter_model.config.http_options is not None
580
+ ):
581
+ http_options = parameter_model.config.http_options
582
+
583
+ request_dict = _common.convert_to_dict(request_dict)
584
+ request_dict = _common.encode_unserializable_types(request_dict)
585
+
586
+ response = self._api_client.request("post", path, request_dict, http_options)
587
+
588
+ response_list = "" if not response.body else json.loads(response.body)
589
+
590
+ return_value = []
591
+
592
+ for response_dict in response_list:
593
+ response_value = types.OptimizeResponseEndpoint._from_response(
594
+ response=response_dict, kwargs=parameter_model.model_dump()
595
+ )
596
+ self._api_client._verify_response(response_value)
597
+ content = response_value.content
598
+ if content is not None:
599
+ parts = content.parts
600
+ if parts and parts[0].text is not None:
601
+ return_value.append(parts[0].text)
602
+
603
+ output = "".join(return_value)
604
+ final_response = types.OptimizeResponse(raw_text_response=output)
605
+ try:
606
+ final_response.parsed_response = _prompt_optimizer_utils._parse(output)
607
+ except Exception as e:
608
+ logger.warning(
609
+ f"Failed to parse response: {e}. Returning only raw_text_response."
610
+ )
611
+ return final_response
612
+
613
+
614
+ class AsyncPromptOptimizer(_api_module.BaseModule):
615
+ """Prompt Optimizer"""
616
+
617
+ async def _optimize_prompt(
618
+ self,
619
+ *,
620
+ content: Optional[genai_types.ContentOrDict] = None,
621
+ config: Optional[types.OptimizeConfigOrDict] = None,
622
+ ) -> types.OptimizeResponseEndpoint:
623
+ """
624
+ Optimize a single prompt.
625
+ """
626
+
627
+ parameter_model = types._OptimizeRequestParameters(
628
+ content=content,
629
+ config=config,
630
+ )
631
+
632
+ request_url_dict: Optional[dict[str, str]]
633
+ if not self._api_client.vertexai:
634
+ raise ValueError(
635
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
636
+ )
637
+ else:
638
+ request_dict = _OptimizeRequestParameters_to_vertex(parameter_model)
639
+ request_url_dict = request_dict.get("_url")
640
+ if request_url_dict:
641
+ path = "tuningJobs:optimizePrompt".format_map(request_url_dict)
642
+ else:
643
+ path = "tuningJobs:optimizePrompt"
644
+
645
+ query_params = request_dict.get("_query")
646
+ if query_params:
647
+ path = f"{path}?{urlencode(query_params)}"
648
+ # TODO: remove the hack that pops config.
649
+ request_dict.pop("config", None)
650
+
651
+ http_options: Optional[types.HttpOptions] = None
652
+ if (
653
+ parameter_model.config is not None
654
+ and parameter_model.config.http_options is not None
655
+ ):
656
+ http_options = parameter_model.config.http_options
657
+
658
+ request_dict = _common.convert_to_dict(request_dict)
659
+ request_dict = _common.encode_unserializable_types(request_dict)
660
+
661
+ response = await self._api_client.async_request(
662
+ "post", path, request_dict, http_options
663
+ )
664
+
665
+ response_dict = {} if not response.body else json.loads(response.body)
666
+
667
+ return_value = types.OptimizeResponseEndpoint._from_response(
668
+ response=response_dict,
669
+ kwargs=(
670
+ {
671
+ "config": {
672
+ "response_schema": getattr(
673
+ parameter_model.config, "response_schema", None
674
+ ),
675
+ "response_json_schema": getattr(
676
+ parameter_model.config, "response_json_schema", None
677
+ ),
678
+ "include_all_fields": getattr(
679
+ parameter_model.config, "include_all_fields", None
680
+ ),
681
+ }
682
+ }
683
+ if getattr(parameter_model, "config", None)
684
+ else {}
685
+ ),
686
+ )
687
+
688
+ self._api_client._verify_response(return_value)
689
+ return return_value
690
+
691
+ async def _create_custom_job_resource(
692
+ self,
693
+ *,
694
+ custom_job: types.CustomJobOrDict,
695
+ config: Optional[types.VertexBaseConfigOrDict] = None,
696
+ ) -> types.CustomJob:
697
+ """
698
+ Creates a custom job.
699
+ """
700
+
701
+ parameter_model = types._CustomJobParameters(
702
+ custom_job=custom_job,
703
+ config=config,
704
+ )
705
+
706
+ request_url_dict: Optional[dict[str, str]]
707
+ if not self._api_client.vertexai:
708
+ raise ValueError(
709
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
710
+ )
711
+ else:
712
+ request_dict = _CustomJobParameters_to_vertex(parameter_model)
713
+ request_url_dict = request_dict.get("_url")
714
+ if request_url_dict:
715
+ path = "customJobs".format_map(request_url_dict)
716
+ else:
717
+ path = "customJobs"
718
+
719
+ query_params = request_dict.get("_query")
720
+ if query_params:
721
+ path = f"{path}?{urlencode(query_params)}"
722
+ # TODO: remove the hack that pops config.
723
+ request_dict.pop("config", None)
724
+
725
+ http_options: Optional[types.HttpOptions] = None
726
+ if (
727
+ parameter_model.config is not None
728
+ and parameter_model.config.http_options is not None
729
+ ):
730
+ http_options = parameter_model.config.http_options
731
+
732
+ request_dict = _common.convert_to_dict(request_dict)
733
+ request_dict = _common.encode_unserializable_types(request_dict)
734
+
735
+ response = await self._api_client.async_request(
736
+ "post", path, request_dict, http_options
737
+ )
738
+
739
+ response_dict = {} if not response.body else json.loads(response.body)
740
+
741
+ if self._api_client.vertexai:
742
+ response_dict = _CustomJob_from_vertex(response_dict)
743
+
744
+ return_value = types.CustomJob._from_response(
745
+ response=response_dict,
746
+ kwargs=(
747
+ {
748
+ "config": {
749
+ "response_schema": getattr(
750
+ parameter_model.config, "response_schema", None
751
+ ),
752
+ "response_json_schema": getattr(
753
+ parameter_model.config, "response_json_schema", None
754
+ ),
755
+ "include_all_fields": getattr(
756
+ parameter_model.config, "include_all_fields", None
757
+ ),
758
+ }
759
+ }
760
+ if getattr(parameter_model, "config", None)
761
+ else {}
762
+ ),
763
+ )
764
+
765
+ self._api_client._verify_response(return_value)
766
+ return return_value
767
+
768
+ async def _get_custom_job(
769
+ self, *, name: str, config: Optional[types.VertexBaseConfigOrDict] = None
770
+ ) -> types.CustomJob:
771
+ """
772
+ Gets a custom job.
773
+ """
774
+
775
+ parameter_model = types._GetCustomJobParameters(
776
+ name=name,
777
+ config=config,
778
+ )
779
+
780
+ request_url_dict: Optional[dict[str, str]]
781
+ if not self._api_client.vertexai:
782
+ raise ValueError(
783
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
784
+ )
785
+ else:
786
+ request_dict = _GetCustomJobParameters_to_vertex(parameter_model)
787
+ request_url_dict = request_dict.get("_url")
788
+ if request_url_dict:
789
+ path = "customJobs/{name}".format_map(request_url_dict)
790
+ else:
791
+ path = "customJobs/{name}"
792
+
793
+ query_params = request_dict.get("_query")
794
+ if query_params:
795
+ path = f"{path}?{urlencode(query_params)}"
796
+ # TODO: remove the hack that pops config.
797
+ request_dict.pop("config", None)
798
+
799
+ http_options: Optional[types.HttpOptions] = None
800
+ if (
801
+ parameter_model.config is not None
802
+ and parameter_model.config.http_options is not None
803
+ ):
804
+ http_options = parameter_model.config.http_options
805
+
806
+ request_dict = _common.convert_to_dict(request_dict)
807
+ request_dict = _common.encode_unserializable_types(request_dict)
808
+
809
+ response = await self._api_client.async_request(
810
+ "get", path, request_dict, http_options
811
+ )
812
+
813
+ response_dict = {} if not response.body else json.loads(response.body)
814
+
815
+ if self._api_client.vertexai:
816
+ response_dict = _CustomJob_from_vertex(response_dict)
817
+
818
+ return_value = types.CustomJob._from_response(
819
+ response=response_dict,
820
+ kwargs=(
821
+ {
822
+ "config": {
823
+ "response_schema": getattr(
824
+ parameter_model.config, "response_schema", None
825
+ ),
826
+ "response_json_schema": getattr(
827
+ parameter_model.config, "response_json_schema", None
828
+ ),
829
+ "include_all_fields": getattr(
830
+ parameter_model.config, "include_all_fields", None
831
+ ),
832
+ }
833
+ }
834
+ if getattr(parameter_model, "config", None)
835
+ else {}
836
+ ),
837
+ )
838
+
839
+ self._api_client._verify_response(return_value)
840
+ return return_value
841
+
842
+ # Todo: b/428953357 - Add example in the README.
843
+ @_logging_utils.show_deprecation_warning_once(
844
+ "The prompt_optimizer.optimize method is deprecated. Please use"
845
+ " prompts.launch_optimization_job instead."
846
+ )
847
+ async def optimize(
848
+ self,
849
+ method: types.PromptOptimizerMethod,
850
+ config: types.PromptOptimizerConfigOrDict,
851
+ ) -> types.CustomJob:
852
+ """Call async Vertex AI Prompt Optimizer (VAPO).
853
+
854
+
855
+ Note: The `wait_for_completion` parameter in the config will be
856
+ ignored when using the AsyncClient, as it is not supported.
857
+
858
+ Example usage:
859
+ client = agentplatform.Client(project=PROJECT_NAME, location='us-central1')
860
+ vapo_config = agentplatform.types.PromptOptimizerConfig(
861
+ config_path='gs://you-bucket-name/your-config.json',
862
+ service_account=service_account,
863
+ )
864
+ job = await client.aio.prompt_optimizer.optimize(
865
+ method=types.PromptOptimizerMethod.VAPO, config=vapo_config)
866
+
867
+ Args:
868
+ method: The method for optimizing multiple prompts. Supported methods:
869
+ VAPO, OPTIMIZATION_TARGET_GEMINI_NANO.
870
+ config: PromptOptimizerConfig instance containing the
871
+ configuration for prompt optimization.
872
+ Returns:
873
+ The custom job that was created.
874
+ """
875
+ prompts_module = prompts.AsyncPrompts(api_client_=self._api_client)
876
+
877
+ return await prompts_module.launch_optimization_job( # type: ignore[no-any-return]
878
+ method=method, config=config
879
+ )
880
+
881
+ async def _custom_optimize_prompt(
882
+ self,
883
+ *,
884
+ content: Optional[genai_types.ContentOrDict] = None,
885
+ config: Optional[types.OptimizeConfigOrDict] = None,
886
+ ) -> types.OptimizeResponse:
887
+ """Optimize a single prompt."""
888
+ if isinstance(config, dict):
889
+ config.pop("examples_dataframe", None)
890
+ elif config and hasattr(config, "examples_dataframe"):
891
+ del config.examples_dataframe
892
+
893
+ parameter_model = types._OptimizeRequestParameters(
894
+ content=content,
895
+ config=config,
896
+ )
897
+ request_url_dict: Optional[dict[str, str]]
898
+ if not self._api_client.vertexai:
899
+ raise ValueError("This method is only supported in the Vertex AI client.")
900
+ else:
901
+ request_dict = _OptimizeRequestParameters_to_vertex(parameter_model)
902
+ request_url_dict = request_dict.get("_url")
903
+ if request_url_dict:
904
+ path = "tuningJobs:optimizePrompt".format_map(request_url_dict)
905
+ else:
906
+ path = "tuningJobs:optimizePrompt"
907
+
908
+ query_params = request_dict.get("_query")
909
+ if query_params:
910
+ path = f"{path}?{urlencode(query_params)}"
911
+ # TODO: remove the hack that pops config.
912
+ request_dict.pop("config", None)
913
+
914
+ http_options: Optional[types.HttpOptions] = None
915
+ if (
916
+ parameter_model.config is not None
917
+ and parameter_model.config.http_options is not None
918
+ ):
919
+ http_options = parameter_model.config.http_options
920
+
921
+ request_dict = _common.convert_to_dict(request_dict)
922
+ request_dict = _common.encode_unserializable_types(request_dict)
923
+
924
+ response = await self._api_client.async_request(
925
+ "post", path, request_dict, http_options
926
+ )
927
+
928
+ response_list = "" if not response.body else json.loads(response.body)
929
+
930
+ return_value = []
931
+
932
+ for response_dict in response_list:
933
+ response_value = types.OptimizeResponseEndpoint._from_response(
934
+ response=response_dict, kwargs=parameter_model.model_dump()
935
+ )
936
+ self._api_client._verify_response(response_value)
937
+ content = response_value.content
938
+ if content is not None:
939
+ parts = content.parts
940
+ if parts and parts[0].text is not None:
941
+ return_value.append(parts[0].text)
942
+
943
+ output = "".join(return_value)
944
+ final_response = types.OptimizeResponse(raw_text_response=output)
945
+ try:
946
+ final_response.parsed_response = _prompt_optimizer_utils._parse(output)
947
+ except Exception as e:
948
+ logger.warning(
949
+ f"Failed to parse response: {e}. Returning only raw_text_response."
950
+ )
951
+ return final_response
952
+
953
+ @_logging_utils.show_deprecation_warning_once(
954
+ "The prompt_optimizer.optimize_prompt method is deprecated. Please use"
955
+ " prompts.optimize instead."
956
+ )
957
+ async def optimize_prompt(
958
+ self,
959
+ *,
960
+ prompt: str,
961
+ config: Optional[types.OptimizeConfigOrDict] = None,
962
+ ) -> types.OptimizeResponse:
963
+ """Makes an async request to _optimize_prompt and returns an optimized prompt.
964
+
965
+ Example usage:
966
+ client = agentplatform.Client(project=PROJECT_NAME, location='us-central1')
967
+ prompt = "Generate system instructions for analyzing medical articles"
968
+ response = await client.aio.prompt_optimizer.optimize_prompt(prompt=prompt)
969
+
970
+ Args:
971
+ prompt: The prompt to optimize.
972
+ config: Optional.The configuration for prompt optimization. To optimize
973
+ prompts from Android API provide
974
+ types.OptimizeConfig(
975
+ optimization_target=types.OptimizeTarget.OPTIMIZATION_TARGET_GEMINI_NANO
976
+ )
977
+ For few-shot optimization, provide:
978
+ optim_target = types.OptimizeTarget.OPTIMIZATION_TARGET_FEW_SHOT_RUBRICS # or types.OptimizeTarget.OPTIMIZATION_TARGET_FEW_SHOT_TARGET_RESPONSE
979
+ types.OptimizeConfig(
980
+ optimization_target=optim_target,
981
+ examples_dataframe=dataframe
982
+ )
983
+ OPTIMIZATION_TARGET_FEW_SHOT_RUBRICS indicates that the few-shot
984
+ examples include specific scoring rubrics and their corresponding
985
+ evaluations.
986
+ OPTIMIZATION_TARGET_FEW_SHOT_TARGET_RESPONSE indicates that the few-shot
987
+ examples include a ground-truth target response.
988
+ Returns:
989
+ The parsed response from the API request.
990
+ """
991
+ prompts_module = prompts.AsyncPrompts(api_client_=self._api_client)
992
+
993
+ return await prompts_module.optimize( # type: ignore[no-any-return]
994
+ prompt=prompt, config=config
995
+ )