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,1149 @@
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
+ from typing import Any, Optional, Union
21
+ from urllib.parse import urlencode
22
+
23
+ from google.genai import _api_module
24
+ from google.genai import _common
25
+ from google.genai import types as genai_types
26
+ from google.genai._common import get_value_by_path as getv
27
+ from google.genai._common import set_value_by_path as setv
28
+
29
+ from . import _operations_utils
30
+ from . import _transformers as t
31
+ from . import types
32
+
33
+ logger = logging.getLogger("agentplatform_genai.endpoints")
34
+
35
+
36
+ def _DeleteEndpointRequestParameters_to_vertex(
37
+ from_object: Union[dict[str, Any], object],
38
+ parent_object: Optional[dict[str, Any]] = None,
39
+ ) -> dict[str, Any]:
40
+ to_object: dict[str, Any] = {}
41
+ if getv(from_object, ["name"]) is not None:
42
+ setv(
43
+ to_object,
44
+ ["_url", "name"],
45
+ t.t_strict_endpoint(getv(from_object, ["name"])),
46
+ )
47
+
48
+ return to_object
49
+
50
+
51
+ def _GetEndpointOperationParameters_to_vertex(
52
+ from_object: Union[dict[str, Any], object],
53
+ parent_object: Optional[dict[str, Any]] = None,
54
+ ) -> dict[str, Any]:
55
+ to_object: dict[str, Any] = {}
56
+ if getv(from_object, ["operation_name"]) is not None:
57
+ setv(
58
+ to_object, ["_url", "operationName"], getv(from_object, ["operation_name"])
59
+ )
60
+
61
+ return to_object
62
+
63
+
64
+ def _GetEndpointParameters_to_vertex(
65
+ from_object: Union[dict[str, Any], object],
66
+ parent_object: Optional[dict[str, Any]] = None,
67
+ ) -> dict[str, Any]:
68
+ to_object: dict[str, Any] = {}
69
+ if getv(from_object, ["name"]) is not None:
70
+ setv(
71
+ to_object,
72
+ ["_url", "name"],
73
+ t.t_strict_endpoint(getv(from_object, ["name"])),
74
+ )
75
+
76
+ return to_object
77
+
78
+
79
+ def _PredictConfig_to_vertex(
80
+ from_object: Union[dict[str, Any], object],
81
+ parent_object: Optional[dict[str, Any]] = None,
82
+ ) -> dict[str, Any]:
83
+ to_object: dict[str, Any] = {}
84
+
85
+ if getv(from_object, ["parameters"]) is not None:
86
+ setv(parent_object, ["parameters"], getv(from_object, ["parameters"]))
87
+
88
+ return to_object
89
+
90
+
91
+ def _PredictParameters_to_vertex(
92
+ from_object: Union[dict[str, Any], object],
93
+ parent_object: Optional[dict[str, Any]] = None,
94
+ ) -> dict[str, Any]:
95
+ to_object: dict[str, Any] = {}
96
+ if getv(from_object, ["name"]) is not None:
97
+ setv(to_object, ["_url", "endpoint"], t.t_endpoint(getv(from_object, ["name"])))
98
+
99
+ if getv(from_object, ["instances"]) is not None:
100
+ setv(to_object, ["instances"], getv(from_object, ["instances"]))
101
+
102
+ if getv(from_object, ["config"]) is not None:
103
+ _PredictConfig_to_vertex(getv(from_object, ["config"]), to_object)
104
+
105
+ return to_object
106
+
107
+
108
+ def _UndeployModelRequestParameters_to_vertex(
109
+ from_object: Union[dict[str, Any], object],
110
+ parent_object: Optional[dict[str, Any]] = None,
111
+ ) -> dict[str, Any]:
112
+ to_object: dict[str, Any] = {}
113
+ if getv(from_object, ["name"]) is not None:
114
+ setv(
115
+ to_object,
116
+ ["_url", "endpoint"],
117
+ t.t_strict_endpoint(getv(from_object, ["name"])),
118
+ )
119
+
120
+ if getv(from_object, ["deployed_model_id"]) is not None:
121
+ setv(to_object, ["deployed_model_id"], getv(from_object, ["deployed_model_id"]))
122
+
123
+ return to_object
124
+
125
+
126
+ class Endpoints(_api_module.BaseModule):
127
+ """Class for managing Endpoints for prediction, undeployment, and deletion."""
128
+
129
+ def _undeploy(
130
+ self,
131
+ *,
132
+ name: str,
133
+ deployed_model_id: str,
134
+ config: Optional[types.UndeployModelConfigOrDict] = None,
135
+ ) -> types.UndeployModelOperation:
136
+ """
137
+ Undeploys a Model from an Endpoint, removing a
138
+ DeployedModel from it, and freeing all resources it's using.
139
+ """
140
+
141
+ parameter_model = types._UndeployModelRequestParameters(
142
+ name=name,
143
+ deployed_model_id=deployed_model_id,
144
+ config=config,
145
+ )
146
+
147
+ request_url_dict: Optional[dict[str, str]]
148
+ if not self._api_client.vertexai:
149
+ raise ValueError(
150
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
151
+ )
152
+ else:
153
+ request_dict = _UndeployModelRequestParameters_to_vertex(parameter_model)
154
+ request_url_dict = request_dict.get("_url")
155
+ if request_url_dict:
156
+ path = "{endpoint}:undeployModel".format_map(request_url_dict)
157
+ else:
158
+ path = "{endpoint}:undeployModel"
159
+
160
+ query_params = request_dict.get("_query")
161
+ if query_params:
162
+ path = f"{path}?{urlencode(query_params)}"
163
+ # TODO: remove the hack that pops config.
164
+ request_dict.pop("config", None)
165
+
166
+ http_options: Optional[types.HttpOptions] = None
167
+ if (
168
+ parameter_model.config is not None
169
+ and parameter_model.config.http_options is not None
170
+ ):
171
+ http_options = parameter_model.config.http_options
172
+
173
+ request_dict = _common.convert_to_dict(request_dict)
174
+ request_dict = _common.encode_unserializable_types(request_dict)
175
+
176
+ response = self._api_client.request("post", path, request_dict, http_options)
177
+
178
+ response_dict = {} if not response.body else json.loads(response.body)
179
+
180
+ return_value = types.UndeployModelOperation._from_response(
181
+ response=response_dict,
182
+ kwargs=(
183
+ {
184
+ "config": {
185
+ "response_schema": getattr(
186
+ parameter_model.config, "response_schema", None
187
+ ),
188
+ "response_json_schema": getattr(
189
+ parameter_model.config, "response_json_schema", None
190
+ ),
191
+ "include_all_fields": getattr(
192
+ parameter_model.config, "include_all_fields", None
193
+ ),
194
+ }
195
+ }
196
+ if getattr(parameter_model, "config", None)
197
+ else {}
198
+ ),
199
+ )
200
+
201
+ self._api_client._verify_response(return_value)
202
+ return return_value
203
+
204
+ def _predict(
205
+ self,
206
+ *,
207
+ name: str,
208
+ instances: list[dict[str, Any]],
209
+ config: Optional[types.PredictConfigOrDict] = None,
210
+ ) -> types.PredictResponse:
211
+ """
212
+ Perform an online prediction.
213
+ """
214
+
215
+ parameter_model = types._PredictParameters(
216
+ name=name,
217
+ instances=instances,
218
+ config=config,
219
+ )
220
+
221
+ request_url_dict: Optional[dict[str, str]]
222
+ if not self._api_client.vertexai:
223
+ raise ValueError(
224
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
225
+ )
226
+ else:
227
+ request_dict = _PredictParameters_to_vertex(parameter_model)
228
+ request_url_dict = request_dict.get("_url")
229
+ if request_url_dict:
230
+ path = "{endpoint}:predict".format_map(request_url_dict)
231
+ else:
232
+ path = "{endpoint}:predict"
233
+
234
+ query_params = request_dict.get("_query")
235
+ if query_params:
236
+ path = f"{path}?{urlencode(query_params)}"
237
+ # TODO: remove the hack that pops config.
238
+ request_dict.pop("config", None)
239
+
240
+ http_options: Optional[types.HttpOptions] = None
241
+ if (
242
+ parameter_model.config is not None
243
+ and parameter_model.config.http_options is not None
244
+ ):
245
+ http_options = parameter_model.config.http_options
246
+
247
+ request_dict = _common.convert_to_dict(request_dict)
248
+ request_dict = _common.encode_unserializable_types(request_dict)
249
+
250
+ response = self._api_client.request("post", path, request_dict, http_options)
251
+
252
+ response_dict = {} if not response.body else json.loads(response.body)
253
+
254
+ return_value = types.PredictResponse._from_response(
255
+ response=response_dict,
256
+ kwargs=(
257
+ {
258
+ "config": {
259
+ "response_schema": getattr(
260
+ parameter_model.config, "response_schema", None
261
+ ),
262
+ "response_json_schema": getattr(
263
+ parameter_model.config, "response_json_schema", None
264
+ ),
265
+ "include_all_fields": getattr(
266
+ parameter_model.config, "include_all_fields", None
267
+ ),
268
+ }
269
+ }
270
+ if getattr(parameter_model, "config", None)
271
+ else {}
272
+ ),
273
+ )
274
+
275
+ self._api_client._verify_response(return_value)
276
+ return return_value
277
+
278
+ def _delete(
279
+ self, *, name: str, config: Optional[types.DeleteEndpointConfigOrDict] = None
280
+ ) -> types.DeleteEndpointOperation:
281
+ """
282
+ Deletes an endpoint resource.
283
+ """
284
+
285
+ parameter_model = types._DeleteEndpointRequestParameters(
286
+ name=name,
287
+ config=config,
288
+ )
289
+
290
+ request_url_dict: Optional[dict[str, str]]
291
+ if not self._api_client.vertexai:
292
+ raise ValueError(
293
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
294
+ )
295
+ else:
296
+ request_dict = _DeleteEndpointRequestParameters_to_vertex(parameter_model)
297
+ request_url_dict = request_dict.get("_url")
298
+ if request_url_dict:
299
+ path = "{name}".format_map(request_url_dict)
300
+ else:
301
+ path = "{name}"
302
+
303
+ query_params = request_dict.get("_query")
304
+ if query_params:
305
+ path = f"{path}?{urlencode(query_params)}"
306
+ # TODO: remove the hack that pops config.
307
+ request_dict.pop("config", None)
308
+
309
+ http_options: Optional[types.HttpOptions] = None
310
+ if (
311
+ parameter_model.config is not None
312
+ and parameter_model.config.http_options is not None
313
+ ):
314
+ http_options = parameter_model.config.http_options
315
+
316
+ request_dict = _common.convert_to_dict(request_dict)
317
+ request_dict = _common.encode_unserializable_types(request_dict)
318
+
319
+ response = self._api_client.request("delete", path, request_dict, http_options)
320
+
321
+ response_dict = {} if not response.body else json.loads(response.body)
322
+
323
+ return_value = types.DeleteEndpointOperation._from_response(
324
+ response=response_dict,
325
+ kwargs=(
326
+ {
327
+ "config": {
328
+ "response_schema": getattr(
329
+ parameter_model.config, "response_schema", None
330
+ ),
331
+ "response_json_schema": getattr(
332
+ parameter_model.config, "response_json_schema", None
333
+ ),
334
+ "include_all_fields": getattr(
335
+ parameter_model.config, "include_all_fields", None
336
+ ),
337
+ }
338
+ }
339
+ if getattr(parameter_model, "config", None)
340
+ else {}
341
+ ),
342
+ )
343
+
344
+ self._api_client._verify_response(return_value)
345
+ return return_value
346
+
347
+ def get(
348
+ self, *, name: str, config: Optional[types.GetEndpointConfigOrDict] = None
349
+ ) -> types.Endpoint:
350
+ """
351
+ Retrieves a specific endpoint resource by its name.
352
+ """
353
+
354
+ parameter_model = types._GetEndpointParameters(
355
+ name=name,
356
+ config=config,
357
+ )
358
+
359
+ request_url_dict: Optional[dict[str, str]]
360
+ if not self._api_client.vertexai:
361
+ raise ValueError(
362
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
363
+ )
364
+ else:
365
+ request_dict = _GetEndpointParameters_to_vertex(parameter_model)
366
+ request_url_dict = request_dict.get("_url")
367
+ if request_url_dict:
368
+ path = "{name}".format_map(request_url_dict)
369
+ else:
370
+ path = "{name}"
371
+
372
+ query_params = request_dict.get("_query")
373
+ if query_params:
374
+ path = f"{path}?{urlencode(query_params)}"
375
+ # TODO: remove the hack that pops config.
376
+ request_dict.pop("config", None)
377
+
378
+ http_options: Optional[types.HttpOptions] = None
379
+ if (
380
+ parameter_model.config is not None
381
+ and parameter_model.config.http_options is not None
382
+ ):
383
+ http_options = parameter_model.config.http_options
384
+
385
+ request_dict = _common.convert_to_dict(request_dict)
386
+ request_dict = _common.encode_unserializable_types(request_dict)
387
+
388
+ response = self._api_client.request("get", path, request_dict, http_options)
389
+
390
+ response_dict = {} if not response.body else json.loads(response.body)
391
+
392
+ return_value = types.Endpoint._from_response(
393
+ response=response_dict,
394
+ kwargs=(
395
+ {
396
+ "config": {
397
+ "response_schema": getattr(
398
+ parameter_model.config, "response_schema", None
399
+ ),
400
+ "response_json_schema": getattr(
401
+ parameter_model.config, "response_json_schema", None
402
+ ),
403
+ "include_all_fields": getattr(
404
+ parameter_model.config, "include_all_fields", None
405
+ ),
406
+ }
407
+ }
408
+ if getattr(parameter_model, "config", None)
409
+ else {}
410
+ ),
411
+ )
412
+
413
+ self._api_client._verify_response(return_value)
414
+ return return_value
415
+
416
+ def _get_endpoint_operation(
417
+ self,
418
+ *,
419
+ operation_name: str,
420
+ config: Optional[types.GetEndpointOperationConfigOrDict] = None,
421
+ ) -> types.EndpointOperation:
422
+ parameter_model = types._GetEndpointOperationParameters(
423
+ operation_name=operation_name,
424
+ config=config,
425
+ )
426
+
427
+ request_url_dict: Optional[dict[str, str]]
428
+ if not self._api_client.vertexai:
429
+ raise ValueError(
430
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
431
+ )
432
+ else:
433
+ request_dict = _GetEndpointOperationParameters_to_vertex(parameter_model)
434
+ request_url_dict = request_dict.get("_url")
435
+ if request_url_dict:
436
+ path = "{operationName}".format_map(request_url_dict)
437
+ else:
438
+ path = "{operationName}"
439
+
440
+ query_params = request_dict.get("_query")
441
+ if query_params:
442
+ path = f"{path}?{urlencode(query_params)}"
443
+ # TODO: remove the hack that pops config.
444
+ request_dict.pop("config", None)
445
+
446
+ http_options: Optional[types.HttpOptions] = None
447
+ if (
448
+ parameter_model.config is not None
449
+ and parameter_model.config.http_options is not None
450
+ ):
451
+ http_options = parameter_model.config.http_options
452
+
453
+ request_dict = _common.convert_to_dict(request_dict)
454
+ request_dict = _common.encode_unserializable_types(request_dict)
455
+
456
+ response = self._api_client.request("get", path, request_dict, http_options)
457
+
458
+ response_dict = {} if not response.body else json.loads(response.body)
459
+
460
+ return_value = types.EndpointOperation._from_response(
461
+ response=response_dict,
462
+ kwargs=(
463
+ {
464
+ "config": {
465
+ "response_schema": getattr(
466
+ parameter_model.config, "response_schema", None
467
+ ),
468
+ "response_json_schema": getattr(
469
+ parameter_model.config, "response_json_schema", None
470
+ ),
471
+ "include_all_fields": getattr(
472
+ parameter_model.config, "include_all_fields", None
473
+ ),
474
+ }
475
+ }
476
+ if getattr(parameter_model, "config", None)
477
+ else {}
478
+ ),
479
+ )
480
+
481
+ self._api_client._verify_response(return_value)
482
+ return return_value
483
+
484
+ def predict(
485
+ self,
486
+ *,
487
+ name: str,
488
+ instances: list[dict[str, Any]],
489
+ config: Optional[types.PredictConfigOrDict] = None,
490
+ ) -> types.PredictResponse:
491
+ """Performs an online prediction.
492
+
493
+ Args:
494
+ name (str):
495
+ Required. The Endpoint or publisher model that serves the
496
+ prediction. Format:
497
+ projects/{project}/locations/{location}/endpoints/{endpoint},
498
+ endpoints/{endpoint},
499
+ projects/{project}/locations/{location}/publishers/{publisher}/models/{model}
500
+ or publishers/{publisher}/models/{model}.
501
+ instances (list[dict[str, Any]]):
502
+ Required. The instances that are the input to the prediction call.
503
+ config (PredictConfigOrDict):
504
+ Optional. Additional configuration for the prediction.
505
+
506
+ Returns:
507
+ PredictResponse: The prediction response.
508
+
509
+ """
510
+ if config is None:
511
+ config = types.PredictConfig()
512
+ elif isinstance(config, dict):
513
+ config = types.PredictConfig.model_validate(config)
514
+ elif not isinstance(config, types.PredictConfig):
515
+ raise TypeError(
516
+ f"config must be a dict or PredictConfig, but got {type(config)}."
517
+ )
518
+
519
+ # A publisher model has no Endpoint resource to look up, and only an
520
+ # Endpoint can have a dedicated DNS.
521
+ if t.is_endpoint_resource_name(name):
522
+ deployed_endpoint = self.get(name=name)
523
+ if deployed_endpoint.dedicated_endpoint_enabled:
524
+ if not deployed_endpoint.dedicated_endpoint_dns:
525
+ raise ValueError(
526
+ "Dedicated endpoint is enabled but no dedicated endpoint DNS is provided."
527
+ )
528
+ http_options = (
529
+ config.http_options.model_copy(deep=True)
530
+ if config.http_options is not None
531
+ else genai_types.HttpOptions()
532
+ )
533
+ http_options.base_url = (
534
+ "https://" + deployed_endpoint.dedicated_endpoint_dns
535
+ )
536
+ config = config.model_copy(update={"http_options": http_options})
537
+
538
+ response = self._predict(
539
+ name=name,
540
+ instances=instances,
541
+ config=config,
542
+ )
543
+
544
+ return response
545
+
546
+ def undeploy(
547
+ self,
548
+ *,
549
+ name: str,
550
+ deployed_model_id: str,
551
+ config: Optional[types.UndeployModelConfigOrDict] = None,
552
+ ) -> Optional[types.UndeployModelOperation]:
553
+ """Undeploys a model from an Endpoint.
554
+
555
+ Args:
556
+ name (str):
557
+ Required. The resource name of the Endpoint to undeploy model from.
558
+ Format: projects/{project}/locations/{location}/endpoints/{endpoint}
559
+ deployed_model_id (str):
560
+ Required. The ID of the DeployedModel to undeploy.
561
+ config (UndeployModelConfigOrDict):
562
+ Optional. Additional configuration for the undeploy operation.
563
+
564
+ Returns:
565
+ UndeployModelOperation: The pending LRO if wait_for_completion is False,
566
+ otherwise None (blocks until done).
567
+ """
568
+ if config is None:
569
+ config = types.UndeployModelConfig()
570
+ elif isinstance(config, dict):
571
+ config = types.UndeployModelConfig.model_validate(config)
572
+ elif not isinstance(config, types.UndeployModelConfig):
573
+ raise TypeError(
574
+ f"config must be a dict or UndeployModelConfig, but got {type(config)}."
575
+ )
576
+
577
+ operation = self._undeploy(
578
+ name=name, deployed_model_id=deployed_model_id, config=config
579
+ )
580
+
581
+ if config.wait_for_completion:
582
+ operation = _operations_utils.await_operation(
583
+ operation_name=operation.name,
584
+ get_operation_fn=self._get_endpoint_operation,
585
+ )
586
+ if operation.error:
587
+ raise RuntimeError(f"Failed to undeploy Endpoint: {operation.error}")
588
+ return None
589
+
590
+ return operation
591
+
592
+ def delete(
593
+ self,
594
+ *,
595
+ name: str,
596
+ config: Optional[types.DeleteEndpointConfigOrDict] = None,
597
+ ) -> Optional[types.DeleteEndpointOperation]:
598
+ """Deletes an Endpoint.
599
+
600
+ Args:
601
+ name (str):
602
+ Required. The resource name of the Endpoint to delete.
603
+ Format: projects/{project}/locations/{location}/endpoints/{endpoint}
604
+ config (DeleteEndpointConfigOrDict):
605
+ Optional. Additional configuration for the delete operation.
606
+
607
+ Returns:
608
+ DeleteEndpointOperation: The pending LRO if wait_for_completion is False,
609
+ otherwise None (blocks until done).
610
+ """
611
+ if config is None:
612
+ config = types.DeleteEndpointConfig()
613
+ elif isinstance(config, dict):
614
+ config = types.DeleteEndpointConfig.model_validate(config)
615
+ elif not isinstance(config, types.DeleteEndpointConfig):
616
+ raise TypeError(
617
+ f"config must be a dict or DeleteEndpointConfig, but got {type(config)}."
618
+ )
619
+
620
+ operation = self._delete(name=name, config=config)
621
+
622
+ if config.wait_for_completion:
623
+ operation = _operations_utils.await_operation(
624
+ operation_name=operation.name,
625
+ get_operation_fn=self._get_endpoint_operation,
626
+ )
627
+ if operation.error:
628
+ raise RuntimeError(f"Failed to delete Endpoint: {operation.error}")
629
+ return None
630
+
631
+ return operation
632
+
633
+
634
+ class AsyncEndpoints(_api_module.BaseModule):
635
+ """Class for managing Endpoints for prediction, undeployment, and deletion."""
636
+
637
+ async def _undeploy(
638
+ self,
639
+ *,
640
+ name: str,
641
+ deployed_model_id: str,
642
+ config: Optional[types.UndeployModelConfigOrDict] = None,
643
+ ) -> types.UndeployModelOperation:
644
+ """
645
+ Undeploys a Model from an Endpoint, removing a
646
+ DeployedModel from it, and freeing all resources it's using.
647
+ """
648
+
649
+ parameter_model = types._UndeployModelRequestParameters(
650
+ name=name,
651
+ deployed_model_id=deployed_model_id,
652
+ config=config,
653
+ )
654
+
655
+ request_url_dict: Optional[dict[str, str]]
656
+ if not self._api_client.vertexai:
657
+ raise ValueError(
658
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
659
+ )
660
+ else:
661
+ request_dict = _UndeployModelRequestParameters_to_vertex(parameter_model)
662
+ request_url_dict = request_dict.get("_url")
663
+ if request_url_dict:
664
+ path = "{endpoint}:undeployModel".format_map(request_url_dict)
665
+ else:
666
+ path = "{endpoint}:undeployModel"
667
+
668
+ query_params = request_dict.get("_query")
669
+ if query_params:
670
+ path = f"{path}?{urlencode(query_params)}"
671
+ # TODO: remove the hack that pops config.
672
+ request_dict.pop("config", None)
673
+
674
+ http_options: Optional[types.HttpOptions] = None
675
+ if (
676
+ parameter_model.config is not None
677
+ and parameter_model.config.http_options is not None
678
+ ):
679
+ http_options = parameter_model.config.http_options
680
+
681
+ request_dict = _common.convert_to_dict(request_dict)
682
+ request_dict = _common.encode_unserializable_types(request_dict)
683
+
684
+ response = await self._api_client.async_request(
685
+ "post", path, request_dict, http_options
686
+ )
687
+
688
+ response_dict = {} if not response.body else json.loads(response.body)
689
+
690
+ return_value = types.UndeployModelOperation._from_response(
691
+ response=response_dict,
692
+ kwargs=(
693
+ {
694
+ "config": {
695
+ "response_schema": getattr(
696
+ parameter_model.config, "response_schema", None
697
+ ),
698
+ "response_json_schema": getattr(
699
+ parameter_model.config, "response_json_schema", None
700
+ ),
701
+ "include_all_fields": getattr(
702
+ parameter_model.config, "include_all_fields", None
703
+ ),
704
+ }
705
+ }
706
+ if getattr(parameter_model, "config", None)
707
+ else {}
708
+ ),
709
+ )
710
+
711
+ self._api_client._verify_response(return_value)
712
+ return return_value
713
+
714
+ async def _predict(
715
+ self,
716
+ *,
717
+ name: str,
718
+ instances: list[dict[str, Any]],
719
+ config: Optional[types.PredictConfigOrDict] = None,
720
+ ) -> types.PredictResponse:
721
+ """
722
+ Perform an online prediction.
723
+ """
724
+
725
+ parameter_model = types._PredictParameters(
726
+ name=name,
727
+ instances=instances,
728
+ config=config,
729
+ )
730
+
731
+ request_url_dict: Optional[dict[str, str]]
732
+ if not self._api_client.vertexai:
733
+ raise ValueError(
734
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
735
+ )
736
+ else:
737
+ request_dict = _PredictParameters_to_vertex(parameter_model)
738
+ request_url_dict = request_dict.get("_url")
739
+ if request_url_dict:
740
+ path = "{endpoint}:predict".format_map(request_url_dict)
741
+ else:
742
+ path = "{endpoint}:predict"
743
+
744
+ query_params = request_dict.get("_query")
745
+ if query_params:
746
+ path = f"{path}?{urlencode(query_params)}"
747
+ # TODO: remove the hack that pops config.
748
+ request_dict.pop("config", None)
749
+
750
+ http_options: Optional[types.HttpOptions] = None
751
+ if (
752
+ parameter_model.config is not None
753
+ and parameter_model.config.http_options is not None
754
+ ):
755
+ http_options = parameter_model.config.http_options
756
+
757
+ request_dict = _common.convert_to_dict(request_dict)
758
+ request_dict = _common.encode_unserializable_types(request_dict)
759
+
760
+ response = await self._api_client.async_request(
761
+ "post", path, request_dict, http_options
762
+ )
763
+
764
+ response_dict = {} if not response.body else json.loads(response.body)
765
+
766
+ return_value = types.PredictResponse._from_response(
767
+ response=response_dict,
768
+ kwargs=(
769
+ {
770
+ "config": {
771
+ "response_schema": getattr(
772
+ parameter_model.config, "response_schema", None
773
+ ),
774
+ "response_json_schema": getattr(
775
+ parameter_model.config, "response_json_schema", None
776
+ ),
777
+ "include_all_fields": getattr(
778
+ parameter_model.config, "include_all_fields", None
779
+ ),
780
+ }
781
+ }
782
+ if getattr(parameter_model, "config", None)
783
+ else {}
784
+ ),
785
+ )
786
+
787
+ self._api_client._verify_response(return_value)
788
+ return return_value
789
+
790
+ async def _delete(
791
+ self, *, name: str, config: Optional[types.DeleteEndpointConfigOrDict] = None
792
+ ) -> types.DeleteEndpointOperation:
793
+ """
794
+ Deletes an endpoint resource.
795
+ """
796
+
797
+ parameter_model = types._DeleteEndpointRequestParameters(
798
+ name=name,
799
+ config=config,
800
+ )
801
+
802
+ request_url_dict: Optional[dict[str, str]]
803
+ if not self._api_client.vertexai:
804
+ raise ValueError(
805
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
806
+ )
807
+ else:
808
+ request_dict = _DeleteEndpointRequestParameters_to_vertex(parameter_model)
809
+ request_url_dict = request_dict.get("_url")
810
+ if request_url_dict:
811
+ path = "{name}".format_map(request_url_dict)
812
+ else:
813
+ path = "{name}"
814
+
815
+ query_params = request_dict.get("_query")
816
+ if query_params:
817
+ path = f"{path}?{urlencode(query_params)}"
818
+ # TODO: remove the hack that pops config.
819
+ request_dict.pop("config", None)
820
+
821
+ http_options: Optional[types.HttpOptions] = None
822
+ if (
823
+ parameter_model.config is not None
824
+ and parameter_model.config.http_options is not None
825
+ ):
826
+ http_options = parameter_model.config.http_options
827
+
828
+ request_dict = _common.convert_to_dict(request_dict)
829
+ request_dict = _common.encode_unserializable_types(request_dict)
830
+
831
+ response = await self._api_client.async_request(
832
+ "delete", path, request_dict, http_options
833
+ )
834
+
835
+ response_dict = {} if not response.body else json.loads(response.body)
836
+
837
+ return_value = types.DeleteEndpointOperation._from_response(
838
+ response=response_dict,
839
+ kwargs=(
840
+ {
841
+ "config": {
842
+ "response_schema": getattr(
843
+ parameter_model.config, "response_schema", None
844
+ ),
845
+ "response_json_schema": getattr(
846
+ parameter_model.config, "response_json_schema", None
847
+ ),
848
+ "include_all_fields": getattr(
849
+ parameter_model.config, "include_all_fields", None
850
+ ),
851
+ }
852
+ }
853
+ if getattr(parameter_model, "config", None)
854
+ else {}
855
+ ),
856
+ )
857
+
858
+ self._api_client._verify_response(return_value)
859
+ return return_value
860
+
861
+ async def get(
862
+ self, *, name: str, config: Optional[types.GetEndpointConfigOrDict] = None
863
+ ) -> types.Endpoint:
864
+ """
865
+ Retrieves a specific endpoint resource by its name.
866
+ """
867
+
868
+ parameter_model = types._GetEndpointParameters(
869
+ name=name,
870
+ config=config,
871
+ )
872
+
873
+ request_url_dict: Optional[dict[str, str]]
874
+ if not self._api_client.vertexai:
875
+ raise ValueError(
876
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
877
+ )
878
+ else:
879
+ request_dict = _GetEndpointParameters_to_vertex(parameter_model)
880
+ request_url_dict = request_dict.get("_url")
881
+ if request_url_dict:
882
+ path = "{name}".format_map(request_url_dict)
883
+ else:
884
+ path = "{name}"
885
+
886
+ query_params = request_dict.get("_query")
887
+ if query_params:
888
+ path = f"{path}?{urlencode(query_params)}"
889
+ # TODO: remove the hack that pops config.
890
+ request_dict.pop("config", None)
891
+
892
+ http_options: Optional[types.HttpOptions] = None
893
+ if (
894
+ parameter_model.config is not None
895
+ and parameter_model.config.http_options is not None
896
+ ):
897
+ http_options = parameter_model.config.http_options
898
+
899
+ request_dict = _common.convert_to_dict(request_dict)
900
+ request_dict = _common.encode_unserializable_types(request_dict)
901
+
902
+ response = await self._api_client.async_request(
903
+ "get", path, request_dict, http_options
904
+ )
905
+
906
+ response_dict = {} if not response.body else json.loads(response.body)
907
+
908
+ return_value = types.Endpoint._from_response(
909
+ response=response_dict,
910
+ kwargs=(
911
+ {
912
+ "config": {
913
+ "response_schema": getattr(
914
+ parameter_model.config, "response_schema", None
915
+ ),
916
+ "response_json_schema": getattr(
917
+ parameter_model.config, "response_json_schema", None
918
+ ),
919
+ "include_all_fields": getattr(
920
+ parameter_model.config, "include_all_fields", None
921
+ ),
922
+ }
923
+ }
924
+ if getattr(parameter_model, "config", None)
925
+ else {}
926
+ ),
927
+ )
928
+
929
+ self._api_client._verify_response(return_value)
930
+ return return_value
931
+
932
+ async def _get_endpoint_operation(
933
+ self,
934
+ *,
935
+ operation_name: str,
936
+ config: Optional[types.GetEndpointOperationConfigOrDict] = None,
937
+ ) -> types.EndpointOperation:
938
+ parameter_model = types._GetEndpointOperationParameters(
939
+ operation_name=operation_name,
940
+ config=config,
941
+ )
942
+
943
+ request_url_dict: Optional[dict[str, str]]
944
+ if not self._api_client.vertexai:
945
+ raise ValueError(
946
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
947
+ )
948
+ else:
949
+ request_dict = _GetEndpointOperationParameters_to_vertex(parameter_model)
950
+ request_url_dict = request_dict.get("_url")
951
+ if request_url_dict:
952
+ path = "{operationName}".format_map(request_url_dict)
953
+ else:
954
+ path = "{operationName}"
955
+
956
+ query_params = request_dict.get("_query")
957
+ if query_params:
958
+ path = f"{path}?{urlencode(query_params)}"
959
+ # TODO: remove the hack that pops config.
960
+ request_dict.pop("config", None)
961
+
962
+ http_options: Optional[types.HttpOptions] = None
963
+ if (
964
+ parameter_model.config is not None
965
+ and parameter_model.config.http_options is not None
966
+ ):
967
+ http_options = parameter_model.config.http_options
968
+
969
+ request_dict = _common.convert_to_dict(request_dict)
970
+ request_dict = _common.encode_unserializable_types(request_dict)
971
+
972
+ response = await self._api_client.async_request(
973
+ "get", path, request_dict, http_options
974
+ )
975
+
976
+ response_dict = {} if not response.body else json.loads(response.body)
977
+
978
+ return_value = types.EndpointOperation._from_response(
979
+ response=response_dict,
980
+ kwargs=(
981
+ {
982
+ "config": {
983
+ "response_schema": getattr(
984
+ parameter_model.config, "response_schema", None
985
+ ),
986
+ "response_json_schema": getattr(
987
+ parameter_model.config, "response_json_schema", None
988
+ ),
989
+ "include_all_fields": getattr(
990
+ parameter_model.config, "include_all_fields", None
991
+ ),
992
+ }
993
+ }
994
+ if getattr(parameter_model, "config", None)
995
+ else {}
996
+ ),
997
+ )
998
+
999
+ self._api_client._verify_response(return_value)
1000
+ return return_value
1001
+
1002
+ async def predict(
1003
+ self,
1004
+ *,
1005
+ name: str,
1006
+ instances: list[dict[str, Any]],
1007
+ config: Optional[types.PredictConfigOrDict] = None,
1008
+ ) -> types.PredictResponse:
1009
+ """Performs an online prediction.
1010
+
1011
+ Args:
1012
+ name (str):
1013
+ Required. The Endpoint or publisher model that serves the
1014
+ prediction. Format:
1015
+ projects/{project}/locations/{location}/endpoints/{endpoint},
1016
+ endpoints/{endpoint},
1017
+ projects/{project}/locations/{location}/publishers/{publisher}/models/{model}
1018
+ or publishers/{publisher}/models/{model}.
1019
+ instances (list[dict[str, Any]]):
1020
+ Required. The instances that are the input to the prediction call.
1021
+ config (PredictConfigOrDict):
1022
+ Optional. Additional configuration for the prediction.
1023
+
1024
+ Returns:
1025
+ PredictResponse: The prediction response.
1026
+
1027
+ """
1028
+ if config is None:
1029
+ config = types.PredictConfig()
1030
+ elif isinstance(config, dict):
1031
+ config = types.PredictConfig.model_validate(config)
1032
+ elif not isinstance(config, types.PredictConfig):
1033
+ raise TypeError(
1034
+ f"config must be a dict or PredictConfig, but got {type(config)}."
1035
+ )
1036
+
1037
+ # A publisher model has no Endpoint resource to look up, and only an
1038
+ # Endpoint can have a dedicated DNS.
1039
+ if t.is_endpoint_resource_name(name):
1040
+ deployed_endpoint = await self.get(name=name)
1041
+ if deployed_endpoint.dedicated_endpoint_enabled:
1042
+ if not deployed_endpoint.dedicated_endpoint_dns:
1043
+ raise ValueError(
1044
+ "Dedicated endpoint is enabled but no dedicated endpoint DNS is provided."
1045
+ )
1046
+ http_options = (
1047
+ config.http_options.model_copy(deep=True)
1048
+ if config.http_options is not None
1049
+ else genai_types.HttpOptions()
1050
+ )
1051
+ http_options.base_url = (
1052
+ "https://" + deployed_endpoint.dedicated_endpoint_dns
1053
+ )
1054
+ config = config.model_copy(update={"http_options": http_options})
1055
+
1056
+ response = await self._predict(
1057
+ name=name,
1058
+ instances=instances,
1059
+ config=config,
1060
+ )
1061
+
1062
+ return response
1063
+
1064
+ async def undeploy(
1065
+ self,
1066
+ *,
1067
+ name: str,
1068
+ deployed_model_id: str,
1069
+ config: Optional[types.UndeployModelConfigOrDict] = None,
1070
+ ) -> Optional[types.UndeployModelOperation]:
1071
+ """Undeploys a model from an Endpoint.
1072
+
1073
+ Args:
1074
+ name (str):
1075
+ Required. The resource name of the Endpoint to undeploy model from.
1076
+ Format: projects/{project}/locations/{location}/endpoints/{endpoint}
1077
+ deployed_model_id (str):
1078
+ Required. The ID of the DeployedModel to undeploy.
1079
+ config (UndeployModelConfigOrDict):
1080
+ Optional. Additional configuration for the undeploy operation.
1081
+
1082
+ Returns:
1083
+ UndeployModelOperation: The pending LRO if wait_for_completion is False,
1084
+ otherwise None (blocks until done).
1085
+ """
1086
+ if config is None:
1087
+ config = types.UndeployModelConfig()
1088
+ elif isinstance(config, dict):
1089
+ config = types.UndeployModelConfig.model_validate(config)
1090
+ elif not isinstance(config, types.UndeployModelConfig):
1091
+ raise TypeError(
1092
+ f"config must be a dict or UndeployModelConfig, but got {type(config)}."
1093
+ )
1094
+
1095
+ operation = await self._undeploy(
1096
+ name=name, deployed_model_id=deployed_model_id, config=config
1097
+ )
1098
+
1099
+ if config.wait_for_completion:
1100
+ operation = await _operations_utils.await_operation_async(
1101
+ operation_name=operation.name,
1102
+ get_operation_fn=self._get_endpoint_operation,
1103
+ )
1104
+ if operation.error:
1105
+ raise RuntimeError(f"Failed to undeploy Endpoint: {operation.error}")
1106
+ return None
1107
+
1108
+ return operation
1109
+
1110
+ async def delete(
1111
+ self,
1112
+ *,
1113
+ name: str,
1114
+ config: Optional[types.DeleteEndpointConfigOrDict] = None,
1115
+ ) -> Optional[types.DeleteEndpointOperation]:
1116
+ """Deletes an Endpoint.
1117
+
1118
+ Args:
1119
+ name (str):
1120
+ Required. The resource name of the Endpoint to delete.
1121
+ Format: projects/{project}/locations/{location}/endpoints/{endpoint}
1122
+ config (DeleteEndpointConfigOrDict):
1123
+ Optional. Additional configuration for the delete operation.
1124
+
1125
+ Returns:
1126
+ DeleteEndpointOperation: The pending LRO if wait_for_completion is False,
1127
+ otherwise None (blocks until done).
1128
+ """
1129
+ if config is None:
1130
+ config = types.DeleteEndpointConfig()
1131
+ elif isinstance(config, dict):
1132
+ config = types.DeleteEndpointConfig.model_validate(config)
1133
+ elif not isinstance(config, types.DeleteEndpointConfig):
1134
+ raise TypeError(
1135
+ f"config must be a dict or DeleteEndpointConfig, but got {type(config)}."
1136
+ )
1137
+
1138
+ operation = await self._delete(name=name, config=config)
1139
+
1140
+ if config.wait_for_completion:
1141
+ operation = await _operations_utils.await_operation_async(
1142
+ operation_name=operation.name,
1143
+ get_operation_fn=self._get_endpoint_operation,
1144
+ )
1145
+ if operation.error:
1146
+ raise RuntimeError(f"Failed to delete Endpoint: {operation.error}")
1147
+ return None
1148
+
1149
+ return operation