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.
- agentplatform/__init__.py +72 -0
- agentplatform/_genai/__init__.py +43 -0
- agentplatform/_genai/_agent_engines_utils.py +2341 -0
- agentplatform/_genai/_bigquery_utils.py +49 -0
- agentplatform/_genai/_datasets_utils.py +344 -0
- agentplatform/_genai/_evals_builtin_tools.py +209 -0
- agentplatform/_genai/_evals_common.py +4268 -0
- agentplatform/_genai/_evals_constant.py +122 -0
- agentplatform/_genai/_evals_data_converters.py +926 -0
- agentplatform/_genai/_evals_metric_handlers.py +1783 -0
- agentplatform/_genai/_evals_metric_loaders.py +401 -0
- agentplatform/_genai/_evals_utils.py +1043 -0
- agentplatform/_genai/_evals_visualization.py +2070 -0
- agentplatform/_genai/_gcs_utils.py +262 -0
- agentplatform/_genai/_logging_utils.py +47 -0
- agentplatform/_genai/_memory_bank_utils.py +206 -0
- agentplatform/_genai/_observability_data_converter.py +186 -0
- agentplatform/_genai/_operations_utils.py +94 -0
- agentplatform/_genai/_prompt_management_utils.py +147 -0
- agentplatform/_genai/_prompt_optimizer_utils.py +215 -0
- agentplatform/_genai/_skills_utils.py +69 -0
- agentplatform/_genai/_transformers.py +628 -0
- agentplatform/_genai/a2a_task_events.py +509 -0
- agentplatform/_genai/a2a_tasks.py +861 -0
- agentplatform/_genai/agent_engines.py +3931 -0
- agentplatform/_genai/client.py +519 -0
- agentplatform/_genai/datasets.py +3045 -0
- agentplatform/_genai/endpoints.py +1149 -0
- agentplatform/_genai/evals.py +6883 -0
- agentplatform/_genai/example_stores.py +1445 -0
- agentplatform/_genai/feedback_contexts.py +700 -0
- agentplatform/_genai/feedback_entries.py +1644 -0
- agentplatform/_genai/live.py +64 -0
- agentplatform/_genai/live_agent_engines.py +179 -0
- agentplatform/_genai/memories.py +2962 -0
- agentplatform/_genai/memory_banks.py +1927 -0
- agentplatform/_genai/memory_revisions.py +465 -0
- agentplatform/_genai/model_garden.py +2638 -0
- agentplatform/_genai/prompt_optimizer.py +995 -0
- agentplatform/_genai/prompts.py +4515 -0
- agentplatform/_genai/rag.py +4961 -0
- agentplatform/_genai/runtime_revisions.py +1257 -0
- agentplatform/_genai/runtimes.py +78 -0
- agentplatform/_genai/sandbox_snapshots.py +1015 -0
- agentplatform/_genai/sandbox_templates.py +1088 -0
- agentplatform/_genai/sandboxes.py +1604 -0
- agentplatform/_genai/session_events.py +543 -0
- agentplatform/_genai/sessions.py +1449 -0
- agentplatform/_genai/skill_revisions.py +377 -0
- agentplatform/_genai/skills.py +1708 -0
- agentplatform/_genai/types/__init__.py +4695 -0
- agentplatform/_genai/types/agent_engines.py +16 -0
- agentplatform/_genai/types/common.py +32784 -0
- agentplatform/_genai/types/evals.py +1031 -0
- agentplatform/_genai/types/prompt_optimizer.py +107 -0
- agentplatform/_genai/types/prompts.py +107 -0
- agentplatform/version.py +17 -0
- google_cloud_agentplatform-1.165.1.dev0.dist-info/METADATA +79 -0
- google_cloud_agentplatform-1.165.1.dev0.dist-info/RECORD +62 -0
- google_cloud_agentplatform-1.165.1.dev0.dist-info/WHEEL +5 -0
- google_cloud_agentplatform-1.165.1.dev0.dist-info/licenses/LICENSE +202 -0
- 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
|
+
)
|