google-genai 1.50.0__py3-none-any.whl → 1.51.0__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.
@@ -628,15 +628,15 @@ class BaseApiClient:
628
628
  )
629
629
  self.api_key = None
630
630
 
631
- if not self.location and not self.api_key:
632
- self.location = 'global'
633
-
634
631
  self.custom_base_url = (
635
632
  validated_http_options.base_url
636
633
  if validated_http_options.base_url
637
634
  else None
638
635
  )
639
636
 
637
+ if not self.location and not self.api_key and not self.custom_base_url:
638
+ self.location = 'global'
639
+
640
640
  # Skip fetching project from ADC if base url is provided in http options.
641
641
  if (
642
642
  not self.project
@@ -1836,12 +1836,17 @@ class BaseApiClient:
1836
1836
 
1837
1837
  def close(self) -> None:
1838
1838
  """Closes the API client."""
1839
- self._httpx_client.close()
1839
+ # Let users close the custom client explicitly by themselves. Otherwise,
1840
+ # close the client when the object is garbage collected.
1841
+ if not self._http_options.httpx_client:
1842
+ self._httpx_client.close()
1840
1843
 
1841
1844
  async def aclose(self) -> None:
1842
1845
  """Closes the API async client."""
1843
-
1844
- await self._async_httpx_client.aclose()
1846
+ # Let users close the custom client explicitly by themselves. Otherwise,
1847
+ # close the client when the object is garbage collected.
1848
+ if not self._http_options.httpx_async_client:
1849
+ await self._async_httpx_client.aclose()
1845
1850
  if self._aiohttp_session:
1846
1851
  await self._aiohttp_session.close()
1847
1852
 
@@ -1853,17 +1858,12 @@ class BaseApiClient:
1853
1858
  """
1854
1859
 
1855
1860
  try:
1856
- # Let users close the custom client explicitly by themselves. Otherwise,
1857
- # close the client when the object is garbage collected.
1858
1861
  if not self._http_options.httpx_client:
1859
1862
  self.close()
1860
1863
  except Exception: # pylint: disable=broad-except
1861
1864
  pass
1862
1865
 
1863
1866
  try:
1864
- # Let users close the custom client explicitly by themselves. Otherwise,
1865
- # close the client when the object is garbage collected.
1866
- if not self._http_options.httpx_async_client:
1867
- asyncio.get_running_loop().create_task(self.aclose())
1867
+ asyncio.get_running_loop().create_task(self.aclose())
1868
1868
  except Exception: # pylint: disable=broad-except
1869
1869
  pass
google/genai/_common.py CHANGED
@@ -561,6 +561,43 @@ class BaseModel(pydantic.BaseModel):
561
561
  ignored_types=(typing.TypeVar,),
562
562
  )
563
563
 
564
+ @pydantic.model_validator(mode='before')
565
+ @classmethod
566
+ def _check_field_type_mismatches(cls, data: Any) -> Any:
567
+ """Check for type mismatches and warn before Pydantic processes the data."""
568
+ # Handle both dict and Pydantic model inputs
569
+ if not isinstance(data, (dict, pydantic.BaseModel)):
570
+ return data
571
+
572
+ for field_name, field_info in cls.model_fields.items():
573
+ if isinstance(data, dict):
574
+ value = data.get(field_name)
575
+ else:
576
+ value = getattr(data, field_name, None)
577
+
578
+ if value is None:
579
+ continue
580
+
581
+ expected_type = field_info.annotation
582
+ origin = get_origin(expected_type)
583
+
584
+ if origin is Union:
585
+ args = get_args(expected_type)
586
+ non_none_types = [arg for arg in args if arg is not type(None)]
587
+ if len(non_none_types) == 1:
588
+ expected_type = non_none_types[0]
589
+
590
+ if (isinstance(expected_type, type) and
591
+ issubclass(expected_type, pydantic.BaseModel) and
592
+ isinstance(value, pydantic.BaseModel) and
593
+ not isinstance(value, expected_type)):
594
+ logger.warning(
595
+ f"Type mismatch in {cls.__name__}.{field_name}: "
596
+ f"expected {expected_type.__name__}, got {type(value).__name__}"
597
+ )
598
+
599
+ return data
600
+
564
601
  def __repr__(self) -> str:
565
602
  try:
566
603
  return _pretty_repr(self)
@@ -489,6 +489,31 @@ def get_max_remote_calls_afc(
489
489
  return int(config_model.automatic_function_calling.maximum_remote_calls)
490
490
 
491
491
 
492
+ def raise_error_for_afc_incompatible_config(config: Optional[types.GenerateContentConfig]
493
+ ) -> None:
494
+ """Raises an error if the config is not compatible with AFC."""
495
+ if (
496
+ not config
497
+ or not config.tool_config
498
+ or not config.tool_config.function_calling_config
499
+ ):
500
+ return
501
+ afc_config = config.automatic_function_calling
502
+ disable_afc_config = afc_config.disable if afc_config else False
503
+ stream_function_call = (
504
+ config.tool_config.function_calling_config.stream_function_call_arguments
505
+ )
506
+
507
+ if stream_function_call and not disable_afc_config:
508
+ raise ValueError(
509
+ 'Running in streaming mode with stream_function_call_arguments'
510
+ ' enabled, this feature is not compatible with automatic function'
511
+ ' calling (AFC). Please set config.automatic_function_calling.disable'
512
+ ' to True to disable AFC or leave config.tool_config.'
513
+ ' function_calling_config.stream_function_call_arguments to be empty'
514
+ ' or set to False to disable streaming function call arguments.'
515
+ )
516
+
492
517
  def should_append_afc_history(
493
518
  config: Optional[types.GenerateContentConfigOrDict] = None,
494
519
  ) -> bool:
@@ -78,6 +78,29 @@ def _FileData_to_mldev(
78
78
  return to_object
79
79
 
80
80
 
81
+ def _FunctionCall_to_mldev(
82
+ from_object: Union[dict[str, Any], object],
83
+ parent_object: Optional[dict[str, Any]] = None,
84
+ ) -> dict[str, Any]:
85
+ to_object: dict[str, Any] = {}
86
+ if getv(from_object, ['id']) is not None:
87
+ setv(to_object, ['id'], getv(from_object, ['id']))
88
+
89
+ if getv(from_object, ['args']) is not None:
90
+ setv(to_object, ['args'], getv(from_object, ['args']))
91
+
92
+ if getv(from_object, ['name']) is not None:
93
+ setv(to_object, ['name'], getv(from_object, ['name']))
94
+
95
+ if getv(from_object, ['partial_args']) is not None:
96
+ raise ValueError('partial_args parameter is not supported in Gemini API.')
97
+
98
+ if getv(from_object, ['will_continue']) is not None:
99
+ raise ValueError('will_continue parameter is not supported in Gemini API.')
100
+
101
+ return to_object
102
+
103
+
81
104
  def _FunctionDeclaration_to_vertex(
82
105
  from_object: Union[dict[str, Any], object],
83
106
  parent_object: Optional[dict[str, Any]] = None,
@@ -1161,8 +1184,10 @@ def _Part_to_mldev(
1161
1184
  parent_object: Optional[dict[str, Any]] = None,
1162
1185
  ) -> dict[str, Any]:
1163
1186
  to_object: dict[str, Any] = {}
1164
- if getv(from_object, ['function_call']) is not None:
1165
- setv(to_object, ['functionCall'], getv(from_object, ['function_call']))
1187
+ if getv(from_object, ['media_resolution']) is not None:
1188
+ setv(
1189
+ to_object, ['mediaResolution'], getv(from_object, ['media_resolution'])
1190
+ )
1166
1191
 
1167
1192
  if getv(from_object, ['code_execution_result']) is not None:
1168
1193
  setv(
@@ -1181,6 +1206,13 @@ def _Part_to_mldev(
1181
1206
  _FileData_to_mldev(getv(from_object, ['file_data']), to_object),
1182
1207
  )
1183
1208
 
1209
+ if getv(from_object, ['function_call']) is not None:
1210
+ setv(
1211
+ to_object,
1212
+ ['functionCall'],
1213
+ _FunctionCall_to_mldev(getv(from_object, ['function_call']), to_object),
1214
+ )
1215
+
1184
1216
  if getv(from_object, ['function_response']) is not None:
1185
1217
  setv(
1186
1218
  to_object,
@@ -148,6 +148,29 @@ def _FileData_to_mldev(
148
148
  return to_object
149
149
 
150
150
 
151
+ def _FunctionCall_to_mldev(
152
+ from_object: Union[dict[str, Any], object],
153
+ parent_object: Optional[dict[str, Any]] = None,
154
+ ) -> dict[str, Any]:
155
+ to_object: dict[str, Any] = {}
156
+ if getv(from_object, ['id']) is not None:
157
+ setv(to_object, ['id'], getv(from_object, ['id']))
158
+
159
+ if getv(from_object, ['args']) is not None:
160
+ setv(to_object, ['args'], getv(from_object, ['args']))
161
+
162
+ if getv(from_object, ['name']) is not None:
163
+ setv(to_object, ['name'], getv(from_object, ['name']))
164
+
165
+ if getv(from_object, ['partial_args']) is not None:
166
+ raise ValueError('partial_args parameter is not supported in Gemini API.')
167
+
168
+ if getv(from_object, ['will_continue']) is not None:
169
+ raise ValueError('will_continue parameter is not supported in Gemini API.')
170
+
171
+ return to_object
172
+
173
+
151
174
  def _GoogleMaps_to_mldev(
152
175
  from_object: Union[dict[str, Any], object],
153
176
  parent_object: Optional[dict[str, Any]] = None,
@@ -365,8 +388,10 @@ def _Part_to_mldev(
365
388
  parent_object: Optional[dict[str, Any]] = None,
366
389
  ) -> dict[str, Any]:
367
390
  to_object: dict[str, Any] = {}
368
- if getv(from_object, ['function_call']) is not None:
369
- setv(to_object, ['functionCall'], getv(from_object, ['function_call']))
391
+ if getv(from_object, ['media_resolution']) is not None:
392
+ setv(
393
+ to_object, ['mediaResolution'], getv(from_object, ['media_resolution'])
394
+ )
370
395
 
371
396
  if getv(from_object, ['code_execution_result']) is not None:
372
397
  setv(
@@ -385,6 +410,13 @@ def _Part_to_mldev(
385
410
  _FileData_to_mldev(getv(from_object, ['file_data']), to_object),
386
411
  )
387
412
 
413
+ if getv(from_object, ['function_call']) is not None:
414
+ setv(
415
+ to_object,
416
+ ['functionCall'],
417
+ _FunctionCall_to_mldev(getv(from_object, ['function_call']), to_object),
418
+ )
419
+
388
420
  if getv(from_object, ['function_response']) is not None:
389
421
  setv(
390
422
  to_object,
google/genai/batches.py CHANGED
@@ -796,6 +796,53 @@ def _FileData_to_mldev(
796
796
  return to_object
797
797
 
798
798
 
799
+ def _FunctionCall_to_mldev(
800
+ from_object: Union[dict[str, Any], object],
801
+ parent_object: Optional[dict[str, Any]] = None,
802
+ ) -> dict[str, Any]:
803
+ to_object: dict[str, Any] = {}
804
+ if getv(from_object, ['id']) is not None:
805
+ setv(to_object, ['id'], getv(from_object, ['id']))
806
+
807
+ if getv(from_object, ['args']) is not None:
808
+ setv(to_object, ['args'], getv(from_object, ['args']))
809
+
810
+ if getv(from_object, ['name']) is not None:
811
+ setv(to_object, ['name'], getv(from_object, ['name']))
812
+
813
+ if getv(from_object, ['partial_args']) is not None:
814
+ raise ValueError('partial_args parameter is not supported in Gemini API.')
815
+
816
+ if getv(from_object, ['will_continue']) is not None:
817
+ raise ValueError('will_continue parameter is not supported in Gemini API.')
818
+
819
+ return to_object
820
+
821
+
822
+ def _FunctionCallingConfig_to_mldev(
823
+ from_object: Union[dict[str, Any], object],
824
+ parent_object: Optional[dict[str, Any]] = None,
825
+ ) -> dict[str, Any]:
826
+ to_object: dict[str, Any] = {}
827
+ if getv(from_object, ['mode']) is not None:
828
+ setv(to_object, ['mode'], getv(from_object, ['mode']))
829
+
830
+ if getv(from_object, ['allowed_function_names']) is not None:
831
+ setv(
832
+ to_object,
833
+ ['allowedFunctionNames'],
834
+ getv(from_object, ['allowed_function_names']),
835
+ )
836
+
837
+ if getv(from_object, ['stream_function_call_arguments']) is not None:
838
+ raise ValueError(
839
+ 'stream_function_call_arguments parameter is not supported in Gemini'
840
+ ' API.'
841
+ )
842
+
843
+ return to_object
844
+
845
+
799
846
  def _GenerateContentConfig_to_mldev(
800
847
  api_client: BaseApiClient,
801
848
  from_object: Union[dict[str, Any], object],
@@ -907,7 +954,11 @@ def _GenerateContentConfig_to_mldev(
907
954
  )
908
955
 
909
956
  if getv(from_object, ['tool_config']) is not None:
910
- setv(parent_object, ['toolConfig'], getv(from_object, ['tool_config']))
957
+ setv(
958
+ parent_object,
959
+ ['toolConfig'],
960
+ _ToolConfig_to_mldev(getv(from_object, ['tool_config']), to_object),
961
+ )
911
962
 
912
963
  if getv(from_object, ['labels']) is not None:
913
964
  raise ValueError('labels parameter is not supported in Gemini API.')
@@ -949,7 +1000,11 @@ def _GenerateContentConfig_to_mldev(
949
1000
  setv(to_object, ['thinkingConfig'], getv(from_object, ['thinking_config']))
950
1001
 
951
1002
  if getv(from_object, ['image_config']) is not None:
952
- setv(to_object, ['imageConfig'], getv(from_object, ['image_config']))
1003
+ setv(
1004
+ to_object,
1005
+ ['imageConfig'],
1006
+ _ImageConfig_to_mldev(getv(from_object, ['image_config']), to_object),
1007
+ )
953
1008
 
954
1009
  return to_object
955
1010
 
@@ -1058,6 +1113,30 @@ def _GoogleSearch_to_mldev(
1058
1113
  return to_object
1059
1114
 
1060
1115
 
1116
+ def _ImageConfig_to_mldev(
1117
+ from_object: Union[dict[str, Any], object],
1118
+ parent_object: Optional[dict[str, Any]] = None,
1119
+ ) -> dict[str, Any]:
1120
+ to_object: dict[str, Any] = {}
1121
+ if getv(from_object, ['aspect_ratio']) is not None:
1122
+ setv(to_object, ['aspectRatio'], getv(from_object, ['aspect_ratio']))
1123
+
1124
+ if getv(from_object, ['image_size']) is not None:
1125
+ setv(to_object, ['imageSize'], getv(from_object, ['image_size']))
1126
+
1127
+ if getv(from_object, ['output_mime_type']) is not None:
1128
+ raise ValueError(
1129
+ 'output_mime_type parameter is not supported in Gemini API.'
1130
+ )
1131
+
1132
+ if getv(from_object, ['output_compression_quality']) is not None:
1133
+ raise ValueError(
1134
+ 'output_compression_quality parameter is not supported in Gemini API.'
1135
+ )
1136
+
1137
+ return to_object
1138
+
1139
+
1061
1140
  def _InlinedRequest_to_mldev(
1062
1141
  api_client: BaseApiClient,
1063
1142
  from_object: Union[dict[str, Any], object],
@@ -1245,8 +1324,10 @@ def _Part_to_mldev(
1245
1324
  parent_object: Optional[dict[str, Any]] = None,
1246
1325
  ) -> dict[str, Any]:
1247
1326
  to_object: dict[str, Any] = {}
1248
- if getv(from_object, ['function_call']) is not None:
1249
- setv(to_object, ['functionCall'], getv(from_object, ['function_call']))
1327
+ if getv(from_object, ['media_resolution']) is not None:
1328
+ setv(
1329
+ to_object, ['mediaResolution'], getv(from_object, ['media_resolution'])
1330
+ )
1250
1331
 
1251
1332
  if getv(from_object, ['code_execution_result']) is not None:
1252
1333
  setv(
@@ -1265,6 +1346,13 @@ def _Part_to_mldev(
1265
1346
  _FileData_to_mldev(getv(from_object, ['file_data']), to_object),
1266
1347
  )
1267
1348
 
1349
+ if getv(from_object, ['function_call']) is not None:
1350
+ setv(
1351
+ to_object,
1352
+ ['functionCall'],
1353
+ _FunctionCall_to_mldev(getv(from_object, ['function_call']), to_object),
1354
+ )
1355
+
1268
1356
  if getv(from_object, ['function_response']) is not None:
1269
1357
  setv(
1270
1358
  to_object,
@@ -1315,6 +1403,28 @@ def _SafetySetting_to_mldev(
1315
1403
  return to_object
1316
1404
 
1317
1405
 
1406
+ def _ToolConfig_to_mldev(
1407
+ from_object: Union[dict[str, Any], object],
1408
+ parent_object: Optional[dict[str, Any]] = None,
1409
+ ) -> dict[str, Any]:
1410
+ to_object: dict[str, Any] = {}
1411
+ if getv(from_object, ['function_calling_config']) is not None:
1412
+ setv(
1413
+ to_object,
1414
+ ['functionCallingConfig'],
1415
+ _FunctionCallingConfig_to_mldev(
1416
+ getv(from_object, ['function_calling_config']), to_object
1417
+ ),
1418
+ )
1419
+
1420
+ if getv(from_object, ['retrieval_config']) is not None:
1421
+ setv(
1422
+ to_object, ['retrievalConfig'], getv(from_object, ['retrieval_config'])
1423
+ )
1424
+
1425
+ return to_object
1426
+
1427
+
1318
1428
  def _Tool_to_mldev(
1319
1429
  from_object: Union[dict[str, Any], object],
1320
1430
  parent_object: Optional[dict[str, Any]] = None,
google/genai/caches.py CHANGED
@@ -116,7 +116,11 @@ def _CreateCachedContentConfig_to_mldev(
116
116
  )
117
117
 
118
118
  if getv(from_object, ['tool_config']) is not None:
119
- setv(parent_object, ['toolConfig'], getv(from_object, ['tool_config']))
119
+ setv(
120
+ parent_object,
121
+ ['toolConfig'],
122
+ _ToolConfig_to_mldev(getv(from_object, ['tool_config']), to_object),
123
+ )
120
124
 
121
125
  if getv(from_object, ['kms_key_name']) is not None:
122
126
  raise ValueError('kms_key_name parameter is not supported in Gemini API.')
@@ -293,6 +297,53 @@ def _FileData_to_mldev(
293
297
  return to_object
294
298
 
295
299
 
300
+ def _FunctionCall_to_mldev(
301
+ from_object: Union[dict[str, Any], object],
302
+ parent_object: Optional[dict[str, Any]] = None,
303
+ ) -> dict[str, Any]:
304
+ to_object: dict[str, Any] = {}
305
+ if getv(from_object, ['id']) is not None:
306
+ setv(to_object, ['id'], getv(from_object, ['id']))
307
+
308
+ if getv(from_object, ['args']) is not None:
309
+ setv(to_object, ['args'], getv(from_object, ['args']))
310
+
311
+ if getv(from_object, ['name']) is not None:
312
+ setv(to_object, ['name'], getv(from_object, ['name']))
313
+
314
+ if getv(from_object, ['partial_args']) is not None:
315
+ raise ValueError('partial_args parameter is not supported in Gemini API.')
316
+
317
+ if getv(from_object, ['will_continue']) is not None:
318
+ raise ValueError('will_continue parameter is not supported in Gemini API.')
319
+
320
+ return to_object
321
+
322
+
323
+ def _FunctionCallingConfig_to_mldev(
324
+ from_object: Union[dict[str, Any], object],
325
+ parent_object: Optional[dict[str, Any]] = None,
326
+ ) -> dict[str, Any]:
327
+ to_object: dict[str, Any] = {}
328
+ if getv(from_object, ['mode']) is not None:
329
+ setv(to_object, ['mode'], getv(from_object, ['mode']))
330
+
331
+ if getv(from_object, ['allowed_function_names']) is not None:
332
+ setv(
333
+ to_object,
334
+ ['allowedFunctionNames'],
335
+ getv(from_object, ['allowed_function_names']),
336
+ )
337
+
338
+ if getv(from_object, ['stream_function_call_arguments']) is not None:
339
+ raise ValueError(
340
+ 'stream_function_call_arguments parameter is not supported in Gemini'
341
+ ' API.'
342
+ )
343
+
344
+ return to_object
345
+
346
+
296
347
  def _FunctionDeclaration_to_vertex(
297
348
  from_object: Union[dict[str, Any], object],
298
349
  parent_object: Optional[dict[str, Any]] = None,
@@ -516,8 +567,10 @@ def _Part_to_mldev(
516
567
  parent_object: Optional[dict[str, Any]] = None,
517
568
  ) -> dict[str, Any]:
518
569
  to_object: dict[str, Any] = {}
519
- if getv(from_object, ['function_call']) is not None:
520
- setv(to_object, ['functionCall'], getv(from_object, ['function_call']))
570
+ if getv(from_object, ['media_resolution']) is not None:
571
+ setv(
572
+ to_object, ['mediaResolution'], getv(from_object, ['media_resolution'])
573
+ )
521
574
 
522
575
  if getv(from_object, ['code_execution_result']) is not None:
523
576
  setv(
@@ -536,6 +589,13 @@ def _Part_to_mldev(
536
589
  _FileData_to_mldev(getv(from_object, ['file_data']), to_object),
537
590
  )
538
591
 
592
+ if getv(from_object, ['function_call']) is not None:
593
+ setv(
594
+ to_object,
595
+ ['functionCall'],
596
+ _FunctionCall_to_mldev(getv(from_object, ['function_call']), to_object),
597
+ )
598
+
539
599
  if getv(from_object, ['function_response']) is not None:
540
600
  setv(
541
601
  to_object,
@@ -569,6 +629,28 @@ def _Part_to_mldev(
569
629
  return to_object
570
630
 
571
631
 
632
+ def _ToolConfig_to_mldev(
633
+ from_object: Union[dict[str, Any], object],
634
+ parent_object: Optional[dict[str, Any]] = None,
635
+ ) -> dict[str, Any]:
636
+ to_object: dict[str, Any] = {}
637
+ if getv(from_object, ['function_calling_config']) is not None:
638
+ setv(
639
+ to_object,
640
+ ['functionCallingConfig'],
641
+ _FunctionCallingConfig_to_mldev(
642
+ getv(from_object, ['function_calling_config']), to_object
643
+ ),
644
+ )
645
+
646
+ if getv(from_object, ['retrieval_config']) is not None:
647
+ setv(
648
+ to_object, ['retrievalConfig'], getv(from_object, ['retrieval_config'])
649
+ )
650
+
651
+ return to_object
652
+
653
+
572
654
  def _Tool_to_mldev(
573
655
  from_object: Union[dict[str, Any], object],
574
656
  parent_object: Optional[dict[str, Any]] = None,