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,3045 @@
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 asyncio
19
+ import json
20
+ import logging
21
+ import time
22
+ from typing import Any, Optional, Union
23
+ from urllib.parse import urlencode
24
+
25
+ from google.genai import _api_module
26
+ from google.genai import _common
27
+ from google.genai import types as genai_types
28
+ from google.genai._common import get_value_by_path as getv
29
+ from google.genai._common import set_value_by_path as setv
30
+ import pandas as pd
31
+
32
+ from . import _datasets_utils
33
+ from . import types
34
+
35
+ logger = logging.getLogger("agentplatform_genai.datasets")
36
+
37
+
38
+ def _AssembleDatasetParameters_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, ["name"]) is not None:
44
+ setv(to_object, ["_url", "name"], getv(from_object, ["name"]))
45
+
46
+ if getv(from_object, ["gemini_request_read_config"]) is not None:
47
+ setv(
48
+ to_object,
49
+ ["geminiRequestReadConfig"],
50
+ getv(from_object, ["gemini_request_read_config"]),
51
+ )
52
+
53
+ if getv(from_object, ["config"]) is not None:
54
+ setv(to_object, ["config"], getv(from_object, ["config"]))
55
+
56
+ return to_object
57
+
58
+
59
+ def _AssessDatasetParameters_to_vertex(
60
+ from_object: Union[dict[str, Any], object],
61
+ parent_object: Optional[dict[str, Any]] = None,
62
+ ) -> dict[str, Any]:
63
+ to_object: dict[str, Any] = {}
64
+ if getv(from_object, ["name"]) is not None:
65
+ setv(to_object, ["_url", "name"], getv(from_object, ["name"]))
66
+
67
+ if getv(from_object, ["gemini_request_read_config"]) is not None:
68
+ setv(
69
+ to_object,
70
+ ["geminiRequestReadConfig"],
71
+ getv(from_object, ["gemini_request_read_config"]),
72
+ )
73
+
74
+ if getv(from_object, ["tuning_resource_usage_assessment_config"]) is not None:
75
+ setv(
76
+ to_object,
77
+ ["tuningResourceUsageAssessmentConfig"],
78
+ getv(from_object, ["tuning_resource_usage_assessment_config"]),
79
+ )
80
+
81
+ if getv(from_object, ["tuning_validation_assessment_config"]) is not None:
82
+ setv(
83
+ to_object,
84
+ ["tuningValidationAssessmentConfig"],
85
+ getv(from_object, ["tuning_validation_assessment_config"]),
86
+ )
87
+
88
+ if (
89
+ getv(from_object, ["batch_prediction_resource_usage_assessment_config"])
90
+ is not None
91
+ ):
92
+ setv(
93
+ to_object,
94
+ ["batchPredictionResourceUsageAssessmentConfig"],
95
+ getv(from_object, ["batch_prediction_resource_usage_assessment_config"]),
96
+ )
97
+
98
+ if getv(from_object, ["batch_prediction_validation_assessment_config"]) is not None:
99
+ setv(
100
+ to_object,
101
+ ["batchPredictionValidationAssessmentConfig"],
102
+ getv(from_object, ["batch_prediction_validation_assessment_config"]),
103
+ )
104
+
105
+ if getv(from_object, ["config"]) is not None:
106
+ setv(to_object, ["config"], getv(from_object, ["config"]))
107
+
108
+ return to_object
109
+
110
+
111
+ def _CreateMultimodalDatasetParameters_to_vertex(
112
+ from_object: Union[dict[str, Any], object],
113
+ parent_object: Optional[dict[str, Any]] = None,
114
+ ) -> dict[str, Any]:
115
+ to_object: dict[str, Any] = {}
116
+ if getv(from_object, ["name"]) is not None:
117
+ setv(to_object, ["name"], getv(from_object, ["name"]))
118
+
119
+ if getv(from_object, ["display_name"]) is not None:
120
+ setv(to_object, ["displayName"], getv(from_object, ["display_name"]))
121
+
122
+ if getv(from_object, ["metadata_schema_uri"]) is not None:
123
+ setv(
124
+ to_object, ["metadataSchemaUri"], getv(from_object, ["metadata_schema_uri"])
125
+ )
126
+
127
+ if getv(from_object, ["metadata"]) is not None:
128
+ setv(to_object, ["metadata"], getv(from_object, ["metadata"]))
129
+
130
+ if getv(from_object, ["description"]) is not None:
131
+ setv(to_object, ["description"], getv(from_object, ["description"]))
132
+
133
+ if getv(from_object, ["encryption_spec"]) is not None:
134
+ setv(to_object, ["encryptionSpec"], getv(from_object, ["encryption_spec"]))
135
+
136
+ if getv(from_object, ["config"]) is not None:
137
+ setv(to_object, ["config"], getv(from_object, ["config"]))
138
+
139
+ return to_object
140
+
141
+
142
+ def _DeleteMultimodalDatasetRequestParameters_to_vertex(
143
+ from_object: Union[dict[str, Any], object],
144
+ parent_object: Optional[dict[str, Any]] = None,
145
+ ) -> dict[str, Any]:
146
+ to_object: dict[str, Any] = {}
147
+ if getv(from_object, ["name"]) is not None:
148
+ setv(to_object, ["_url", "name"], getv(from_object, ["name"]))
149
+
150
+ if getv(from_object, ["config"]) is not None:
151
+ setv(to_object, ["config"], getv(from_object, ["config"]))
152
+
153
+ return to_object
154
+
155
+
156
+ def _GetMultimodalDatasetOperationParameters_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, ["dataset_id"]) is not None:
162
+ setv(to_object, ["_url", "dataset_id"], getv(from_object, ["dataset_id"]))
163
+
164
+ if getv(from_object, ["operation_id"]) is not None:
165
+ setv(to_object, ["_url", "operation_id"], getv(from_object, ["operation_id"]))
166
+
167
+ if getv(from_object, ["config"]) is not None:
168
+ setv(to_object, ["config"], getv(from_object, ["config"]))
169
+
170
+ return to_object
171
+
172
+
173
+ def _GetMultimodalDatasetParameters_to_vertex(
174
+ from_object: Union[dict[str, Any], object],
175
+ parent_object: Optional[dict[str, Any]] = None,
176
+ ) -> dict[str, Any]:
177
+ to_object: dict[str, Any] = {}
178
+ if getv(from_object, ["name"]) is not None:
179
+ setv(to_object, ["_url", "name"], getv(from_object, ["name"]))
180
+
181
+ if getv(from_object, ["config"]) is not None:
182
+ setv(to_object, ["config"], getv(from_object, ["config"]))
183
+
184
+ return to_object
185
+
186
+
187
+ def _ListMultimodalDatasetsConfig_to_vertex(
188
+ from_object: Union[dict[str, Any], object],
189
+ parent_object: Optional[dict[str, Any]] = None,
190
+ ) -> dict[str, Any]:
191
+ to_object: dict[str, Any] = {}
192
+
193
+ if getv(from_object, ["page_size"]) is not None:
194
+ setv(parent_object, ["_query", "pageSize"], getv(from_object, ["page_size"]))
195
+
196
+ if getv(from_object, ["page_token"]) is not None:
197
+ setv(parent_object, ["_query", "pageToken"], getv(from_object, ["page_token"]))
198
+
199
+ if getv(from_object, ["filter"]) is not None:
200
+ setv(parent_object, ["_query", "filter"], getv(from_object, ["filter"]))
201
+
202
+ return to_object
203
+
204
+
205
+ def _ListMultimodalDatasetsRequestParameters_to_vertex(
206
+ from_object: Union[dict[str, Any], object],
207
+ parent_object: Optional[dict[str, Any]] = None,
208
+ ) -> dict[str, Any]:
209
+ to_object: dict[str, Any] = {}
210
+ if getv(from_object, ["config"]) is not None:
211
+ setv(
212
+ to_object,
213
+ ["config"],
214
+ _ListMultimodalDatasetsConfig_to_vertex(
215
+ getv(from_object, ["config"]), to_object
216
+ ),
217
+ )
218
+
219
+ return to_object
220
+
221
+
222
+ def _UpdateMultimodalDatasetParameters_to_vertex(
223
+ from_object: Union[dict[str, Any], object],
224
+ parent_object: Optional[dict[str, Any]] = None,
225
+ ) -> dict[str, Any]:
226
+ to_object: dict[str, Any] = {}
227
+ if getv(from_object, ["name"]) is not None:
228
+ setv(to_object, ["_url", "name"], getv(from_object, ["name"]))
229
+
230
+ if getv(from_object, ["display_name"]) is not None:
231
+ setv(to_object, ["displayName"], getv(from_object, ["display_name"]))
232
+
233
+ if getv(from_object, ["metadata"]) is not None:
234
+ setv(to_object, ["metadata"], getv(from_object, ["metadata"]))
235
+
236
+ if getv(from_object, ["description"]) is not None:
237
+ setv(to_object, ["description"], getv(from_object, ["description"]))
238
+
239
+ if getv(from_object, ["encryption_spec"]) is not None:
240
+ setv(to_object, ["encryptionSpec"], getv(from_object, ["encryption_spec"]))
241
+
242
+ if getv(from_object, ["config"]) is not None:
243
+ setv(to_object, ["config"], getv(from_object, ["config"]))
244
+
245
+ return to_object
246
+
247
+
248
+ class Datasets(_api_module.BaseModule):
249
+
250
+ def _assemble_multimodal_dataset(
251
+ self,
252
+ *,
253
+ name: str,
254
+ gemini_request_read_config: Optional[
255
+ types.GeminiRequestReadConfigOrDict
256
+ ] = None,
257
+ config: Optional[types.AssembleDatasetConfigOrDict] = None,
258
+ ) -> types.MultimodalDatasetOperation:
259
+ """
260
+ Assembles a multimodal dataset resource.
261
+ """
262
+
263
+ parameter_model = types._AssembleDatasetParameters(
264
+ name=name,
265
+ gemini_request_read_config=gemini_request_read_config,
266
+ config=config,
267
+ )
268
+
269
+ request_url_dict: Optional[dict[str, str]]
270
+ if not self._api_client.vertexai:
271
+ raise ValueError(
272
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
273
+ )
274
+ else:
275
+ request_dict = _AssembleDatasetParameters_to_vertex(parameter_model)
276
+ request_url_dict = request_dict.get("_url")
277
+ if request_url_dict:
278
+ path = "{name}:assemble".format_map(request_url_dict)
279
+ else:
280
+ path = "{name}:assemble"
281
+
282
+ query_params = request_dict.get("_query")
283
+ if query_params:
284
+ path = f"{path}?{urlencode(query_params)}"
285
+ # TODO: remove the hack that pops config.
286
+ request_dict.pop("config", None)
287
+
288
+ http_options: Optional[types.HttpOptions] = None
289
+ if (
290
+ parameter_model.config is not None
291
+ and parameter_model.config.http_options is not None
292
+ ):
293
+ http_options = parameter_model.config.http_options
294
+
295
+ request_dict = _common.convert_to_dict(request_dict)
296
+ request_dict = _common.encode_unserializable_types(request_dict)
297
+
298
+ response = self._api_client.request("post", path, request_dict, http_options)
299
+
300
+ response_dict = {} if not response.body else json.loads(response.body)
301
+
302
+ return_value = types.MultimodalDatasetOperation._from_response(
303
+ response=response_dict,
304
+ kwargs=(
305
+ {
306
+ "config": {
307
+ "response_schema": getattr(
308
+ parameter_model.config, "response_schema", None
309
+ ),
310
+ "response_json_schema": getattr(
311
+ parameter_model.config, "response_json_schema", None
312
+ ),
313
+ "include_all_fields": getattr(
314
+ parameter_model.config, "include_all_fields", None
315
+ ),
316
+ }
317
+ }
318
+ if getattr(parameter_model, "config", None)
319
+ else {}
320
+ ),
321
+ )
322
+
323
+ self._api_client._verify_response(return_value)
324
+ return return_value
325
+
326
+ def _assess_multimodal_dataset(
327
+ self,
328
+ *,
329
+ name: str,
330
+ gemini_request_read_config: Optional[
331
+ types.GeminiRequestReadConfigOrDict
332
+ ] = None,
333
+ tuning_resource_usage_assessment_config: Optional[
334
+ types.TuningResourceUsageAssessmentConfigOrDict
335
+ ] = None,
336
+ tuning_validation_assessment_config: Optional[
337
+ types.TuningValidationAssessmentConfigOrDict
338
+ ] = None,
339
+ batch_prediction_resource_usage_assessment_config: Optional[
340
+ types.BatchPredictionResourceUsageAssessmentConfigOrDict
341
+ ] = None,
342
+ batch_prediction_validation_assessment_config: Optional[
343
+ types.BatchPredictionValidationAssessmentConfigOrDict
344
+ ] = None,
345
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
346
+ ) -> types.MultimodalDatasetOperation:
347
+ """
348
+ Assesses a multimodal dataset resource.
349
+ """
350
+
351
+ parameter_model = types._AssessDatasetParameters(
352
+ name=name,
353
+ gemini_request_read_config=gemini_request_read_config,
354
+ tuning_resource_usage_assessment_config=tuning_resource_usage_assessment_config,
355
+ tuning_validation_assessment_config=tuning_validation_assessment_config,
356
+ batch_prediction_resource_usage_assessment_config=batch_prediction_resource_usage_assessment_config,
357
+ batch_prediction_validation_assessment_config=batch_prediction_validation_assessment_config,
358
+ config=config,
359
+ )
360
+
361
+ request_url_dict: Optional[dict[str, str]]
362
+ if not self._api_client.vertexai:
363
+ raise ValueError(
364
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
365
+ )
366
+ else:
367
+ request_dict = _AssessDatasetParameters_to_vertex(parameter_model)
368
+ request_url_dict = request_dict.get("_url")
369
+ if request_url_dict:
370
+ path = "{name}:assess".format_map(request_url_dict)
371
+ else:
372
+ path = "{name}:assess"
373
+
374
+ query_params = request_dict.get("_query")
375
+ if query_params:
376
+ path = f"{path}?{urlencode(query_params)}"
377
+ # TODO: remove the hack that pops config.
378
+ request_dict.pop("config", None)
379
+
380
+ http_options: Optional[types.HttpOptions] = None
381
+ if (
382
+ parameter_model.config is not None
383
+ and parameter_model.config.http_options is not None
384
+ ):
385
+ http_options = parameter_model.config.http_options
386
+
387
+ request_dict = _common.convert_to_dict(request_dict)
388
+ request_dict = _common.encode_unserializable_types(request_dict)
389
+
390
+ response = self._api_client.request("post", path, request_dict, http_options)
391
+
392
+ response_dict = {} if not response.body else json.loads(response.body)
393
+
394
+ return_value = types.MultimodalDatasetOperation._from_response(
395
+ response=response_dict,
396
+ kwargs=(
397
+ {
398
+ "config": {
399
+ "response_schema": getattr(
400
+ parameter_model.config, "response_schema", None
401
+ ),
402
+ "response_json_schema": getattr(
403
+ parameter_model.config, "response_json_schema", None
404
+ ),
405
+ "include_all_fields": getattr(
406
+ parameter_model.config, "include_all_fields", None
407
+ ),
408
+ }
409
+ }
410
+ if getattr(parameter_model, "config", None)
411
+ else {}
412
+ ),
413
+ )
414
+
415
+ self._api_client._verify_response(return_value)
416
+ return return_value
417
+
418
+ def _create_multimodal_dataset(
419
+ self,
420
+ *,
421
+ name: Optional[str] = None,
422
+ display_name: Optional[str] = None,
423
+ metadata_schema_uri: Optional[str] = None,
424
+ metadata: Optional[types.SchemaTablesDatasetMetadataOrDict] = None,
425
+ description: Optional[str] = None,
426
+ encryption_spec: Optional[genai_types.EncryptionSpecOrDict] = None,
427
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
428
+ ) -> types.MultimodalDatasetOperation:
429
+ """
430
+ Creates a dataset resource to store multimodal datasets.
431
+ """
432
+
433
+ parameter_model = types._CreateMultimodalDatasetParameters(
434
+ name=name,
435
+ display_name=display_name,
436
+ metadata_schema_uri=metadata_schema_uri,
437
+ metadata=metadata,
438
+ description=description,
439
+ encryption_spec=encryption_spec,
440
+ config=config,
441
+ )
442
+
443
+ request_url_dict: Optional[dict[str, str]]
444
+ if not self._api_client.vertexai:
445
+ raise ValueError(
446
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
447
+ )
448
+ else:
449
+ request_dict = _CreateMultimodalDatasetParameters_to_vertex(parameter_model)
450
+ request_url_dict = request_dict.get("_url")
451
+ if request_url_dict:
452
+ path = "datasets".format_map(request_url_dict)
453
+ else:
454
+ path = "datasets"
455
+
456
+ query_params = request_dict.get("_query")
457
+ if query_params:
458
+ path = f"{path}?{urlencode(query_params)}"
459
+ # TODO: remove the hack that pops config.
460
+ request_dict.pop("config", None)
461
+
462
+ http_options: Optional[types.HttpOptions] = None
463
+ if (
464
+ parameter_model.config is not None
465
+ and parameter_model.config.http_options is not None
466
+ ):
467
+ http_options = parameter_model.config.http_options
468
+
469
+ request_dict = _common.convert_to_dict(request_dict)
470
+ request_dict = _common.encode_unserializable_types(request_dict)
471
+
472
+ response = self._api_client.request("post", path, request_dict, http_options)
473
+
474
+ response_dict = {} if not response.body else json.loads(response.body)
475
+
476
+ return_value = types.MultimodalDatasetOperation._from_response(
477
+ response=response_dict,
478
+ kwargs=(
479
+ {
480
+ "config": {
481
+ "response_schema": getattr(
482
+ parameter_model.config, "response_schema", None
483
+ ),
484
+ "response_json_schema": getattr(
485
+ parameter_model.config, "response_json_schema", None
486
+ ),
487
+ "include_all_fields": getattr(
488
+ parameter_model.config, "include_all_fields", None
489
+ ),
490
+ }
491
+ }
492
+ if getattr(parameter_model, "config", None)
493
+ else {}
494
+ ),
495
+ )
496
+
497
+ self._api_client._verify_response(return_value)
498
+ return return_value
499
+
500
+ def _delete_multimodal_dataset(
501
+ self, *, name: str, config: Optional[types.VertexBaseConfigOrDict] = None
502
+ ) -> types.MultimodalDatasetOperation:
503
+ """
504
+ Deletes a multimodal dataset resource.
505
+ """
506
+
507
+ parameter_model = types._DeleteMultimodalDatasetRequestParameters(
508
+ name=name,
509
+ config=config,
510
+ )
511
+
512
+ request_url_dict: Optional[dict[str, str]]
513
+ if not self._api_client.vertexai:
514
+ raise ValueError(
515
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
516
+ )
517
+ else:
518
+ request_dict = _DeleteMultimodalDatasetRequestParameters_to_vertex(
519
+ parameter_model
520
+ )
521
+ request_url_dict = request_dict.get("_url")
522
+ if request_url_dict:
523
+ path = "{name}".format_map(request_url_dict)
524
+ else:
525
+ path = "{name}"
526
+
527
+ query_params = request_dict.get("_query")
528
+ if query_params:
529
+ path = f"{path}?{urlencode(query_params)}"
530
+ # TODO: remove the hack that pops config.
531
+ request_dict.pop("config", None)
532
+
533
+ http_options: Optional[types.HttpOptions] = None
534
+ if (
535
+ parameter_model.config is not None
536
+ and parameter_model.config.http_options is not None
537
+ ):
538
+ http_options = parameter_model.config.http_options
539
+
540
+ request_dict = _common.convert_to_dict(request_dict)
541
+ request_dict = _common.encode_unserializable_types(request_dict)
542
+
543
+ response = self._api_client.request("delete", path, request_dict, http_options)
544
+
545
+ response_dict = {} if not response.body else json.loads(response.body)
546
+
547
+ return_value = types.MultimodalDatasetOperation._from_response(
548
+ response=response_dict,
549
+ kwargs=(
550
+ {
551
+ "config": {
552
+ "response_schema": getattr(
553
+ parameter_model.config, "response_schema", None
554
+ ),
555
+ "response_json_schema": getattr(
556
+ parameter_model.config, "response_json_schema", None
557
+ ),
558
+ "include_all_fields": getattr(
559
+ parameter_model.config, "include_all_fields", None
560
+ ),
561
+ }
562
+ }
563
+ if getattr(parameter_model, "config", None)
564
+ else {}
565
+ ),
566
+ )
567
+
568
+ self._api_client._verify_response(return_value)
569
+ return return_value
570
+
571
+ def _get_multimodal_dataset(
572
+ self,
573
+ *,
574
+ name: Optional[str] = None,
575
+ config: Optional[types.VertexBaseConfigOrDict] = None,
576
+ ) -> types.MultimodalDataset:
577
+ """
578
+ Gets a multimodal dataset resource.
579
+ """
580
+
581
+ parameter_model = types._GetMultimodalDatasetParameters(
582
+ name=name,
583
+ config=config,
584
+ )
585
+
586
+ request_url_dict: Optional[dict[str, str]]
587
+ if not self._api_client.vertexai:
588
+ raise ValueError(
589
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
590
+ )
591
+ else:
592
+ request_dict = _GetMultimodalDatasetParameters_to_vertex(parameter_model)
593
+ request_url_dict = request_dict.get("_url")
594
+ if request_url_dict:
595
+ path = "{name}".format_map(request_url_dict)
596
+ else:
597
+ path = "{name}"
598
+
599
+ query_params = request_dict.get("_query")
600
+ if query_params:
601
+ path = f"{path}?{urlencode(query_params)}"
602
+ # TODO: remove the hack that pops config.
603
+ request_dict.pop("config", None)
604
+
605
+ http_options: Optional[types.HttpOptions] = None
606
+ if (
607
+ parameter_model.config is not None
608
+ and parameter_model.config.http_options is not None
609
+ ):
610
+ http_options = parameter_model.config.http_options
611
+
612
+ request_dict = _common.convert_to_dict(request_dict)
613
+ request_dict = _common.encode_unserializable_types(request_dict)
614
+
615
+ response = self._api_client.request("get", path, request_dict, http_options)
616
+
617
+ response_dict = {} if not response.body else json.loads(response.body)
618
+
619
+ return_value = types.MultimodalDataset._from_response(
620
+ response=response_dict,
621
+ kwargs=(
622
+ {
623
+ "config": {
624
+ "response_schema": getattr(
625
+ parameter_model.config, "response_schema", None
626
+ ),
627
+ "response_json_schema": getattr(
628
+ parameter_model.config, "response_json_schema", None
629
+ ),
630
+ "include_all_fields": getattr(
631
+ parameter_model.config, "include_all_fields", None
632
+ ),
633
+ }
634
+ }
635
+ if getattr(parameter_model, "config", None)
636
+ else {}
637
+ ),
638
+ )
639
+
640
+ self._api_client._verify_response(return_value)
641
+ return return_value
642
+
643
+ def _get_multimodal_dataset_operation(
644
+ self,
645
+ *,
646
+ dataset_id: Optional[str] = None,
647
+ operation_id: Optional[str] = None,
648
+ config: Optional[types.GetMultimodalDatasetOperationConfigOrDict] = None,
649
+ ) -> types.MultimodalDatasetOperation:
650
+ """
651
+ Gets the operation from creating a multimodal dataset.
652
+ """
653
+
654
+ parameter_model = types._GetMultimodalDatasetOperationParameters(
655
+ dataset_id=dataset_id,
656
+ operation_id=operation_id,
657
+ config=config,
658
+ )
659
+
660
+ request_url_dict: Optional[dict[str, str]]
661
+ if not self._api_client.vertexai:
662
+ raise ValueError(
663
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
664
+ )
665
+ else:
666
+ request_dict = _GetMultimodalDatasetOperationParameters_to_vertex(
667
+ parameter_model
668
+ )
669
+ request_url_dict = request_dict.get("_url")
670
+ if request_url_dict:
671
+ path = "datasets/{dataset_id}/operations/{operation_id}".format_map(
672
+ request_url_dict
673
+ )
674
+ else:
675
+ path = "datasets/{dataset_id}/operations/{operation_id}"
676
+
677
+ query_params = request_dict.get("_query")
678
+ if query_params:
679
+ path = f"{path}?{urlencode(query_params)}"
680
+ # TODO: remove the hack that pops config.
681
+ request_dict.pop("config", None)
682
+
683
+ http_options: Optional[types.HttpOptions] = None
684
+ if (
685
+ parameter_model.config is not None
686
+ and parameter_model.config.http_options is not None
687
+ ):
688
+ http_options = parameter_model.config.http_options
689
+
690
+ request_dict = _common.convert_to_dict(request_dict)
691
+ request_dict = _common.encode_unserializable_types(request_dict)
692
+
693
+ response = self._api_client.request("get", path, request_dict, http_options)
694
+
695
+ response_dict = {} if not response.body else json.loads(response.body)
696
+
697
+ return_value = types.MultimodalDatasetOperation._from_response(
698
+ response=response_dict,
699
+ kwargs=(
700
+ {
701
+ "config": {
702
+ "response_schema": getattr(
703
+ parameter_model.config, "response_schema", None
704
+ ),
705
+ "response_json_schema": getattr(
706
+ parameter_model.config, "response_json_schema", None
707
+ ),
708
+ "include_all_fields": getattr(
709
+ parameter_model.config, "include_all_fields", None
710
+ ),
711
+ }
712
+ }
713
+ if getattr(parameter_model, "config", None)
714
+ else {}
715
+ ),
716
+ )
717
+
718
+ self._api_client._verify_response(return_value)
719
+ return return_value
720
+
721
+ def _list_multimodal_datasets(
722
+ self, *, config: Optional[types.ListMultimodalDatasetsConfigOrDict] = None
723
+ ) -> types.ListMultimodalDatasetsResponse:
724
+ """
725
+ Lists multimodal datasets.
726
+ """
727
+
728
+ parameter_model = types._ListMultimodalDatasetsRequestParameters(
729
+ config=config,
730
+ )
731
+
732
+ request_url_dict: Optional[dict[str, str]]
733
+ if not self._api_client.vertexai:
734
+ raise ValueError(
735
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
736
+ )
737
+ else:
738
+ request_dict = _ListMultimodalDatasetsRequestParameters_to_vertex(
739
+ parameter_model
740
+ )
741
+ request_url_dict = request_dict.get("_url")
742
+ if request_url_dict:
743
+ path = "datasets".format_map(request_url_dict)
744
+ else:
745
+ path = "datasets"
746
+
747
+ query_params = request_dict.get("_query")
748
+ if query_params:
749
+ path = f"{path}?{urlencode(query_params)}"
750
+ # TODO: remove the hack that pops config.
751
+ request_dict.pop("config", None)
752
+
753
+ http_options: Optional[types.HttpOptions] = None
754
+ if (
755
+ parameter_model.config is not None
756
+ and parameter_model.config.http_options is not None
757
+ ):
758
+ http_options = parameter_model.config.http_options
759
+
760
+ request_dict = _common.convert_to_dict(request_dict)
761
+ request_dict = _common.encode_unserializable_types(request_dict)
762
+
763
+ response = self._api_client.request("get", path, request_dict, http_options)
764
+
765
+ response_dict = {} if not response.body else json.loads(response.body)
766
+
767
+ return_value = types.ListMultimodalDatasetsResponse._from_response(
768
+ response=response_dict,
769
+ kwargs=(
770
+ {
771
+ "config": {
772
+ "response_schema": getattr(
773
+ parameter_model.config, "response_schema", None
774
+ ),
775
+ "response_json_schema": getattr(
776
+ parameter_model.config, "response_json_schema", None
777
+ ),
778
+ "include_all_fields": getattr(
779
+ parameter_model.config, "include_all_fields", None
780
+ ),
781
+ }
782
+ }
783
+ if getattr(parameter_model, "config", None)
784
+ else {}
785
+ ),
786
+ )
787
+
788
+ self._api_client._verify_response(return_value)
789
+ return return_value
790
+
791
+ def _update_multimodal_dataset(
792
+ self,
793
+ *,
794
+ name: Optional[str] = None,
795
+ display_name: Optional[str] = None,
796
+ metadata: Optional[types.SchemaTablesDatasetMetadataOrDict] = None,
797
+ description: Optional[str] = None,
798
+ encryption_spec: Optional[genai_types.EncryptionSpecOrDict] = None,
799
+ config: Optional[types.VertexBaseConfigOrDict] = None,
800
+ ) -> types.MultimodalDataset:
801
+ """
802
+ Updates a multimodal dataset resource.
803
+ """
804
+
805
+ parameter_model = types._UpdateMultimodalDatasetParameters(
806
+ name=name,
807
+ display_name=display_name,
808
+ metadata=metadata,
809
+ description=description,
810
+ encryption_spec=encryption_spec,
811
+ config=config,
812
+ )
813
+
814
+ request_url_dict: Optional[dict[str, str]]
815
+ if not self._api_client.vertexai:
816
+ raise ValueError(
817
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
818
+ )
819
+ else:
820
+ request_dict = _UpdateMultimodalDatasetParameters_to_vertex(parameter_model)
821
+ request_url_dict = request_dict.get("_url")
822
+ if request_url_dict:
823
+ path = "{name}".format_map(request_url_dict)
824
+ else:
825
+ path = "{name}"
826
+
827
+ query_params = request_dict.get("_query")
828
+ if query_params:
829
+ path = f"{path}?{urlencode(query_params)}"
830
+ # TODO: remove the hack that pops config.
831
+ request_dict.pop("config", None)
832
+
833
+ http_options: Optional[types.HttpOptions] = None
834
+ if (
835
+ parameter_model.config is not None
836
+ and parameter_model.config.http_options is not None
837
+ ):
838
+ http_options = parameter_model.config.http_options
839
+
840
+ request_dict = _common.convert_to_dict(request_dict)
841
+ request_dict = _common.encode_unserializable_types(request_dict)
842
+
843
+ response = self._api_client.request("patch", path, request_dict, http_options)
844
+
845
+ response_dict = {} if not response.body else json.loads(response.body)
846
+
847
+ return_value = types.MultimodalDataset._from_response(
848
+ response=response_dict,
849
+ kwargs=(
850
+ {
851
+ "config": {
852
+ "response_schema": getattr(
853
+ parameter_model.config, "response_schema", None
854
+ ),
855
+ "response_json_schema": getattr(
856
+ parameter_model.config, "response_json_schema", None
857
+ ),
858
+ "include_all_fields": getattr(
859
+ parameter_model.config, "include_all_fields", None
860
+ ),
861
+ }
862
+ }
863
+ if getattr(parameter_model, "config", None)
864
+ else {}
865
+ ),
866
+ )
867
+
868
+ self._api_client._verify_response(return_value)
869
+ return return_value
870
+
871
+ def _wait_for_operation(
872
+ self,
873
+ operation: types.MultimodalDatasetOperation,
874
+ timeout_seconds: int,
875
+ ) -> dict[str, Any]:
876
+ """Waits for a multimodal or assemble dataset operation to complete.
877
+
878
+ Args:
879
+ operation: The multimodal or assemble dataset operation to wait for.
880
+ timeout_seconds: The maximum time in seconds to wait for the operation
881
+ to complete.
882
+
883
+ Returns:
884
+ A dict containing the operation response.
885
+
886
+ Raises:
887
+ TimeoutError: If the operation does not complete within the timeout.
888
+ ValueError: If the operation fails.
889
+ """
890
+ response_operation_name = operation.name
891
+ if response_operation_name is None:
892
+ raise ValueError("Dataset operation name is empty.")
893
+ dataset_id = response_operation_name.split("/datasets/")[1].split("/")[0]
894
+ operation_id = response_operation_name.split("/")[-1]
895
+
896
+ start_time = time.time()
897
+ sleep_duration_seconds = 5
898
+ wait_multiplier = 2
899
+ max_wait_time_seconds = 60
900
+
901
+ while (time.time() - start_time) < timeout_seconds:
902
+ operation = self._get_multimodal_dataset_operation(
903
+ dataset_id=dataset_id,
904
+ operation_id=operation_id,
905
+ )
906
+ if operation.done:
907
+ break
908
+ time.sleep(sleep_duration_seconds)
909
+ sleep_duration_seconds = min(
910
+ sleep_duration_seconds * wait_multiplier, max_wait_time_seconds
911
+ )
912
+ else:
913
+ raise TimeoutError(
914
+ "The operation did not complete within the"
915
+ f" specified timeout of {timeout_seconds} seconds."
916
+ )
917
+ if not operation or operation.response is None:
918
+ logger.error(f"Error running the operation {operation.response}.")
919
+ raise ValueError(f"Error running the operation {operation.response}.")
920
+ if hasattr(operation, "error") and operation.error is not None:
921
+ raise ValueError(f"Error running the operation {operation.error}")
922
+ return operation.response
923
+
924
+ def create_from_bigquery(
925
+ self,
926
+ *,
927
+ bigquery_uri: Optional[str] = None,
928
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
929
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
930
+ ) -> types.MultimodalDataset:
931
+ """Creates a multimodal dataset from a BigQuery table.
932
+
933
+ Args:
934
+ bigquery_uri:
935
+ Optional. The BigQuery URI of the table to create the dataset from.
936
+ e.g. "bq://project.dataset.table". If both `bigquery_uri` and
937
+ `multimodal_dataset` are provided, and `multimodal_dataset` also
938
+ contains a BigQuery URI, the `bigquery_uri` parameter takes precedence.
939
+ multimodal_dataset:
940
+ Optional. A representation of a multimodal dataset. If `bigquery_uri`
941
+ is set, `multimodal_dataset` can still be used to set other metadata
942
+ fields. If both `bigquery_uri` and `multimodal_dataset` are provided,
943
+ and `multimodal_dataset` also contains a BigQuery URI, the
944
+ `bigquery_uri` parameter takes precedence.
945
+ config:
946
+ Optional. A configuration for creating the multimodal dataset. If not
947
+ provided, the default configuration will be used.
948
+
949
+ Returns:
950
+ A types.MultimodalDataset object representing a multimodal dataset.
951
+ """
952
+ if not bigquery_uri and not multimodal_dataset:
953
+ raise ValueError(
954
+ "At least one of `bigquery_uri` or `multimodal_dataset` must be"
955
+ " provided."
956
+ )
957
+
958
+ if multimodal_dataset is None:
959
+ multimodal_dataset = types.MultimodalDataset()
960
+ elif isinstance(multimodal_dataset, dict):
961
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
962
+
963
+ if bigquery_uri:
964
+ multimodal_dataset = multimodal_dataset.model_copy(deep=True)
965
+ multimodal_dataset.set_bigquery_uri(bigquery_uri)
966
+
967
+ _datasets_utils.validate_multimodal_dataset_bigquery_uri(multimodal_dataset)
968
+
969
+ if isinstance(config, dict):
970
+ config = types.CreateMultimodalDatasetConfig(**config)
971
+ elif not config:
972
+ config = types.CreateMultimodalDatasetConfig()
973
+
974
+ display_name = (
975
+ multimodal_dataset.display_name
976
+ if multimodal_dataset.display_name is not None
977
+ else _datasets_utils.generate_multimodal_dataset_display_name()
978
+ )
979
+ multimodal_dataset_operation = self._create_multimodal_dataset(
980
+ config=config,
981
+ display_name=display_name,
982
+ metadata_schema_uri=_datasets_utils.METADATA_SCHEMA_URI,
983
+ metadata=multimodal_dataset.metadata,
984
+ )
985
+ response = self._wait_for_operation(
986
+ operation=multimodal_dataset_operation,
987
+ timeout_seconds=config.timeout,
988
+ )
989
+ return _datasets_utils.create_from_response(
990
+ types.MultimodalDataset, response, config
991
+ )
992
+
993
+ def create_from_pandas(
994
+ self,
995
+ *,
996
+ dataframe: pd.DataFrame,
997
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
998
+ target_table_id: Optional[str] = None,
999
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
1000
+ ) -> types.MultimodalDataset:
1001
+ """Creates a multimodal dataset from a pandas dataframe.
1002
+
1003
+ Args:
1004
+ dataframe (pandas.DataFrame):
1005
+ The pandas dataframe to be used for the created dataset.
1006
+ multimodal_dataset:
1007
+ Optional. A representation of a multimodal dataset.
1008
+ target_table_id (str):
1009
+ Optional. The BigQuery table id where the dataframe will be
1010
+ uploaded. The table id can be in the format of "dataset.table"
1011
+ or "project.dataset.table". Note that the BigQuery
1012
+ dataset must already exist and be in the same location as the
1013
+ multimodal dataset. If not provided, a generated table id will
1014
+ be created in the `vertex_datasets` dataset (e.g.
1015
+ `project.vertex_datasets_us_central1.multimodal_dataset_4cbf7ffd`).
1016
+ config:
1017
+ Optional. A configuration for creating the multimodal dataset. If not
1018
+ provided, the default configuration will be used.
1019
+
1020
+ Returns:
1021
+ dataset (MultimodalDataset):
1022
+ The created multimodal dataset.
1023
+ """
1024
+ if isinstance(multimodal_dataset, dict):
1025
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
1026
+ elif not multimodal_dataset:
1027
+ multimodal_dataset = types.MultimodalDataset()
1028
+
1029
+ bigframes = _datasets_utils._try_import_bigframes()
1030
+ project = self._api_client.project
1031
+ location = self._api_client.location
1032
+ credentials = self._api_client._credentials
1033
+
1034
+ session_options = bigframes.BigQueryOptions(
1035
+ credentials=credentials,
1036
+ project=project,
1037
+ location=location,
1038
+ )
1039
+ with bigframes.connect(session_options) as session:
1040
+ return self.create_from_bigframes(
1041
+ dataframe=session.read_pandas(dataframe),
1042
+ multimodal_dataset=multimodal_dataset,
1043
+ target_table_id=target_table_id,
1044
+ config=config,
1045
+ )
1046
+
1047
+ def create_from_bigframes(
1048
+ self,
1049
+ *,
1050
+ dataframe: "bigframes.pandas.DataFrame", # type: ignore # noqa: F821
1051
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
1052
+ target_table_id: Optional[str] = None,
1053
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
1054
+ ) -> types.MultimodalDataset:
1055
+ """Creates a multimodal dataset from a bigframes dataframe.
1056
+
1057
+ Args:
1058
+ dataframe (bigframes.pandas.DataFrame):
1059
+ The BigFrames dataframe that will be used for the created
1060
+ dataset.
1061
+ multimodal_dataset:
1062
+ Optional. A representation of a multimodal dataset.
1063
+ target_table_id (str):
1064
+ Optional. The BigQuery table id where the dataframe will be
1065
+ uploaded. The table id can be in the format of "dataset.table"
1066
+ or "project.dataset.table". Note that the BigQuery
1067
+ dataset must already exist and be in the same location as the
1068
+ multimodal dataset. If not provided, a generated table id will
1069
+ be created in the `vertex_datasets` dataset (e.g.
1070
+ `project.vertex_datasets_us_central1.multimodal_dataset_4cbf7ffd`).
1071
+ config:
1072
+ Optional. A configuration for creating the multimodal dataset. If not
1073
+ provided, the default configuration will be used.
1074
+
1075
+ Returns:
1076
+ dataset (MultimodalDataset):
1077
+ The created multimodal dataset.
1078
+ """
1079
+ if isinstance(multimodal_dataset, dict):
1080
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
1081
+ elif not multimodal_dataset:
1082
+ multimodal_dataset = types.MultimodalDataset()
1083
+
1084
+ bigquery = _datasets_utils._try_import_bigquery()
1085
+ project = self._api_client.project
1086
+ location = self._api_client.location
1087
+ credentials = self._api_client._credentials
1088
+
1089
+ if target_table_id:
1090
+ target_table_id = _datasets_utils._normalize_and_validate_table_id(
1091
+ table_id=target_table_id,
1092
+ project=project,
1093
+ location=location,
1094
+ credentials=credentials,
1095
+ )
1096
+ else:
1097
+ dataset_id = _datasets_utils._create_default_bigquery_dataset_if_not_exists(
1098
+ project=project, location=location, credentials=credentials
1099
+ )
1100
+ target_table_id = _datasets_utils._generate_target_table_id(dataset_id)
1101
+
1102
+ client = bigquery.Client(project=project, credentials=credentials)
1103
+ _datasets_utils.save_dataframe_to_bigquery(
1104
+ dataframe,
1105
+ target_table_id,
1106
+ client,
1107
+ )
1108
+
1109
+ multimodal_dataset = multimodal_dataset.model_copy(deep=True)
1110
+ multimodal_dataset.set_bigquery_uri(f"bq://{target_table_id}")
1111
+ return self.create_from_bigquery(
1112
+ multimodal_dataset=multimodal_dataset, config=config
1113
+ )
1114
+
1115
+ def create_from_gemini_request_jsonl(
1116
+ self,
1117
+ *,
1118
+ gcs_uri: str,
1119
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
1120
+ target_table_id: Optional[str] = None,
1121
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
1122
+ ) -> types.MultimodalDataset:
1123
+ """Creates a multimodal dataset from a JSONL file stored on GCS.
1124
+
1125
+ The JSONL file should contain instances of Gemini
1126
+ `GenerateContentRequest` on each line. The data will be stored in a
1127
+ BigQuery table with a single column called "requests". The
1128
+ request_column_name in the dataset metadata will be set to "requests".
1129
+
1130
+ Args:
1131
+ gcs_uri (str):
1132
+ The Google Cloud Storage URI of the JSONL file to import.
1133
+ For example, 'gs://my-bucket/path/to/data.jsonl'
1134
+ multimodal_dataset:
1135
+ Optional. A representation of a multimodal dataset.
1136
+ target_table_id (str):
1137
+ Optional. The BigQuery table id where the dataframe will be
1138
+ uploaded. The table id can be in the format of "dataset.table"
1139
+ or "project.dataset.table". Note that the BigQuery
1140
+ dataset must already exist and be in the same location as the
1141
+ multimodal dataset. If not provided, a generated table id will
1142
+ be created in the `vertex_datasets` dataset (e.g.
1143
+ `project.vertex_datasets_us_central1.multimodal_dataset_4cbf7ffd`).
1144
+ config:
1145
+ Optional. A configuration for creating the multimodal dataset. If not
1146
+ provided, the default configuration will be used.
1147
+
1148
+ Returns:
1149
+ The created multimodal dataset.
1150
+ """
1151
+ bigquery = _datasets_utils._try_import_bigquery()
1152
+
1153
+ if isinstance(multimodal_dataset, dict):
1154
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
1155
+ elif not multimodal_dataset:
1156
+ multimodal_dataset = types.MultimodalDataset()
1157
+
1158
+ if not gcs_uri.startswith("gs://"):
1159
+ raise ValueError(
1160
+ "Invalid GCS URI format. Expected: gs://bucket-name/object-path"
1161
+ )
1162
+
1163
+ project = self._api_client.project
1164
+ location = self._api_client.location
1165
+ credentials = self._api_client._credentials
1166
+
1167
+ if target_table_id:
1168
+ target_table_id = _datasets_utils._normalize_and_validate_table_id(
1169
+ table_id=target_table_id,
1170
+ project=project,
1171
+ location=location,
1172
+ credentials=credentials,
1173
+ )
1174
+ else:
1175
+ dataset_id = _datasets_utils._create_default_bigquery_dataset_if_not_exists(
1176
+ project=project, location=location, credentials=credentials
1177
+ )
1178
+ target_table_id = _datasets_utils._generate_target_table_id(dataset_id)
1179
+
1180
+ request_column_name = "requests"
1181
+
1182
+ # Setup LoadJobConfig to load the JSONL file as a CSV directly from GCS.
1183
+ # We use an unused character (unit separator \x1f) as the field delimiter
1184
+ # and an empty string as the quote character. This forces BigQuery to
1185
+ # treat each line (a valid JSON string) as a single CSV row.
1186
+ job_config = bigquery.LoadJobConfig(
1187
+ source_format=bigquery.SourceFormat.CSV,
1188
+ field_delimiter="\x1f",
1189
+ quote_character="",
1190
+ schema=[bigquery.SchemaField(request_column_name, "JSON")],
1191
+ write_disposition=bigquery.WriteDisposition.WRITE_TRUNCATE,
1192
+ )
1193
+
1194
+ client = bigquery.Client(project=project, credentials=credentials)
1195
+ load_job = client.load_table_from_uri(
1196
+ gcs_uri,
1197
+ target_table_id,
1198
+ job_config=job_config,
1199
+ )
1200
+ load_job.result()
1201
+
1202
+ multimodal_dataset = multimodal_dataset.model_copy(deep=True)
1203
+ metadata = multimodal_dataset.metadata or types.SchemaTablesDatasetMetadata()
1204
+
1205
+ read_config = (
1206
+ metadata.gemini_request_read_config or types.GeminiRequestReadConfig()
1207
+ )
1208
+ read_config.assembled_request_column_name = request_column_name
1209
+ metadata.gemini_request_read_config = read_config
1210
+
1211
+ multimodal_dataset.metadata = metadata
1212
+ multimodal_dataset.set_bigquery_uri(f"bq://{target_table_id}")
1213
+
1214
+ return self.create_from_bigquery(
1215
+ multimodal_dataset=multimodal_dataset, config=config
1216
+ )
1217
+
1218
+ def update_multimodal_dataset(
1219
+ self,
1220
+ *,
1221
+ multimodal_dataset: types.MultimodalDatasetOrDict,
1222
+ config: Optional[types.VertexBaseConfigOrDict] = None,
1223
+ ) -> types.MultimodalDataset:
1224
+ """Updates a multimodal dataset.
1225
+
1226
+ Updatable fields include:
1227
+ - display_name
1228
+ - description
1229
+
1230
+ Args:
1231
+ multimodal_dataset:
1232
+ Required. A representation of a multimodal dataset.
1233
+ config:
1234
+ Optional. A configuration for updating the multimodal dataset. If not
1235
+ provided, the default configuration will be used.
1236
+
1237
+ Returns:
1238
+ A types.MultimodalDataset object representing the retrieved multimodal
1239
+ dataset.
1240
+ """
1241
+ if isinstance(multimodal_dataset, dict):
1242
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
1243
+ _datasets_utils.validate_multimodal_dataset_bigquery_uri(multimodal_dataset)
1244
+
1245
+ if isinstance(config, dict):
1246
+ config = types.VertexBaseConfig(**config)
1247
+ elif not config:
1248
+ config = types.VertexBaseConfig()
1249
+
1250
+ return self._update_multimodal_dataset(
1251
+ config=config,
1252
+ name=multimodal_dataset.name,
1253
+ display_name=multimodal_dataset.display_name,
1254
+ description=multimodal_dataset.description,
1255
+ metadata=multimodal_dataset.metadata,
1256
+ )
1257
+
1258
+ def get_multimodal_dataset(
1259
+ self,
1260
+ *,
1261
+ name: str,
1262
+ config: Optional[types.VertexBaseConfigOrDict] = None,
1263
+ ) -> types.MultimodalDataset:
1264
+ """Gets a multimodal dataset.
1265
+
1266
+ Args:
1267
+ name:
1268
+ Required. A fully-qualified resource name or ID of the dataset.
1269
+ Example: "projects/.../locations/.../datasets/123" or "123".
1270
+ config:
1271
+ Optional. A configuration for getting the multimodal dataset. If not
1272
+ provided, the default configuration will be used.
1273
+
1274
+ Returns:
1275
+ A types.MultimodalDataset object representing the retrieved multimodal
1276
+ dataset.
1277
+ """
1278
+ if isinstance(config, dict):
1279
+ config = types.VertexBaseConfig(**config)
1280
+ elif not config:
1281
+ config = types.VertexBaseConfig()
1282
+
1283
+ name = _datasets_utils.resolve_dataset_name(
1284
+ name, self._api_client.project, self._api_client.location
1285
+ )
1286
+
1287
+ return self._get_multimodal_dataset(config=config, name=name)
1288
+
1289
+ def delete_multimodal_dataset(
1290
+ self,
1291
+ *,
1292
+ name: str,
1293
+ config: Optional[types.VertexBaseConfigOrDict] = None,
1294
+ ) -> types.MultimodalDatasetOperation:
1295
+ """Deletes a multimodal dataset.
1296
+
1297
+ Args:
1298
+ name:
1299
+ Required. A fully-qualified resource name or ID of the dataset.
1300
+ Example: "projects/.../locations/.../datasets/123" or "123".
1301
+ config:
1302
+ Optional. A configuration for deleting the multimodal dataset. If not
1303
+ provided, the default configuration will be used.
1304
+
1305
+ Returns:
1306
+ A types.MultimodalDatasetOperation object representing the delete
1307
+ multimodal dataset operation.
1308
+ """
1309
+ if isinstance(config, dict):
1310
+ config = types.VertexBaseConfig(**config)
1311
+ elif not config:
1312
+ config = types.VertexBaseConfig()
1313
+
1314
+ name = _datasets_utils.resolve_dataset_name(
1315
+ name, self._api_client.project, self._api_client.location
1316
+ )
1317
+
1318
+ return self._delete_multimodal_dataset(config=config, name=name)
1319
+
1320
+ def assemble(
1321
+ self,
1322
+ *,
1323
+ name: str,
1324
+ gemini_request_read_config: Optional[
1325
+ types.GeminiRequestReadConfigOrDict
1326
+ ] = None,
1327
+ load_dataframe: bool = False,
1328
+ config: Optional[types.AssembleDatasetConfigOrDict] = None,
1329
+ ) -> tuple[str, Optional["bigframes.pandas.DataFrame"]]: # type: ignore # noqa: F821
1330
+ """Assemble the dataset into a BigQuery table.
1331
+
1332
+ Waits for the assemble operation to complete before returning.
1333
+
1334
+ Args:
1335
+ name:
1336
+ Required. A fully-qualified resource name or ID of the dataset.
1337
+ Example: "projects/.../locations/.../datasets/123" or "123".
1338
+ gemini_request_read_config:
1339
+ Optional. The read config to use to assemble the dataset. If
1340
+ not provided, the read config attached to the dataset will be
1341
+ used.
1342
+ load_dataframe:
1343
+ Optional. Whether to load the assembled BigQuery table into a
1344
+ BigFrames DataFrame and return it. If False, the returned
1345
+ DataFrame is None, no BigQuery read is performed, and `bigframes`
1346
+ is not required. Defaults to False.
1347
+ config:
1348
+ Optional. A configuration for assembling the dataset. If not
1349
+ provided, the default configuration will be used.
1350
+
1351
+ Returns:
1352
+ A tuple `(table_id, dataframe)`, where `table_id` is the BigQuery
1353
+ table id of the assembled dataset (without the `bq://` prefix) and
1354
+ `dataframe` is the assembled table loaded as a BigFrames DataFrame.
1355
+ `dataframe` is None if `load_dataframe` is False.
1356
+ """
1357
+ if isinstance(config, dict):
1358
+ config = types.AssembleDatasetConfig(**config)
1359
+ elif not config:
1360
+ config = types.AssembleDatasetConfig()
1361
+
1362
+ name = _datasets_utils.resolve_dataset_name(
1363
+ name, self._api_client.project, self._api_client.location
1364
+ )
1365
+
1366
+ operation = self._assemble_multimodal_dataset(
1367
+ name=name,
1368
+ gemini_request_read_config=gemini_request_read_config,
1369
+ config=config,
1370
+ )
1371
+ response = self._wait_for_operation(
1372
+ operation=operation,
1373
+ timeout_seconds=config.timeout,
1374
+ )
1375
+ bigquery_uri = response["bigqueryDestination"]
1376
+ table_id = bigquery_uri.removeprefix("bq://")
1377
+ dataframe = None
1378
+ if load_dataframe:
1379
+ dataframe = _datasets_utils.load_dataframe_from_bigquery(
1380
+ bigquery_uri=bigquery_uri,
1381
+ project=self._api_client.project,
1382
+ location=self._api_client.location,
1383
+ credentials=self._api_client._credentials,
1384
+ )
1385
+ return (table_id, dataframe)
1386
+
1387
+ def assess_tuning_resources(
1388
+ self,
1389
+ *,
1390
+ dataset_name: str,
1391
+ model_name: str,
1392
+ gemini_request_read_config: Optional[
1393
+ types.GeminiRequestReadConfigOrDict
1394
+ ] = None,
1395
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
1396
+ ) -> types.TuningResourceUsageAssessmentResult:
1397
+ """Assess the tuning resources required for a given model.
1398
+
1399
+ Args:
1400
+ dataset_name:
1401
+ Required. A fully-qualified resource name or ID of the dataset.
1402
+ Example: "projects/.../locations/.../datasets/123" or "123".
1403
+ model_name:
1404
+ Required. The name of the model to assess the tuning resources
1405
+ for.
1406
+ gemini_request_read_config:
1407
+ Optional. The read config used to assemble the dataset
1408
+ before assessing the tuning resources. If not provided, the
1409
+ read config attached to the dataset will be used. Required
1410
+ if no read config is attached to the dataset.
1411
+ config:
1412
+ Optional. A configuration for assessing the tuning resources. If not
1413
+ provided, the default configuration will be used.
1414
+
1415
+ Returns:
1416
+ A types.TuningResourceUsageAssessmentResult object representing the
1417
+ tuning resource usage assessment result.
1418
+ """
1419
+ if isinstance(config, dict):
1420
+ config = types.AssessDatasetConfig(**config)
1421
+ elif not config:
1422
+ config = types.AssessDatasetConfig()
1423
+
1424
+ dataset_name = _datasets_utils.resolve_dataset_name(
1425
+ dataset_name, self._api_client.project, self._api_client.location
1426
+ )
1427
+
1428
+ operation = self._assess_multimodal_dataset(
1429
+ name=dataset_name,
1430
+ tuning_resource_usage_assessment_config=types.TuningResourceUsageAssessmentConfig(
1431
+ model_name=model_name
1432
+ ),
1433
+ gemini_request_read_config=gemini_request_read_config,
1434
+ config=config,
1435
+ )
1436
+ response = self._wait_for_operation(
1437
+ operation=operation,
1438
+ timeout_seconds=config.timeout,
1439
+ )
1440
+ return _datasets_utils.create_from_response(
1441
+ types.TuningResourceUsageAssessmentResult,
1442
+ response["tuningResourceUsageAssessmentResult"],
1443
+ config,
1444
+ )
1445
+
1446
+ def assess_tuning_validity(
1447
+ self,
1448
+ *,
1449
+ dataset_name: str,
1450
+ model_name: str,
1451
+ dataset_usage: str,
1452
+ gemini_request_read_config: Optional[
1453
+ types.GeminiRequestReadConfigOrDict
1454
+ ] = None,
1455
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
1456
+ ) -> types.TuningValidationAssessmentResult:
1457
+ """Assess if the assembled dataset is valid in terms of tuning a given
1458
+ model.
1459
+
1460
+ Args:
1461
+ dataset_name:
1462
+ Required. A fully-qualified resource name or ID of the dataset.
1463
+ Example: "projects/.../locations/.../datasets/123" or "123".
1464
+ model_name:
1465
+ Required. The name of the model to assess the tuning validity
1466
+ for.
1467
+ dataset_usage:
1468
+ Required. The dataset usage to assess the tuning validity for.
1469
+ Must be one of the following: SFT_TRAINING, SFT_VALIDATION.
1470
+ gemini_request_read_config:
1471
+ Optional. The read config used to assemble the dataset
1472
+ before assessing the tuning validity. If not provided, the
1473
+ read config attached to the dataset will be used. Required
1474
+ if no read config is attached to the dataset.
1475
+ config:
1476
+ Optional. A configuration for assessing the tuning validity. If not
1477
+ provided, the default configuration will be used.
1478
+
1479
+ Returns:
1480
+ A dict containing the tuning validity assessment result. The dict
1481
+ contains the following keys:
1482
+ - errors: A list of errors that occurred during the tuning validity
1483
+ assessment.
1484
+ """
1485
+ if isinstance(config, dict):
1486
+ config = types.AssessDatasetConfig(**config)
1487
+ elif not config:
1488
+ config = types.AssessDatasetConfig()
1489
+
1490
+ dataset_name = _datasets_utils.resolve_dataset_name(
1491
+ dataset_name, self._api_client.project, self._api_client.location
1492
+ )
1493
+
1494
+ operation = self._assess_multimodal_dataset(
1495
+ name=dataset_name,
1496
+ tuning_validation_assessment_config=types.TuningValidationAssessmentConfig(
1497
+ model_name=model_name,
1498
+ dataset_usage=dataset_usage,
1499
+ ),
1500
+ gemini_request_read_config=gemini_request_read_config,
1501
+ config=config,
1502
+ )
1503
+ response = self._wait_for_operation(
1504
+ operation=operation,
1505
+ timeout_seconds=config.timeout,
1506
+ )
1507
+ return _datasets_utils.create_from_response(
1508
+ types.TuningValidationAssessmentResult,
1509
+ response["tuningValidationAssessmentResult"],
1510
+ config,
1511
+ )
1512
+
1513
+ def assess_batch_prediction_resources(
1514
+ self,
1515
+ *,
1516
+ dataset_name: str,
1517
+ model_name: str,
1518
+ gemini_request_read_config: Optional[
1519
+ types.GeminiRequestReadConfigOrDict
1520
+ ] = None,
1521
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
1522
+ ) -> types.BatchPredictionResourceUsageAssessmentResult:
1523
+ """Assess the batch prediction resources required for a given model.
1524
+
1525
+ Args:
1526
+ dataset_name:
1527
+ Required. A fully-qualified resource name or ID of the dataset.
1528
+ Example: "projects/.../locations/.../datasets/123" or "123".
1529
+ model_name:
1530
+ Required. The name of the model to assess the batch prediction
1531
+ resources.
1532
+ gemini_request_read_config:
1533
+ Optional. The read config used to assemble the dataset
1534
+ before assessing the batch prediction resources. If not provided,
1535
+ the read config attached to the dataset will be used. Required
1536
+ if no read config is attached to the dataset.
1537
+ config:
1538
+ Optional. A configuration for assessing the batch prediction
1539
+ resources. If not provided, the default configuration will be
1540
+ used.
1541
+
1542
+ Returns:
1543
+ A types.BatchPredictionResourceUsageAssessmentResult object
1544
+ representing the batch prediction resource usage assessment result.
1545
+ It contains the following keys:
1546
+ - token_count: The number of tokens in the dataset.
1547
+ - audio_token_count: The number of audio tokens in the dataset.
1548
+
1549
+ """
1550
+ if isinstance(config, dict):
1551
+ config = types.AssessDatasetConfig(**config)
1552
+ elif not config:
1553
+ config = types.AssessDatasetConfig()
1554
+
1555
+ dataset_name = _datasets_utils.resolve_dataset_name(
1556
+ dataset_name, self._api_client.project, self._api_client.location
1557
+ )
1558
+
1559
+ operation = self._assess_multimodal_dataset(
1560
+ name=dataset_name,
1561
+ batch_prediction_resource_usage_assessment_config=types.BatchPredictionResourceUsageAssessmentConfig(
1562
+ model_name=model_name,
1563
+ ),
1564
+ gemini_request_read_config=gemini_request_read_config,
1565
+ config=config,
1566
+ )
1567
+ response = self._wait_for_operation(
1568
+ operation=operation,
1569
+ timeout_seconds=config.timeout,
1570
+ )
1571
+ result = response["batchPredictionResourceUsageAssessmentResult"]
1572
+ return _datasets_utils.create_from_response(
1573
+ types.BatchPredictionResourceUsageAssessmentResult, result, config
1574
+ )
1575
+
1576
+ def assess_batch_prediction_validity(
1577
+ self,
1578
+ *,
1579
+ dataset_name: str,
1580
+ model_name: str,
1581
+ gemini_request_read_config: Optional[
1582
+ types.GeminiRequestReadConfigOrDict
1583
+ ] = None,
1584
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
1585
+ ) -> types.BatchPredictionValidationAssessmentResult:
1586
+ """Assess if the assembled dataset is valid in terms of batch prediction
1587
+ for a given model. Raises an error if the dataset is invalid, otherwise
1588
+ returns None.
1589
+
1590
+ Args:
1591
+ dataset_name:
1592
+ Required. A fully-qualified resource name or ID of the dataset.
1593
+ Example: "projects/.../locations/.../datasets/123" or "123".
1594
+ model_name:
1595
+ Required. The name of the model to assess the batch prediction
1596
+ validity for.
1597
+ gemini_request_read_config:
1598
+ Optional. The read config used to assemble the dataset
1599
+ before assessing the batch prediction validity. If not provided, the
1600
+ read config attached to the dataset will be used. Required
1601
+ if no read config is attached to the dataset.
1602
+ config:
1603
+ Optional. A configuration for assessing the batch prediction validity.
1604
+ If not provided, the default configuration will be used.
1605
+
1606
+ Returns:
1607
+ A types.BatchPredictionValidationAssessmentResult object representing
1608
+ the batch prediction validity assessment result.
1609
+ It contains the following keys:
1610
+ - errors: A list of errors that occurred during the batch prediction
1611
+ validity assessment.
1612
+ """
1613
+ if isinstance(config, dict):
1614
+ config = types.AssessDatasetConfig(**config)
1615
+ elif not config:
1616
+ config = types.AssessDatasetConfig()
1617
+
1618
+ dataset_name = _datasets_utils.resolve_dataset_name(
1619
+ dataset_name, self._api_client.project, self._api_client.location
1620
+ )
1621
+
1622
+ operation = self._assess_multimodal_dataset(
1623
+ name=dataset_name,
1624
+ batch_prediction_validation_assessment_config=types.BatchPredictionValidationAssessmentConfig(
1625
+ model_name=model_name,
1626
+ ),
1627
+ gemini_request_read_config=gemini_request_read_config,
1628
+ config=config,
1629
+ )
1630
+ response = self._wait_for_operation(
1631
+ operation=operation,
1632
+ timeout_seconds=config.timeout,
1633
+ )
1634
+ result = response["batchPredictionValidationAssessmentResult"]
1635
+ return _datasets_utils.create_from_response(
1636
+ types.BatchPredictionValidationAssessmentResult, result, config
1637
+ )
1638
+
1639
+
1640
+ class AsyncDatasets(_api_module.BaseModule):
1641
+
1642
+ async def _assemble_multimodal_dataset(
1643
+ self,
1644
+ *,
1645
+ name: str,
1646
+ gemini_request_read_config: Optional[
1647
+ types.GeminiRequestReadConfigOrDict
1648
+ ] = None,
1649
+ config: Optional[types.AssembleDatasetConfigOrDict] = None,
1650
+ ) -> types.MultimodalDatasetOperation:
1651
+ """
1652
+ Assembles a multimodal dataset resource.
1653
+ """
1654
+
1655
+ parameter_model = types._AssembleDatasetParameters(
1656
+ name=name,
1657
+ gemini_request_read_config=gemini_request_read_config,
1658
+ config=config,
1659
+ )
1660
+
1661
+ request_url_dict: Optional[dict[str, str]]
1662
+ if not self._api_client.vertexai:
1663
+ raise ValueError(
1664
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
1665
+ )
1666
+ else:
1667
+ request_dict = _AssembleDatasetParameters_to_vertex(parameter_model)
1668
+ request_url_dict = request_dict.get("_url")
1669
+ if request_url_dict:
1670
+ path = "{name}:assemble".format_map(request_url_dict)
1671
+ else:
1672
+ path = "{name}:assemble"
1673
+
1674
+ query_params = request_dict.get("_query")
1675
+ if query_params:
1676
+ path = f"{path}?{urlencode(query_params)}"
1677
+ # TODO: remove the hack that pops config.
1678
+ request_dict.pop("config", None)
1679
+
1680
+ http_options: Optional[types.HttpOptions] = None
1681
+ if (
1682
+ parameter_model.config is not None
1683
+ and parameter_model.config.http_options is not None
1684
+ ):
1685
+ http_options = parameter_model.config.http_options
1686
+
1687
+ request_dict = _common.convert_to_dict(request_dict)
1688
+ request_dict = _common.encode_unserializable_types(request_dict)
1689
+
1690
+ response = await self._api_client.async_request(
1691
+ "post", path, request_dict, http_options
1692
+ )
1693
+
1694
+ response_dict = {} if not response.body else json.loads(response.body)
1695
+
1696
+ return_value = types.MultimodalDatasetOperation._from_response(
1697
+ response=response_dict,
1698
+ kwargs=(
1699
+ {
1700
+ "config": {
1701
+ "response_schema": getattr(
1702
+ parameter_model.config, "response_schema", None
1703
+ ),
1704
+ "response_json_schema": getattr(
1705
+ parameter_model.config, "response_json_schema", None
1706
+ ),
1707
+ "include_all_fields": getattr(
1708
+ parameter_model.config, "include_all_fields", None
1709
+ ),
1710
+ }
1711
+ }
1712
+ if getattr(parameter_model, "config", None)
1713
+ else {}
1714
+ ),
1715
+ )
1716
+
1717
+ self._api_client._verify_response(return_value)
1718
+ return return_value
1719
+
1720
+ async def _assess_multimodal_dataset(
1721
+ self,
1722
+ *,
1723
+ name: str,
1724
+ gemini_request_read_config: Optional[
1725
+ types.GeminiRequestReadConfigOrDict
1726
+ ] = None,
1727
+ tuning_resource_usage_assessment_config: Optional[
1728
+ types.TuningResourceUsageAssessmentConfigOrDict
1729
+ ] = None,
1730
+ tuning_validation_assessment_config: Optional[
1731
+ types.TuningValidationAssessmentConfigOrDict
1732
+ ] = None,
1733
+ batch_prediction_resource_usage_assessment_config: Optional[
1734
+ types.BatchPredictionResourceUsageAssessmentConfigOrDict
1735
+ ] = None,
1736
+ batch_prediction_validation_assessment_config: Optional[
1737
+ types.BatchPredictionValidationAssessmentConfigOrDict
1738
+ ] = None,
1739
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
1740
+ ) -> types.MultimodalDatasetOperation:
1741
+ """
1742
+ Assesses a multimodal dataset resource.
1743
+ """
1744
+
1745
+ parameter_model = types._AssessDatasetParameters(
1746
+ name=name,
1747
+ gemini_request_read_config=gemini_request_read_config,
1748
+ tuning_resource_usage_assessment_config=tuning_resource_usage_assessment_config,
1749
+ tuning_validation_assessment_config=tuning_validation_assessment_config,
1750
+ batch_prediction_resource_usage_assessment_config=batch_prediction_resource_usage_assessment_config,
1751
+ batch_prediction_validation_assessment_config=batch_prediction_validation_assessment_config,
1752
+ config=config,
1753
+ )
1754
+
1755
+ request_url_dict: Optional[dict[str, str]]
1756
+ if not self._api_client.vertexai:
1757
+ raise ValueError(
1758
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
1759
+ )
1760
+ else:
1761
+ request_dict = _AssessDatasetParameters_to_vertex(parameter_model)
1762
+ request_url_dict = request_dict.get("_url")
1763
+ if request_url_dict:
1764
+ path = "{name}:assess".format_map(request_url_dict)
1765
+ else:
1766
+ path = "{name}:assess"
1767
+
1768
+ query_params = request_dict.get("_query")
1769
+ if query_params:
1770
+ path = f"{path}?{urlencode(query_params)}"
1771
+ # TODO: remove the hack that pops config.
1772
+ request_dict.pop("config", None)
1773
+
1774
+ http_options: Optional[types.HttpOptions] = None
1775
+ if (
1776
+ parameter_model.config is not None
1777
+ and parameter_model.config.http_options is not None
1778
+ ):
1779
+ http_options = parameter_model.config.http_options
1780
+
1781
+ request_dict = _common.convert_to_dict(request_dict)
1782
+ request_dict = _common.encode_unserializable_types(request_dict)
1783
+
1784
+ response = await self._api_client.async_request(
1785
+ "post", path, request_dict, http_options
1786
+ )
1787
+
1788
+ response_dict = {} if not response.body else json.loads(response.body)
1789
+
1790
+ return_value = types.MultimodalDatasetOperation._from_response(
1791
+ response=response_dict,
1792
+ kwargs=(
1793
+ {
1794
+ "config": {
1795
+ "response_schema": getattr(
1796
+ parameter_model.config, "response_schema", None
1797
+ ),
1798
+ "response_json_schema": getattr(
1799
+ parameter_model.config, "response_json_schema", None
1800
+ ),
1801
+ "include_all_fields": getattr(
1802
+ parameter_model.config, "include_all_fields", None
1803
+ ),
1804
+ }
1805
+ }
1806
+ if getattr(parameter_model, "config", None)
1807
+ else {}
1808
+ ),
1809
+ )
1810
+
1811
+ self._api_client._verify_response(return_value)
1812
+ return return_value
1813
+
1814
+ async def _create_multimodal_dataset(
1815
+ self,
1816
+ *,
1817
+ name: Optional[str] = None,
1818
+ display_name: Optional[str] = None,
1819
+ metadata_schema_uri: Optional[str] = None,
1820
+ metadata: Optional[types.SchemaTablesDatasetMetadataOrDict] = None,
1821
+ description: Optional[str] = None,
1822
+ encryption_spec: Optional[genai_types.EncryptionSpecOrDict] = None,
1823
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
1824
+ ) -> types.MultimodalDatasetOperation:
1825
+ """
1826
+ Creates a dataset resource to store multimodal datasets.
1827
+ """
1828
+
1829
+ parameter_model = types._CreateMultimodalDatasetParameters(
1830
+ name=name,
1831
+ display_name=display_name,
1832
+ metadata_schema_uri=metadata_schema_uri,
1833
+ metadata=metadata,
1834
+ description=description,
1835
+ encryption_spec=encryption_spec,
1836
+ config=config,
1837
+ )
1838
+
1839
+ request_url_dict: Optional[dict[str, str]]
1840
+ if not self._api_client.vertexai:
1841
+ raise ValueError(
1842
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
1843
+ )
1844
+ else:
1845
+ request_dict = _CreateMultimodalDatasetParameters_to_vertex(parameter_model)
1846
+ request_url_dict = request_dict.get("_url")
1847
+ if request_url_dict:
1848
+ path = "datasets".format_map(request_url_dict)
1849
+ else:
1850
+ path = "datasets"
1851
+
1852
+ query_params = request_dict.get("_query")
1853
+ if query_params:
1854
+ path = f"{path}?{urlencode(query_params)}"
1855
+ # TODO: remove the hack that pops config.
1856
+ request_dict.pop("config", None)
1857
+
1858
+ http_options: Optional[types.HttpOptions] = None
1859
+ if (
1860
+ parameter_model.config is not None
1861
+ and parameter_model.config.http_options is not None
1862
+ ):
1863
+ http_options = parameter_model.config.http_options
1864
+
1865
+ request_dict = _common.convert_to_dict(request_dict)
1866
+ request_dict = _common.encode_unserializable_types(request_dict)
1867
+
1868
+ response = await self._api_client.async_request(
1869
+ "post", path, request_dict, http_options
1870
+ )
1871
+
1872
+ response_dict = {} if not response.body else json.loads(response.body)
1873
+
1874
+ return_value = types.MultimodalDatasetOperation._from_response(
1875
+ response=response_dict,
1876
+ kwargs=(
1877
+ {
1878
+ "config": {
1879
+ "response_schema": getattr(
1880
+ parameter_model.config, "response_schema", None
1881
+ ),
1882
+ "response_json_schema": getattr(
1883
+ parameter_model.config, "response_json_schema", None
1884
+ ),
1885
+ "include_all_fields": getattr(
1886
+ parameter_model.config, "include_all_fields", None
1887
+ ),
1888
+ }
1889
+ }
1890
+ if getattr(parameter_model, "config", None)
1891
+ else {}
1892
+ ),
1893
+ )
1894
+
1895
+ self._api_client._verify_response(return_value)
1896
+ return return_value
1897
+
1898
+ async def _delete_multimodal_dataset(
1899
+ self, *, name: str, config: Optional[types.VertexBaseConfigOrDict] = None
1900
+ ) -> types.MultimodalDatasetOperation:
1901
+ """
1902
+ Deletes a multimodal dataset resource.
1903
+ """
1904
+
1905
+ parameter_model = types._DeleteMultimodalDatasetRequestParameters(
1906
+ name=name,
1907
+ config=config,
1908
+ )
1909
+
1910
+ request_url_dict: Optional[dict[str, str]]
1911
+ if not self._api_client.vertexai:
1912
+ raise ValueError(
1913
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
1914
+ )
1915
+ else:
1916
+ request_dict = _DeleteMultimodalDatasetRequestParameters_to_vertex(
1917
+ parameter_model
1918
+ )
1919
+ request_url_dict = request_dict.get("_url")
1920
+ if request_url_dict:
1921
+ path = "{name}".format_map(request_url_dict)
1922
+ else:
1923
+ path = "{name}"
1924
+
1925
+ query_params = request_dict.get("_query")
1926
+ if query_params:
1927
+ path = f"{path}?{urlencode(query_params)}"
1928
+ # TODO: remove the hack that pops config.
1929
+ request_dict.pop("config", None)
1930
+
1931
+ http_options: Optional[types.HttpOptions] = None
1932
+ if (
1933
+ parameter_model.config is not None
1934
+ and parameter_model.config.http_options is not None
1935
+ ):
1936
+ http_options = parameter_model.config.http_options
1937
+
1938
+ request_dict = _common.convert_to_dict(request_dict)
1939
+ request_dict = _common.encode_unserializable_types(request_dict)
1940
+
1941
+ response = await self._api_client.async_request(
1942
+ "delete", path, request_dict, http_options
1943
+ )
1944
+
1945
+ response_dict = {} if not response.body else json.loads(response.body)
1946
+
1947
+ return_value = types.MultimodalDatasetOperation._from_response(
1948
+ response=response_dict,
1949
+ kwargs=(
1950
+ {
1951
+ "config": {
1952
+ "response_schema": getattr(
1953
+ parameter_model.config, "response_schema", None
1954
+ ),
1955
+ "response_json_schema": getattr(
1956
+ parameter_model.config, "response_json_schema", None
1957
+ ),
1958
+ "include_all_fields": getattr(
1959
+ parameter_model.config, "include_all_fields", None
1960
+ ),
1961
+ }
1962
+ }
1963
+ if getattr(parameter_model, "config", None)
1964
+ else {}
1965
+ ),
1966
+ )
1967
+
1968
+ self._api_client._verify_response(return_value)
1969
+ return return_value
1970
+
1971
+ async def _get_multimodal_dataset(
1972
+ self,
1973
+ *,
1974
+ name: Optional[str] = None,
1975
+ config: Optional[types.VertexBaseConfigOrDict] = None,
1976
+ ) -> types.MultimodalDataset:
1977
+ """
1978
+ Gets a multimodal dataset resource.
1979
+ """
1980
+
1981
+ parameter_model = types._GetMultimodalDatasetParameters(
1982
+ name=name,
1983
+ config=config,
1984
+ )
1985
+
1986
+ request_url_dict: Optional[dict[str, str]]
1987
+ if not self._api_client.vertexai:
1988
+ raise ValueError(
1989
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
1990
+ )
1991
+ else:
1992
+ request_dict = _GetMultimodalDatasetParameters_to_vertex(parameter_model)
1993
+ request_url_dict = request_dict.get("_url")
1994
+ if request_url_dict:
1995
+ path = "{name}".format_map(request_url_dict)
1996
+ else:
1997
+ path = "{name}"
1998
+
1999
+ query_params = request_dict.get("_query")
2000
+ if query_params:
2001
+ path = f"{path}?{urlencode(query_params)}"
2002
+ # TODO: remove the hack that pops config.
2003
+ request_dict.pop("config", None)
2004
+
2005
+ http_options: Optional[types.HttpOptions] = None
2006
+ if (
2007
+ parameter_model.config is not None
2008
+ and parameter_model.config.http_options is not None
2009
+ ):
2010
+ http_options = parameter_model.config.http_options
2011
+
2012
+ request_dict = _common.convert_to_dict(request_dict)
2013
+ request_dict = _common.encode_unserializable_types(request_dict)
2014
+
2015
+ response = await self._api_client.async_request(
2016
+ "get", path, request_dict, http_options
2017
+ )
2018
+
2019
+ response_dict = {} if not response.body else json.loads(response.body)
2020
+
2021
+ return_value = types.MultimodalDataset._from_response(
2022
+ response=response_dict,
2023
+ kwargs=(
2024
+ {
2025
+ "config": {
2026
+ "response_schema": getattr(
2027
+ parameter_model.config, "response_schema", None
2028
+ ),
2029
+ "response_json_schema": getattr(
2030
+ parameter_model.config, "response_json_schema", None
2031
+ ),
2032
+ "include_all_fields": getattr(
2033
+ parameter_model.config, "include_all_fields", None
2034
+ ),
2035
+ }
2036
+ }
2037
+ if getattr(parameter_model, "config", None)
2038
+ else {}
2039
+ ),
2040
+ )
2041
+
2042
+ self._api_client._verify_response(return_value)
2043
+ return return_value
2044
+
2045
+ async def _get_multimodal_dataset_operation(
2046
+ self,
2047
+ *,
2048
+ dataset_id: Optional[str] = None,
2049
+ operation_id: Optional[str] = None,
2050
+ config: Optional[types.GetMultimodalDatasetOperationConfigOrDict] = None,
2051
+ ) -> types.MultimodalDatasetOperation:
2052
+ """
2053
+ Gets the operation from creating a multimodal dataset.
2054
+ """
2055
+
2056
+ parameter_model = types._GetMultimodalDatasetOperationParameters(
2057
+ dataset_id=dataset_id,
2058
+ operation_id=operation_id,
2059
+ config=config,
2060
+ )
2061
+
2062
+ request_url_dict: Optional[dict[str, str]]
2063
+ if not self._api_client.vertexai:
2064
+ raise ValueError(
2065
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
2066
+ )
2067
+ else:
2068
+ request_dict = _GetMultimodalDatasetOperationParameters_to_vertex(
2069
+ parameter_model
2070
+ )
2071
+ request_url_dict = request_dict.get("_url")
2072
+ if request_url_dict:
2073
+ path = "datasets/{dataset_id}/operations/{operation_id}".format_map(
2074
+ request_url_dict
2075
+ )
2076
+ else:
2077
+ path = "datasets/{dataset_id}/operations/{operation_id}"
2078
+
2079
+ query_params = request_dict.get("_query")
2080
+ if query_params:
2081
+ path = f"{path}?{urlencode(query_params)}"
2082
+ # TODO: remove the hack that pops config.
2083
+ request_dict.pop("config", None)
2084
+
2085
+ http_options: Optional[types.HttpOptions] = None
2086
+ if (
2087
+ parameter_model.config is not None
2088
+ and parameter_model.config.http_options is not None
2089
+ ):
2090
+ http_options = parameter_model.config.http_options
2091
+
2092
+ request_dict = _common.convert_to_dict(request_dict)
2093
+ request_dict = _common.encode_unserializable_types(request_dict)
2094
+
2095
+ response = await self._api_client.async_request(
2096
+ "get", path, request_dict, http_options
2097
+ )
2098
+
2099
+ response_dict = {} if not response.body else json.loads(response.body)
2100
+
2101
+ return_value = types.MultimodalDatasetOperation._from_response(
2102
+ response=response_dict,
2103
+ kwargs=(
2104
+ {
2105
+ "config": {
2106
+ "response_schema": getattr(
2107
+ parameter_model.config, "response_schema", None
2108
+ ),
2109
+ "response_json_schema": getattr(
2110
+ parameter_model.config, "response_json_schema", None
2111
+ ),
2112
+ "include_all_fields": getattr(
2113
+ parameter_model.config, "include_all_fields", None
2114
+ ),
2115
+ }
2116
+ }
2117
+ if getattr(parameter_model, "config", None)
2118
+ else {}
2119
+ ),
2120
+ )
2121
+
2122
+ self._api_client._verify_response(return_value)
2123
+ return return_value
2124
+
2125
+ async def _list_multimodal_datasets(
2126
+ self, *, config: Optional[types.ListMultimodalDatasetsConfigOrDict] = None
2127
+ ) -> types.ListMultimodalDatasetsResponse:
2128
+ """
2129
+ Lists multimodal datasets.
2130
+ """
2131
+
2132
+ parameter_model = types._ListMultimodalDatasetsRequestParameters(
2133
+ config=config,
2134
+ )
2135
+
2136
+ request_url_dict: Optional[dict[str, str]]
2137
+ if not self._api_client.vertexai:
2138
+ raise ValueError(
2139
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
2140
+ )
2141
+ else:
2142
+ request_dict = _ListMultimodalDatasetsRequestParameters_to_vertex(
2143
+ parameter_model
2144
+ )
2145
+ request_url_dict = request_dict.get("_url")
2146
+ if request_url_dict:
2147
+ path = "datasets".format_map(request_url_dict)
2148
+ else:
2149
+ path = "datasets"
2150
+
2151
+ query_params = request_dict.get("_query")
2152
+ if query_params:
2153
+ path = f"{path}?{urlencode(query_params)}"
2154
+ # TODO: remove the hack that pops config.
2155
+ request_dict.pop("config", None)
2156
+
2157
+ http_options: Optional[types.HttpOptions] = None
2158
+ if (
2159
+ parameter_model.config is not None
2160
+ and parameter_model.config.http_options is not None
2161
+ ):
2162
+ http_options = parameter_model.config.http_options
2163
+
2164
+ request_dict = _common.convert_to_dict(request_dict)
2165
+ request_dict = _common.encode_unserializable_types(request_dict)
2166
+
2167
+ response = await self._api_client.async_request(
2168
+ "get", path, request_dict, http_options
2169
+ )
2170
+
2171
+ response_dict = {} if not response.body else json.loads(response.body)
2172
+
2173
+ return_value = types.ListMultimodalDatasetsResponse._from_response(
2174
+ response=response_dict,
2175
+ kwargs=(
2176
+ {
2177
+ "config": {
2178
+ "response_schema": getattr(
2179
+ parameter_model.config, "response_schema", None
2180
+ ),
2181
+ "response_json_schema": getattr(
2182
+ parameter_model.config, "response_json_schema", None
2183
+ ),
2184
+ "include_all_fields": getattr(
2185
+ parameter_model.config, "include_all_fields", None
2186
+ ),
2187
+ }
2188
+ }
2189
+ if getattr(parameter_model, "config", None)
2190
+ else {}
2191
+ ),
2192
+ )
2193
+
2194
+ self._api_client._verify_response(return_value)
2195
+ return return_value
2196
+
2197
+ async def _update_multimodal_dataset(
2198
+ self,
2199
+ *,
2200
+ name: Optional[str] = None,
2201
+ display_name: Optional[str] = None,
2202
+ metadata: Optional[types.SchemaTablesDatasetMetadataOrDict] = None,
2203
+ description: Optional[str] = None,
2204
+ encryption_spec: Optional[genai_types.EncryptionSpecOrDict] = None,
2205
+ config: Optional[types.VertexBaseConfigOrDict] = None,
2206
+ ) -> types.MultimodalDataset:
2207
+ """
2208
+ Updates a multimodal dataset resource.
2209
+ """
2210
+
2211
+ parameter_model = types._UpdateMultimodalDatasetParameters(
2212
+ name=name,
2213
+ display_name=display_name,
2214
+ metadata=metadata,
2215
+ description=description,
2216
+ encryption_spec=encryption_spec,
2217
+ config=config,
2218
+ )
2219
+
2220
+ request_url_dict: Optional[dict[str, str]]
2221
+ if not self._api_client.vertexai:
2222
+ raise ValueError(
2223
+ "This method is only supported in Gemini Enterprise Agent Platform mode, not in Gemini Developer API mode."
2224
+ )
2225
+ else:
2226
+ request_dict = _UpdateMultimodalDatasetParameters_to_vertex(parameter_model)
2227
+ request_url_dict = request_dict.get("_url")
2228
+ if request_url_dict:
2229
+ path = "{name}".format_map(request_url_dict)
2230
+ else:
2231
+ path = "{name}"
2232
+
2233
+ query_params = request_dict.get("_query")
2234
+ if query_params:
2235
+ path = f"{path}?{urlencode(query_params)}"
2236
+ # TODO: remove the hack that pops config.
2237
+ request_dict.pop("config", None)
2238
+
2239
+ http_options: Optional[types.HttpOptions] = None
2240
+ if (
2241
+ parameter_model.config is not None
2242
+ and parameter_model.config.http_options is not None
2243
+ ):
2244
+ http_options = parameter_model.config.http_options
2245
+
2246
+ request_dict = _common.convert_to_dict(request_dict)
2247
+ request_dict = _common.encode_unserializable_types(request_dict)
2248
+
2249
+ response = await self._api_client.async_request(
2250
+ "patch", path, request_dict, http_options
2251
+ )
2252
+
2253
+ response_dict = {} if not response.body else json.loads(response.body)
2254
+
2255
+ return_value = types.MultimodalDataset._from_response(
2256
+ response=response_dict,
2257
+ kwargs=(
2258
+ {
2259
+ "config": {
2260
+ "response_schema": getattr(
2261
+ parameter_model.config, "response_schema", None
2262
+ ),
2263
+ "response_json_schema": getattr(
2264
+ parameter_model.config, "response_json_schema", None
2265
+ ),
2266
+ "include_all_fields": getattr(
2267
+ parameter_model.config, "include_all_fields", None
2268
+ ),
2269
+ }
2270
+ }
2271
+ if getattr(parameter_model, "config", None)
2272
+ else {}
2273
+ ),
2274
+ )
2275
+
2276
+ self._api_client._verify_response(return_value)
2277
+ return return_value
2278
+
2279
+ async def _wait_for_operation(
2280
+ self,
2281
+ operation: types.MultimodalDatasetOperation,
2282
+ timeout_seconds: int,
2283
+ ) -> dict[str, Any]:
2284
+ """Waits for a multimodal dataset operation to complete.
2285
+
2286
+ Args:
2287
+ operation: The multimodal dataset operation to wait for.
2288
+ timeout_seconds: The maximum time in seconds to wait for the operation
2289
+ to complete.
2290
+
2291
+ Returns:
2292
+ A dict containing the operation response.
2293
+
2294
+ Raises:
2295
+ TimeoutError: If the operation does not complete within the timeout.
2296
+ ValueError: If the operation fails.
2297
+ """
2298
+ response_operation_name = operation.name
2299
+ if response_operation_name is None:
2300
+ raise ValueError("Dataset operation name is empty.")
2301
+ dataset_id = response_operation_name.split("/datasets/")[1].split("/")[0]
2302
+ operation_id = response_operation_name.split("/")[-1]
2303
+
2304
+ start_time = time.time()
2305
+ sleep_duration_seconds = 5
2306
+ wait_multiplier = 2
2307
+ max_wait_time_seconds = 60
2308
+
2309
+ while (time.time() - start_time) < timeout_seconds:
2310
+ operation = await self._get_multimodal_dataset_operation(
2311
+ dataset_id=dataset_id,
2312
+ operation_id=operation_id,
2313
+ )
2314
+ if operation.done:
2315
+ break
2316
+ await asyncio.sleep(sleep_duration_seconds)
2317
+ sleep_duration_seconds = min(
2318
+ sleep_duration_seconds * wait_multiplier, max_wait_time_seconds
2319
+ )
2320
+ else:
2321
+ raise TimeoutError(
2322
+ "The operation did not complete within the"
2323
+ f" specified timeout of {timeout_seconds} seconds."
2324
+ )
2325
+ if not operation or operation.response is None:
2326
+ logger.error(f"Error running the operation {operation.response}.")
2327
+ raise ValueError(f"Error running the operation {operation.response}.")
2328
+ if hasattr(operation, "error") and operation.error is not None:
2329
+ raise ValueError(f"Error running the operation {operation.error}")
2330
+ return operation.response
2331
+
2332
+ async def create_from_bigquery(
2333
+ self,
2334
+ *,
2335
+ bigquery_uri: Optional[str] = None,
2336
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
2337
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
2338
+ ) -> types.MultimodalDataset:
2339
+ """Creates a multimodal dataset from a BigQuery table.
2340
+
2341
+ Args:
2342
+ bigquery_uri:
2343
+ Optional. The BigQuery URI of the table to create the dataset from.
2344
+ e.g. "bq://project.dataset.table". If both `bigquery_uri` and
2345
+ `multimodal_dataset` are provided, and `multimodal_dataset` also
2346
+ contains a BigQuery URI, the `bigquery_uri` parameter takes precedence.
2347
+ multimodal_dataset:
2348
+ Optional. A representation of a multimodal dataset. If `bigquery_uri`
2349
+ is set, `multimodal_dataset` can still be used to set other metadata
2350
+ fields. If both `bigquery_uri` and `multimodal_dataset` are provided,
2351
+ and `multimodal_dataset` also contains a BigQuery URI, the
2352
+ `bigquery_uri` parameter takes precedence.
2353
+ config:
2354
+ Optional. A configuration for creating the multimodal dataset. If not
2355
+ provided, the default configuration will be used.
2356
+
2357
+ Returns:
2358
+ A types.MultimodalDataset object representing a multimodal dataset.
2359
+ """
2360
+ if not bigquery_uri and not multimodal_dataset:
2361
+ raise ValueError(
2362
+ "At least one of `bigquery_uri` or `multimodal_dataset` must be"
2363
+ " provided."
2364
+ )
2365
+
2366
+ if multimodal_dataset is None:
2367
+ multimodal_dataset = types.MultimodalDataset()
2368
+ elif isinstance(multimodal_dataset, dict):
2369
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
2370
+
2371
+ if bigquery_uri:
2372
+ multimodal_dataset = multimodal_dataset.model_copy(deep=True)
2373
+ multimodal_dataset.set_bigquery_uri(bigquery_uri)
2374
+
2375
+ _datasets_utils.validate_multimodal_dataset_bigquery_uri(multimodal_dataset)
2376
+
2377
+ if isinstance(config, dict):
2378
+ config = types.CreateMultimodalDatasetConfig(**config)
2379
+ elif not config:
2380
+ config = types.CreateMultimodalDatasetConfig()
2381
+
2382
+ display_name = (
2383
+ multimodal_dataset.display_name
2384
+ if multimodal_dataset.display_name is not None
2385
+ else _datasets_utils.generate_multimodal_dataset_display_name()
2386
+ )
2387
+ multimodal_dataset_operation = await self._create_multimodal_dataset(
2388
+ config=config,
2389
+ display_name=display_name,
2390
+ metadata_schema_uri=_datasets_utils.METADATA_SCHEMA_URI,
2391
+ metadata=multimodal_dataset.metadata,
2392
+ )
2393
+ response = await self._wait_for_operation(
2394
+ operation=multimodal_dataset_operation,
2395
+ timeout_seconds=config.timeout,
2396
+ )
2397
+ return _datasets_utils.create_from_response(
2398
+ types.MultimodalDataset, response, config
2399
+ )
2400
+
2401
+ async def create_from_pandas(
2402
+ self,
2403
+ *,
2404
+ dataframe: pd.DataFrame,
2405
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
2406
+ target_table_id: Optional[str] = None,
2407
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
2408
+ ) -> types.MultimodalDataset:
2409
+ """Creates a multimodal dataset from a pandas dataframe.
2410
+
2411
+ Args:
2412
+ dataframe (pandas.DataFrame):
2413
+ The pandas dataframe to be used for the created dataset.
2414
+ multimodal_dataset:
2415
+ Optional. A representation of a multimodal dataset.
2416
+ target_table_id (str):
2417
+ Optional. The BigQuery table id where the dataframe will be
2418
+ uploaded. The table id can be in the format of "dataset.table"
2419
+ or "project.dataset.table". Note that the BigQuery
2420
+ dataset must already exist and be in the same location as the
2421
+ multimodal dataset. If not provided, a generated table id will
2422
+ be created in the `vertex_datasets` dataset (e.g.
2423
+ `project.vertex_datasets_us_central1.multimodal_dataset_4cbf7ffd`).
2424
+ config:
2425
+ Optional. A configuration for creating the multimodal dataset. If not
2426
+ provided, the default configuration will be used.
2427
+
2428
+ Returns:
2429
+ dataset (MultimodalDataset):
2430
+ The created multimodal dataset.
2431
+ """
2432
+ if isinstance(multimodal_dataset, dict):
2433
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
2434
+ elif not multimodal_dataset:
2435
+ multimodal_dataset = types.MultimodalDataset()
2436
+
2437
+ bigframes = _datasets_utils._try_import_bigframes()
2438
+ project = self._api_client.project
2439
+ location = self._api_client.location
2440
+ credentials = self._api_client._credentials
2441
+
2442
+ session_options = bigframes.BigQueryOptions(
2443
+ credentials=credentials,
2444
+ project=project,
2445
+ location=location,
2446
+ )
2447
+ with bigframes.connect(session_options) as session:
2448
+ return await self.create_from_bigframes(
2449
+ dataframe=session.read_pandas(dataframe),
2450
+ multimodal_dataset=multimodal_dataset,
2451
+ target_table_id=target_table_id,
2452
+ config=config,
2453
+ )
2454
+
2455
+ async def create_from_bigframes(
2456
+ self,
2457
+ *,
2458
+ dataframe: "bigframes.pandas.DataFrame", # type: ignore # noqa: F821
2459
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
2460
+ target_table_id: Optional[str] = None,
2461
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
2462
+ ) -> types.MultimodalDataset:
2463
+ """Creates a multimodal dataset from a bigframes dataframe.
2464
+
2465
+ Args:
2466
+ dataframe (bigframes.pandas.DataFrame):
2467
+ The BigFrames dataframe that will be used for the created
2468
+ dataset.
2469
+ multimodal_dataset:
2470
+ Optional. A representation of a multimodal dataset.
2471
+ target_table_id (str):
2472
+ Optional. The BigQuery table id where the dataframe will be
2473
+ uploaded. The table id can be in the format of "dataset.table"
2474
+ or "project.dataset.table". Note that the BigQuery
2475
+ dataset must already exist and be in the same location as the
2476
+ multimodal dataset. If not provided, a generated table id will
2477
+ be created in the `vertex_datasets` dataset (e.g.
2478
+ `project.vertex_datasets_us_central1.multimodal_dataset_4cbf7ffd`).
2479
+ config:
2480
+ Optional. A configuration for creating the multimodal dataset. If not
2481
+ provided, the default configuration will be used.
2482
+
2483
+ Returns:
2484
+ dataset (MultimodalDataset):
2485
+ The created multimodal dataset.
2486
+ """
2487
+ if isinstance(multimodal_dataset, dict):
2488
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
2489
+ elif not multimodal_dataset:
2490
+ multimodal_dataset = types.MultimodalDataset()
2491
+
2492
+ bigquery = _datasets_utils._try_import_bigquery()
2493
+ project = self._api_client.project
2494
+ location = self._api_client.location
2495
+ credentials = self._api_client._credentials
2496
+
2497
+ if target_table_id:
2498
+ target_table_id = (
2499
+ await _datasets_utils._normalize_and_validate_table_id_async(
2500
+ table_id=target_table_id,
2501
+ project=project,
2502
+ location=location,
2503
+ credentials=credentials,
2504
+ )
2505
+ )
2506
+ else:
2507
+ dataset_id = await _datasets_utils._create_default_bigquery_dataset_if_not_exists_async(
2508
+ project=project, location=location, credentials=credentials
2509
+ )
2510
+ target_table_id = _datasets_utils._generate_target_table_id(dataset_id)
2511
+
2512
+ client = bigquery.Client(project=project, credentials=credentials)
2513
+ await _datasets_utils.save_dataframe_to_bigquery_async(
2514
+ dataframe,
2515
+ target_table_id,
2516
+ client,
2517
+ )
2518
+
2519
+ multimodal_dataset = multimodal_dataset.model_copy(deep=True)
2520
+ multimodal_dataset.set_bigquery_uri(f"bq://{target_table_id}")
2521
+ return await self.create_from_bigquery(
2522
+ multimodal_dataset=multimodal_dataset, config=config
2523
+ )
2524
+
2525
+ async def create_from_gemini_request_jsonl(
2526
+ self,
2527
+ *,
2528
+ gcs_uri: str,
2529
+ multimodal_dataset: Optional[types.MultimodalDatasetOrDict] = None,
2530
+ target_table_id: Optional[str] = None,
2531
+ config: Optional[types.CreateMultimodalDatasetConfigOrDict] = None,
2532
+ ) -> types.MultimodalDataset:
2533
+ """Creates a multimodal dataset from a JSONL file stored on GCS.
2534
+
2535
+ The JSONL file should contain instances of Gemini
2536
+ `GenerateContentRequest` on each line. The data will be stored in a
2537
+ BigQuery table with a single column called "requests". The
2538
+ request_column_name in the dataset metadata will be set to "requests".
2539
+
2540
+ Args:
2541
+ gcs_uri (str):
2542
+ The Google Cloud Storage URI of the JSONL file to import.
2543
+ For example, 'gs://my-bucket/path/to/data.jsonl'
2544
+ multimodal_dataset:
2545
+ Optional. A representation of a multimodal dataset.
2546
+ target_table_id (str):
2547
+ Optional. The BigQuery table id where the dataframe will be
2548
+ uploaded. The table id can be in the format of "dataset.table"
2549
+ or "project.dataset.table". Note that the BigQuery
2550
+ dataset must already exist and be in the same location as the
2551
+ multimodal dataset. If not provided, a generated table id will
2552
+ be created in the `vertex_datasets` dataset (e.g.
2553
+ `project.vertex_datasets_us_central1.multimodal_dataset_4cbf7ffd`).
2554
+ config:
2555
+ Optional. A configuration for creating the multimodal dataset. If not
2556
+ provided, the default configuration will be used.
2557
+
2558
+ Returns:
2559
+ The created multimodal dataset.
2560
+ """
2561
+ bigquery = _datasets_utils._try_import_bigquery()
2562
+
2563
+ if isinstance(multimodal_dataset, dict):
2564
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
2565
+ elif not multimodal_dataset:
2566
+ multimodal_dataset = types.MultimodalDataset()
2567
+
2568
+ if not gcs_uri.startswith("gs://"):
2569
+ raise ValueError(
2570
+ "Invalid GCS URI format. Expected: gs://bucket-name/object-path"
2571
+ )
2572
+
2573
+ project = self._api_client.project
2574
+ location = self._api_client.location
2575
+ credentials = self._api_client._credentials
2576
+
2577
+ if target_table_id:
2578
+ target_table_id = (
2579
+ await _datasets_utils._normalize_and_validate_table_id_async(
2580
+ table_id=target_table_id,
2581
+ project=project,
2582
+ location=location,
2583
+ credentials=credentials,
2584
+ )
2585
+ )
2586
+ else:
2587
+ dataset_id = await _datasets_utils._create_default_bigquery_dataset_if_not_exists_async(
2588
+ project=project, location=location, credentials=credentials
2589
+ )
2590
+ target_table_id = _datasets_utils._generate_target_table_id(dataset_id)
2591
+
2592
+ request_column_name = "requests"
2593
+
2594
+ # Setup LoadJobConfig to load the JSONL file as a CSV directly from GCS.
2595
+ # We use an unused character (unit separator \x1f) as the field delimiter
2596
+ # and an empty string as the quote character. This forces BigQuery to
2597
+ # treat each line (a valid JSON string) as a single CSV row.
2598
+ job_config = bigquery.LoadJobConfig(
2599
+ source_format=bigquery.SourceFormat.CSV,
2600
+ field_delimiter="\x1f",
2601
+ quote_character="",
2602
+ schema=[bigquery.SchemaField(request_column_name, "JSON")],
2603
+ write_disposition=bigquery.WriteDisposition.WRITE_TRUNCATE,
2604
+ )
2605
+
2606
+ client = bigquery.Client(project=project, credentials=credentials)
2607
+ load_job = client.load_table_from_uri(
2608
+ gcs_uri,
2609
+ target_table_id,
2610
+ job_config=job_config,
2611
+ )
2612
+ await asyncio.to_thread(load_job.result)
2613
+
2614
+ multimodal_dataset = multimodal_dataset.model_copy(deep=True)
2615
+ metadata = multimodal_dataset.metadata or types.SchemaTablesDatasetMetadata()
2616
+
2617
+ read_config = (
2618
+ metadata.gemini_request_read_config or types.GeminiRequestReadConfig()
2619
+ )
2620
+ read_config.assembled_request_column_name = request_column_name
2621
+ metadata.gemini_request_read_config = read_config
2622
+
2623
+ multimodal_dataset.metadata = metadata
2624
+ multimodal_dataset.set_bigquery_uri(f"bq://{target_table_id}")
2625
+
2626
+ return await self.create_from_bigquery(
2627
+ multimodal_dataset=multimodal_dataset, config=config
2628
+ )
2629
+
2630
+ async def update_multimodal_dataset(
2631
+ self,
2632
+ *,
2633
+ multimodal_dataset: types.MultimodalDatasetOrDict,
2634
+ config: Optional[types.VertexBaseConfigOrDict] = None,
2635
+ ) -> types.MultimodalDataset:
2636
+ """Updates a multimodal dataset.
2637
+
2638
+ Args:
2639
+ multimodal_dataset:
2640
+ Required. A representation of a multimodal dataset.
2641
+ config:
2642
+ Optional. A configuration for updating the multimodal dataset. If not
2643
+ provided, the default configuration will be used.
2644
+
2645
+ Returns:
2646
+ A types.MultimodalDataset object representing the updated multimodal
2647
+ dataset.
2648
+ """
2649
+ if isinstance(multimodal_dataset, dict):
2650
+ multimodal_dataset = types.MultimodalDataset(**multimodal_dataset)
2651
+ _datasets_utils.validate_multimodal_dataset_bigquery_uri(multimodal_dataset)
2652
+
2653
+ if isinstance(config, dict):
2654
+ config = types.VertexBaseConfig(**config)
2655
+ elif not config:
2656
+ config = types.VertexBaseConfig()
2657
+
2658
+ return await self._update_multimodal_dataset(
2659
+ config=config,
2660
+ name=multimodal_dataset.name,
2661
+ display_name=multimodal_dataset.display_name,
2662
+ description=multimodal_dataset.description,
2663
+ metadata=multimodal_dataset.metadata,
2664
+ )
2665
+
2666
+ async def get_multimodal_dataset(
2667
+ self,
2668
+ *,
2669
+ name: str,
2670
+ config: Optional[types.VertexBaseConfigOrDict] = None,
2671
+ ) -> types.MultimodalDataset:
2672
+ """Gets a multimodal dataset.
2673
+
2674
+ Args:
2675
+ name:
2676
+ Required. A fully-qualified resource name or ID of the dataset.
2677
+ Example: "projects/.../locations/.../datasets/123" or "123".
2678
+ config:
2679
+ Optional. A configuration for getting the multimodal dataset. If not
2680
+ provided, the default configuration will be used.
2681
+
2682
+ Returns:
2683
+ A types.MultimodalDataset object representing the retrieved multimodal
2684
+ dataset.
2685
+ """
2686
+ if isinstance(config, dict):
2687
+ config = types.VertexBaseConfig(**config)
2688
+ elif not config:
2689
+ config = types.VertexBaseConfig()
2690
+
2691
+ name = _datasets_utils.resolve_dataset_name(
2692
+ name, self._api_client.project, self._api_client.location
2693
+ )
2694
+
2695
+ return await self._get_multimodal_dataset(config=config, name=name)
2696
+
2697
+ async def delete_multimodal_dataset(
2698
+ self,
2699
+ *,
2700
+ name: str,
2701
+ config: Optional[types.VertexBaseConfigOrDict] = None,
2702
+ ) -> types.MultimodalDatasetOperation:
2703
+ """Deletes a multimodal dataset.
2704
+
2705
+ Args:
2706
+ name:
2707
+ Required. A fully-qualified resource name or ID of the dataset.
2708
+ Example: "projects/.../locations/.../datasets/123" or "123".
2709
+ config:
2710
+ Optional. A configuration for deleting the multimodal dataset. If not
2711
+ provided, the default configuration will be used.
2712
+
2713
+ Returns:
2714
+ A types.MultimodalDatasetOperation object representing the delete
2715
+ multimodal dataset operation.
2716
+ """
2717
+ if isinstance(config, dict):
2718
+ config = types.VertexBaseConfig(**config)
2719
+ elif not config:
2720
+ config = types.VertexBaseConfig()
2721
+
2722
+ name = _datasets_utils.resolve_dataset_name(
2723
+ name, self._api_client.project, self._api_client.location
2724
+ )
2725
+
2726
+ return await self._delete_multimodal_dataset(config=config, name=name)
2727
+
2728
+ async def assemble(
2729
+ self,
2730
+ *,
2731
+ name: str,
2732
+ gemini_request_read_config: Optional[
2733
+ types.GeminiRequestReadConfigOrDict
2734
+ ] = None,
2735
+ load_dataframe: bool = False,
2736
+ config: Optional[types.AssembleDatasetConfigOrDict] = None,
2737
+ ) -> tuple[str, Optional["bigframes.pandas.DataFrame"]]: # type: ignore # noqa: F821
2738
+ """Assemble the dataset into a BigQuery table.
2739
+
2740
+ Waits for the assemble operation to complete before returning.
2741
+
2742
+ Args:
2743
+ name:
2744
+ Required. A fully-qualified resource name or ID of the dataset.
2745
+ Example: "projects/.../locations/.../datasets/123" or "123".
2746
+ gemini_request_read_config:
2747
+ Optional. The read config to use to assemble the dataset. If
2748
+ not provided, the read config attached to the dataset will be
2749
+ used.
2750
+ load_dataframe:
2751
+ Optional. Whether to load the assembled BigQuery table into a
2752
+ BigFrames DataFrame and return it. If False, the returned
2753
+ DataFrame is None, no BigQuery read is performed, and `bigframes`
2754
+ is not required. Defaults to False.
2755
+ config:
2756
+ Optional. A configuration for assembling the dataset. If not
2757
+ provided, the default configuration will be used.
2758
+
2759
+ Returns:
2760
+ A tuple `(table_id, dataframe)`, where `table_id` is the BigQuery
2761
+ table id of the assembled dataset (without the `bq://` prefix) and
2762
+ `dataframe` is the assembled table loaded as a BigFrames DataFrame.
2763
+ `dataframe` is None if `load_dataframe` is False.
2764
+ """
2765
+ if isinstance(config, dict):
2766
+ config = types.AssembleDatasetConfig(**config)
2767
+ elif not config:
2768
+ config = types.AssembleDatasetConfig()
2769
+
2770
+ name = _datasets_utils.resolve_dataset_name(
2771
+ name, self._api_client.project, self._api_client.location
2772
+ )
2773
+
2774
+ operation = await self._assemble_multimodal_dataset(
2775
+ name=name,
2776
+ gemini_request_read_config=gemini_request_read_config,
2777
+ config=config,
2778
+ )
2779
+ response = await self._wait_for_operation(
2780
+ operation=operation,
2781
+ timeout_seconds=config.timeout,
2782
+ )
2783
+ bigquery_uri = response["bigqueryDestination"]
2784
+ table_id = bigquery_uri.removeprefix("bq://")
2785
+ dataframe = None
2786
+ if load_dataframe:
2787
+ dataframe = await _datasets_utils.load_dataframe_from_bigquery_async(
2788
+ bigquery_uri=bigquery_uri,
2789
+ project=self._api_client.project,
2790
+ location=self._api_client.location,
2791
+ credentials=self._api_client._credentials,
2792
+ )
2793
+ return (table_id, dataframe)
2794
+
2795
+ async def assess_tuning_resources(
2796
+ self,
2797
+ *,
2798
+ dataset_name: str,
2799
+ model_name: str,
2800
+ gemini_request_read_config: Optional[
2801
+ types.GeminiRequestReadConfigOrDict
2802
+ ] = None,
2803
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
2804
+ ) -> types.TuningResourceUsageAssessmentResult:
2805
+ """Assess the tuning resources required for a given model.
2806
+
2807
+ Args:
2808
+ dataset_name:
2809
+ Required. A fully-qualified resource name or ID of the dataset.
2810
+ Example: "projects/.../locations/.../datasets/123" or "123".
2811
+ model_name:
2812
+ Required. The name of the model to assess the tuning resources
2813
+ for.
2814
+ gemini_request_read_config:
2815
+ Optional. The read config used to assemble the dataset
2816
+ before assessing the tuning resources. If not provided, the
2817
+ read config attached to the dataset will be used. Required
2818
+ if no read config is attached to the dataset.
2819
+ config:
2820
+ Optional. A configuration for assessing the tuning resources. If not
2821
+ provided, the default configuration will be used.
2822
+
2823
+ Returns:
2824
+ A types.TuningResourceUsageAssessmentResult object representing the
2825
+ tuning resource usage assessment result.
2826
+ """
2827
+ if isinstance(config, dict):
2828
+ config = types.AssessDatasetConfig(**config)
2829
+ elif not config:
2830
+ config = types.AssessDatasetConfig()
2831
+
2832
+ dataset_name = _datasets_utils.resolve_dataset_name(
2833
+ dataset_name, self._api_client.project, self._api_client.location
2834
+ )
2835
+
2836
+ operation = await self._assess_multimodal_dataset(
2837
+ name=dataset_name,
2838
+ tuning_resource_usage_assessment_config=types.TuningResourceUsageAssessmentConfig(
2839
+ model_name=model_name
2840
+ ),
2841
+ gemini_request_read_config=gemini_request_read_config,
2842
+ config=config,
2843
+ )
2844
+ response = await self._wait_for_operation(
2845
+ operation=operation,
2846
+ timeout_seconds=config.timeout,
2847
+ )
2848
+ return _datasets_utils.create_from_response(
2849
+ types.TuningResourceUsageAssessmentResult,
2850
+ response["tuningResourceUsageAssessmentResult"],
2851
+ config,
2852
+ )
2853
+
2854
+ async def assess_tuning_validity(
2855
+ self,
2856
+ *,
2857
+ dataset_name: str,
2858
+ model_name: str,
2859
+ dataset_usage: str,
2860
+ gemini_request_read_config: Optional[
2861
+ types.GeminiRequestReadConfigOrDict
2862
+ ] = None,
2863
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
2864
+ ) -> types.TuningValidationAssessmentResult:
2865
+ """Assess if the assembled dataset is valid in terms of tuning a given
2866
+ model.
2867
+
2868
+ Args:
2869
+ dataset_name:
2870
+ Required. A fully-qualified resource name or ID of the dataset.
2871
+ Example: "projects/.../locations/.../datasets/123" or "123".
2872
+ model_name:
2873
+ Required. The name of the model to assess the tuning validity
2874
+ for.
2875
+ dataset_usage:
2876
+ Required. The dataset usage to assess the tuning validity for.
2877
+ Must be one of the following: SFT_TRAINING, SFT_VALIDATION.
2878
+ gemini_request_read_config:
2879
+ Optional. The read config used to assemble the dataset
2880
+ before assessing the tuning validity. If not provided, the
2881
+ read config attached to the dataset will be used. Required
2882
+ if no read config is attached to the dataset.
2883
+ config:
2884
+ Optional. A configuration for assessing the tuning validity. If not
2885
+ provided, the default configuration will be used.
2886
+
2887
+ Returns:
2888
+ A dict containing the tuning validity assessment result. The dict
2889
+ contains the following keys:
2890
+ - errors: A list of errors that occurred during the tuning validity
2891
+ assessment.
2892
+ """
2893
+ if isinstance(config, dict):
2894
+ config = types.AssessDatasetConfig(**config)
2895
+ elif not config:
2896
+ config = types.AssessDatasetConfig()
2897
+
2898
+ dataset_name = _datasets_utils.resolve_dataset_name(
2899
+ dataset_name, self._api_client.project, self._api_client.location
2900
+ )
2901
+
2902
+ operation = await self._assess_multimodal_dataset(
2903
+ name=dataset_name,
2904
+ tuning_validation_assessment_config=types.TuningValidationAssessmentConfig(
2905
+ model_name=model_name,
2906
+ dataset_usage=dataset_usage,
2907
+ ),
2908
+ gemini_request_read_config=gemini_request_read_config,
2909
+ config=config,
2910
+ )
2911
+ response = await self._wait_for_operation(
2912
+ operation=operation,
2913
+ timeout_seconds=config.timeout,
2914
+ )
2915
+ return _datasets_utils.create_from_response(
2916
+ types.TuningValidationAssessmentResult,
2917
+ response["tuningValidationAssessmentResult"],
2918
+ config,
2919
+ )
2920
+
2921
+ async def assess_batch_prediction_resources(
2922
+ self,
2923
+ *,
2924
+ dataset_name: str,
2925
+ model_name: str,
2926
+ gemini_request_read_config: Optional[
2927
+ types.GeminiRequestReadConfigOrDict
2928
+ ] = None,
2929
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
2930
+ ) -> types.BatchPredictionResourceUsageAssessmentResult:
2931
+ """Assess the batch prediction resources required for a given model.
2932
+
2933
+ Args:
2934
+ dataset_name:
2935
+ Required. A fully-qualified resource name or ID of the dataset.
2936
+ Example: "projects/.../locations/.../datasets/123" or "123".
2937
+ model_name:
2938
+ Required. The name of the model to assess the batch prediction
2939
+ resources.
2940
+ gemini_request_read_config:
2941
+ Optional. The read config used to assemble the dataset
2942
+ before assessing the batch prediction resources. If not provided,
2943
+ the read config attached to the dataset will be used. Required
2944
+ if no read config is attached to the dataset.
2945
+ config:
2946
+ Optional. A configuration for assessing the batch prediction
2947
+ resources. If not provided, the default configuration will be
2948
+ used.
2949
+
2950
+ Returns:
2951
+ A types.BatchPredictionResourceUsageAssessmentResult object
2952
+ representing the batch prediction resource usage assessment result.
2953
+ It contains the following keys:
2954
+ - token_count: The number of tokens in the dataset.
2955
+ - audio_token_count: The number of audio tokens in the dataset.
2956
+
2957
+ """
2958
+ if isinstance(config, dict):
2959
+ config = types.AssessDatasetConfig(**config)
2960
+ elif not config:
2961
+ config = types.AssessDatasetConfig()
2962
+
2963
+ dataset_name = _datasets_utils.resolve_dataset_name(
2964
+ dataset_name, self._api_client.project, self._api_client.location
2965
+ )
2966
+
2967
+ operation = await self._assess_multimodal_dataset(
2968
+ name=dataset_name,
2969
+ batch_prediction_resource_usage_assessment_config=types.BatchPredictionResourceUsageAssessmentConfig(
2970
+ model_name=model_name,
2971
+ ),
2972
+ gemini_request_read_config=gemini_request_read_config,
2973
+ config=config,
2974
+ )
2975
+ response = await self._wait_for_operation(
2976
+ operation=operation,
2977
+ timeout_seconds=config.timeout,
2978
+ )
2979
+ result = response["batchPredictionResourceUsageAssessmentResult"]
2980
+ return _datasets_utils.create_from_response(
2981
+ types.BatchPredictionResourceUsageAssessmentResult, result, config
2982
+ )
2983
+
2984
+ async def assess_batch_prediction_validity(
2985
+ self,
2986
+ *,
2987
+ dataset_name: str,
2988
+ model_name: str,
2989
+ gemini_request_read_config: Optional[
2990
+ types.GeminiRequestReadConfigOrDict
2991
+ ] = None,
2992
+ config: Optional[types.AssessDatasetConfigOrDict] = None,
2993
+ ) -> types.BatchPredictionValidationAssessmentResult:
2994
+ """Assess if the assembled dataset is valid in terms of batch prediction
2995
+ for a given model. Raises an error if the dataset is invalid, otherwise
2996
+ returns None.
2997
+
2998
+ Args:
2999
+ dataset_name:
3000
+ Required. A fully-qualified resource name or ID of the dataset.
3001
+ Example: "projects/.../locations/.../datasets/123" or "123".
3002
+ model_name:
3003
+ Required. The name of the model to assess the batch prediction
3004
+ validity for.
3005
+ gemini_request_read_config:
3006
+ Optional. The read config used to assemble the dataset
3007
+ before assessing the batch prediction validity. If not provided, the
3008
+ read config attached to the dataset will be used. Required
3009
+ if no read config is attached to the dataset.
3010
+ config:
3011
+ Optional. A configuration for assessing the batch prediction validity.
3012
+ If not provided, the default configuration will be used.
3013
+
3014
+ Returns:
3015
+ A types.BatchPredictionValidationAssessmentResult object representing
3016
+ the batch prediction validity assessment result.
3017
+ It contains the following keys:
3018
+ - errors: A list of errors that occurred during the batch prediction
3019
+ validity assessment.
3020
+ """
3021
+ if isinstance(config, dict):
3022
+ config = types.AssessDatasetConfig(**config)
3023
+ elif not config:
3024
+ config = types.AssessDatasetConfig()
3025
+
3026
+ dataset_name = _datasets_utils.resolve_dataset_name(
3027
+ dataset_name, self._api_client.project, self._api_client.location
3028
+ )
3029
+
3030
+ operation = await self._assess_multimodal_dataset(
3031
+ name=dataset_name,
3032
+ batch_prediction_validation_assessment_config=types.BatchPredictionValidationAssessmentConfig(
3033
+ model_name=model_name,
3034
+ ),
3035
+ gemini_request_read_config=gemini_request_read_config,
3036
+ config=config,
3037
+ )
3038
+ response = await self._wait_for_operation(
3039
+ operation=operation,
3040
+ timeout_seconds=config.timeout,
3041
+ )
3042
+ result = response["batchPredictionValidationAssessmentResult"]
3043
+ return _datasets_utils.create_from_response(
3044
+ types.BatchPredictionValidationAssessmentResult, result, config
3045
+ )