google-genai 1.5.0__py3-none-any.whl → 1.7.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.
- google/genai/_api_client.py +196 -141
- google/genai/_automatic_function_calling_util.py +4 -14
- google/genai/_common.py +7 -5
- google/genai/_replay_api_client.py +6 -3
- google/genai/_transformers.py +61 -37
- google/genai/batches.py +4 -0
- google/genai/caches.py +20 -26
- google/genai/chats.py +137 -46
- google/genai/client.py +3 -2
- google/genai/errors.py +11 -19
- google/genai/files.py +9 -9
- google/genai/live.py +276 -93
- google/genai/models.py +245 -68
- google/genai/operations.py +30 -2
- google/genai/pagers.py +3 -5
- google/genai/tunings.py +31 -21
- google/genai/types.py +88 -33
- google/genai/version.py +1 -1
- {google_genai-1.5.0.dist-info → google_genai-1.7.0.dist-info}/METADATA +201 -31
- google_genai-1.7.0.dist-info/RECORD +27 -0
- {google_genai-1.5.0.dist-info → google_genai-1.7.0.dist-info}/WHEEL +1 -1
- google_genai-1.5.0.dist-info/RECORD +0 -27
- {google_genai-1.5.0.dist-info → google_genai-1.7.0.dist-info}/LICENSE +0 -0
- {google_genai-1.5.0.dist-info → google_genai-1.7.0.dist-info}/top_level.txt +0 -0
google/genai/_transformers.py
CHANGED
@@ -26,9 +26,7 @@ import sys
|
|
26
26
|
import time
|
27
27
|
import types as builtin_types
|
28
28
|
import typing
|
29
|
-
from typing import Any, GenericAlias, Optional, Union
|
30
|
-
|
31
|
-
import types as builtin_types
|
29
|
+
from typing import Any, GenericAlias, Optional, Union # type: ignore[attr-defined]
|
32
30
|
|
33
31
|
if typing.TYPE_CHECKING:
|
34
32
|
import PIL.Image
|
@@ -43,10 +41,11 @@ logger = logging.getLogger('google_genai._transformers')
|
|
43
41
|
if sys.version_info >= (3, 10):
|
44
42
|
VersionedUnionType = builtin_types.UnionType
|
45
43
|
_UNION_TYPES = (typing.Union, builtin_types.UnionType)
|
44
|
+
from typing import TypeGuard
|
46
45
|
else:
|
47
46
|
VersionedUnionType = typing._UnionGenericAlias
|
48
47
|
_UNION_TYPES = (typing.Union,)
|
49
|
-
|
48
|
+
from typing_extensions import TypeGuard
|
50
49
|
|
51
50
|
def _resource_name(
|
52
51
|
client: _api_client.BaseApiClient,
|
@@ -165,7 +164,9 @@ def t_model(client: _api_client.BaseApiClient, model: str):
|
|
165
164
|
return f'models/{model}'
|
166
165
|
|
167
166
|
|
168
|
-
def t_models_url(
|
167
|
+
def t_models_url(
|
168
|
+
api_client: _api_client.BaseApiClient, base_models: bool
|
169
|
+
) -> str:
|
169
170
|
if api_client.vertexai:
|
170
171
|
if base_models:
|
171
172
|
return 'publishers/google/models'
|
@@ -179,7 +180,8 @@ def t_models_url(api_client: _api_client.BaseApiClient, base_models: bool) -> st
|
|
179
180
|
|
180
181
|
|
181
182
|
def t_extract_models(
|
182
|
-
api_client: _api_client.BaseApiClient,
|
183
|
+
api_client: _api_client.BaseApiClient,
|
184
|
+
response: dict[str, list[types.ModelDict]],
|
183
185
|
) -> Optional[list[types.ModelDict]]:
|
184
186
|
if not response:
|
185
187
|
return []
|
@@ -240,9 +242,7 @@ def pil_to_blob(img) -> types.Blob:
|
|
240
242
|
return types.Blob(mime_type=mime_type, data=data)
|
241
243
|
|
242
244
|
|
243
|
-
def t_part(
|
244
|
-
part: Optional[types.PartUnionDict]
|
245
|
-
) -> types.Part:
|
245
|
+
def t_part(part: Optional[types.PartUnionDict]) -> types.Part:
|
246
246
|
try:
|
247
247
|
import PIL.Image
|
248
248
|
|
@@ -268,7 +268,7 @@ def t_part(
|
|
268
268
|
|
269
269
|
|
270
270
|
def t_parts(
|
271
|
-
parts: Optional[Union[list[types.PartUnionDict], types.PartUnionDict]],
|
271
|
+
parts: Optional[Union[list[types.PartUnionDict], types.PartUnionDict, list[types.Part]]],
|
272
272
|
) -> list[types.Part]:
|
273
273
|
#
|
274
274
|
if parts is None or (isinstance(parts, list) and not parts):
|
@@ -332,22 +332,35 @@ def t_content(
|
|
332
332
|
def t_contents_for_embed(
|
333
333
|
client: _api_client.BaseApiClient,
|
334
334
|
contents: Union[list[types.Content], list[types.ContentDict], ContentType],
|
335
|
-
):
|
336
|
-
if
|
337
|
-
|
338
|
-
return [t_content(client, content).parts[0].text for content in contents]
|
339
|
-
elif client.vertexai:
|
340
|
-
return [t_content(client, contents).parts[0].text]
|
341
|
-
elif isinstance(contents, list):
|
342
|
-
return [t_content(client, content) for content in contents]
|
335
|
+
) -> Union[list[str], list[types.Content]]:
|
336
|
+
if isinstance(contents, list):
|
337
|
+
transformed_contents = [t_content(client, content) for content in contents]
|
343
338
|
else:
|
344
|
-
|
339
|
+
transformed_contents = [t_content(client, contents)]
|
340
|
+
|
341
|
+
if client.vertexai:
|
342
|
+
text_parts = []
|
343
|
+
for content in transformed_contents:
|
344
|
+
if content is not None:
|
345
|
+
if isinstance(content, dict):
|
346
|
+
content = types.Content.model_validate(content)
|
347
|
+
if content.parts is not None:
|
348
|
+
for part in content.parts:
|
349
|
+
if part.text:
|
350
|
+
text_parts.append(part.text)
|
351
|
+
else:
|
352
|
+
logger.warning(
|
353
|
+
f'Non-text part found, only returning text parts.'
|
354
|
+
)
|
355
|
+
return text_parts
|
356
|
+
else:
|
357
|
+
return transformed_contents
|
345
358
|
|
346
359
|
|
347
360
|
def t_contents(
|
348
361
|
client: _api_client.BaseApiClient,
|
349
362
|
contents: Optional[
|
350
|
-
Union[types.ContentListUnion, types.ContentListUnionDict]
|
363
|
+
Union[types.ContentListUnion, types.ContentListUnionDict, types.Content]
|
351
364
|
],
|
352
365
|
) -> list[types.Content]:
|
353
366
|
if contents is None or (isinstance(contents, list) and not contents):
|
@@ -365,7 +378,7 @@ def t_contents(
|
|
365
378
|
result: list[types.Content] = []
|
366
379
|
accumulated_parts: list[types.Part] = []
|
367
380
|
|
368
|
-
def _is_part(part: types.PartUnionDict) ->
|
381
|
+
def _is_part(part: Union[types.PartUnionDict, Any]) -> TypeGuard[types.PartUnionDict]:
|
369
382
|
if (
|
370
383
|
isinstance(part, str)
|
371
384
|
or isinstance(part, types.File)
|
@@ -429,11 +442,11 @@ def t_contents(
|
|
429
442
|
):
|
430
443
|
_append_accumulated_parts_as_content(result, accumulated_parts)
|
431
444
|
if isinstance(content, list):
|
432
|
-
result.append(types.UserContent(parts=content))
|
445
|
+
result.append(types.UserContent(parts=content)) # type: ignore[arg-type]
|
433
446
|
else:
|
434
447
|
result.append(content)
|
435
|
-
elif (_is_part(content)):
|
436
|
-
_handle_current_part(result, accumulated_parts, content)
|
448
|
+
elif (_is_part(content)):
|
449
|
+
_handle_current_part(result, accumulated_parts, content)
|
437
450
|
elif isinstance(content, dict):
|
438
451
|
# PactDict is already handled in _is_part
|
439
452
|
result.append(types.Content.model_validate(content))
|
@@ -499,7 +512,7 @@ def handle_null_fields(schema: dict[str, Any]):
|
|
499
512
|
schema['anyOf'].remove({'type': 'null'})
|
500
513
|
if len(schema['anyOf']) == 1:
|
501
514
|
# If there is only one type left after removing null, remove the anyOf field.
|
502
|
-
for key,val in schema['anyOf'][0].items():
|
515
|
+
for key, val in schema['anyOf'][0].items():
|
503
516
|
schema[key] = val
|
504
517
|
del schema['anyOf']
|
505
518
|
|
@@ -574,7 +587,8 @@ def process_schema(
|
|
574
587
|
|
575
588
|
if schema.get('default') is not None:
|
576
589
|
raise ValueError(
|
577
|
-
'Default value is not supported in the response schema for the Gemini
|
590
|
+
'Default value is not supported in the response schema for the Gemini'
|
591
|
+
' API.'
|
578
592
|
)
|
579
593
|
|
580
594
|
if schema.get('title') == 'PlaceholderLiteralEnum':
|
@@ -604,10 +618,6 @@ def process_schema(
|
|
604
618
|
|
605
619
|
any_of = schema.get('anyOf', None)
|
606
620
|
if any_of is not None:
|
607
|
-
if client and not client.vertexai:
|
608
|
-
raise ValueError(
|
609
|
-
'AnyOf is not supported in the response schema for the Gemini API.'
|
610
|
-
)
|
611
621
|
for sub_schema in any_of:
|
612
622
|
# $ref is present in any_of if the schema is a union of Pydantic classes
|
613
623
|
ref_key = sub_schema.get('$ref', None)
|
@@ -670,7 +680,7 @@ def process_schema(
|
|
670
680
|
|
671
681
|
|
672
682
|
def _process_enum(
|
673
|
-
enum: EnumMeta, client:
|
683
|
+
enum: EnumMeta, client: _api_client.BaseApiClient
|
674
684
|
) -> types.Schema:
|
675
685
|
for member in enum: # type: ignore
|
676
686
|
if not isinstance(member.value, str):
|
@@ -680,7 +690,7 @@ def _process_enum(
|
|
680
690
|
)
|
681
691
|
|
682
692
|
class Placeholder(pydantic.BaseModel):
|
683
|
-
placeholder: enum
|
693
|
+
placeholder: enum # type: ignore[valid-type]
|
684
694
|
|
685
695
|
enum_schema = Placeholder.model_json_schema()
|
686
696
|
process_schema(enum_schema, client)
|
@@ -688,12 +698,19 @@ def _process_enum(
|
|
688
698
|
return types.Schema.model_validate(enum_schema)
|
689
699
|
|
690
700
|
|
701
|
+
def _is_type_dict_str_any(origin: Union[types.SchemaUnionDict, Any]) -> TypeGuard[dict[str, Any]]:
|
702
|
+
"""Verifies the schema is of type dict[str, Any] for mypy type checking."""
|
703
|
+
return isinstance(origin, dict) and all(
|
704
|
+
isinstance(key, str) for key in origin
|
705
|
+
)
|
706
|
+
|
707
|
+
|
691
708
|
def t_schema(
|
692
709
|
client: _api_client.BaseApiClient, origin: Union[types.SchemaUnionDict, Any]
|
693
710
|
) -> Optional[types.Schema]:
|
694
711
|
if not origin:
|
695
712
|
return None
|
696
|
-
if isinstance(origin, dict):
|
713
|
+
if isinstance(origin, dict) and _is_type_dict_str_any(origin):
|
697
714
|
process_schema(origin, client, order_properties=False)
|
698
715
|
return types.Schema.model_validate(origin)
|
699
716
|
if isinstance(origin, EnumMeta):
|
@@ -724,7 +741,7 @@ def t_schema(
|
|
724
741
|
):
|
725
742
|
|
726
743
|
class Placeholder(pydantic.BaseModel):
|
727
|
-
placeholder: origin
|
744
|
+
placeholder: origin # type: ignore[valid-type]
|
728
745
|
|
729
746
|
schema = Placeholder.model_json_schema()
|
730
747
|
process_schema(schema, client)
|
@@ -735,7 +752,8 @@ def t_schema(
|
|
735
752
|
|
736
753
|
|
737
754
|
def t_speech_config(
|
738
|
-
_: _api_client.BaseApiClient,
|
755
|
+
_: _api_client.BaseApiClient,
|
756
|
+
origin: Union[types.SpeechConfigUnionDict, Any],
|
739
757
|
) -> Optional[types.SpeechConfig]:
|
740
758
|
if not origin:
|
741
759
|
return None
|
@@ -794,7 +812,10 @@ def t_tools(
|
|
794
812
|
transformed_tool = t_tool(client, tool)
|
795
813
|
# All functions should be merged into one tool.
|
796
814
|
if transformed_tool is not None:
|
797
|
-
if
|
815
|
+
if (
|
816
|
+
transformed_tool.function_declarations
|
817
|
+
and function_tool.function_declarations is not None
|
818
|
+
):
|
798
819
|
function_tool.function_declarations += (
|
799
820
|
transformed_tool.function_declarations
|
800
821
|
)
|
@@ -896,7 +917,10 @@ def t_file_name(
|
|
896
917
|
elif isinstance(name, types.Video):
|
897
918
|
name = name.uri
|
898
919
|
elif isinstance(name, types.GeneratedVideo):
|
899
|
-
|
920
|
+
if name.video is not None:
|
921
|
+
name = name.video.uri
|
922
|
+
else:
|
923
|
+
name = None
|
900
924
|
|
901
925
|
if name is None:
|
902
926
|
raise ValueError('File name is required.')
|
google/genai/batches.py
CHANGED
@@ -998,6 +998,8 @@ class Batches(_api_module.BaseModule):
|
|
998
998
|
for batch_job in batch_jobs:
|
999
999
|
print(f"Batch job: {batch_job.name}, state {batch_job.state}")
|
1000
1000
|
"""
|
1001
|
+
if config is None:
|
1002
|
+
config = types.ListBatchJobsConfig()
|
1001
1003
|
return Pager(
|
1002
1004
|
'batch_jobs',
|
1003
1005
|
self._list,
|
@@ -1373,6 +1375,8 @@ class AsyncBatches(_api_module.BaseModule):
|
|
1373
1375
|
await batch_jobs_pager.next_page()
|
1374
1376
|
print(f"next page: {batch_jobs_pager.page}")
|
1375
1377
|
"""
|
1378
|
+
if config is None:
|
1379
|
+
config = types.ListBatchJobsConfig()
|
1376
1380
|
return AsyncPager(
|
1377
1381
|
'batch_jobs',
|
1378
1382
|
self._list,
|
google/genai/caches.py
CHANGED
@@ -174,15 +174,9 @@ def _Schema_to_mldev(
|
|
174
174
|
if getv(from_object, ['pattern']) is not None:
|
175
175
|
raise ValueError('pattern parameter is not supported in Gemini API.')
|
176
176
|
|
177
|
-
if getv(from_object, ['minimum']) is not None:
|
178
|
-
raise ValueError('minimum parameter is not supported in Gemini API.')
|
179
|
-
|
180
177
|
if getv(from_object, ['default']) is not None:
|
181
178
|
raise ValueError('default parameter is not supported in Gemini API.')
|
182
179
|
|
183
|
-
if getv(from_object, ['any_of']) is not None:
|
184
|
-
raise ValueError('any_of parameter is not supported in Gemini API.')
|
185
|
-
|
186
180
|
if getv(from_object, ['max_length']) is not None:
|
187
181
|
raise ValueError('max_length parameter is not supported in Gemini API.')
|
188
182
|
|
@@ -195,12 +189,12 @@ def _Schema_to_mldev(
|
|
195
189
|
if getv(from_object, ['min_properties']) is not None:
|
196
190
|
raise ValueError('min_properties parameter is not supported in Gemini API.')
|
197
191
|
|
198
|
-
if getv(from_object, ['maximum']) is not None:
|
199
|
-
raise ValueError('maximum parameter is not supported in Gemini API.')
|
200
|
-
|
201
192
|
if getv(from_object, ['max_properties']) is not None:
|
202
193
|
raise ValueError('max_properties parameter is not supported in Gemini API.')
|
203
194
|
|
195
|
+
if getv(from_object, ['any_of']) is not None:
|
196
|
+
setv(to_object, ['anyOf'], getv(from_object, ['any_of']))
|
197
|
+
|
204
198
|
if getv(from_object, ['description']) is not None:
|
205
199
|
setv(to_object, ['description'], getv(from_object, ['description']))
|
206
200
|
|
@@ -216,9 +210,15 @@ def _Schema_to_mldev(
|
|
216
210
|
if getv(from_object, ['max_items']) is not None:
|
217
211
|
setv(to_object, ['maxItems'], getv(from_object, ['max_items']))
|
218
212
|
|
213
|
+
if getv(from_object, ['maximum']) is not None:
|
214
|
+
setv(to_object, ['maximum'], getv(from_object, ['maximum']))
|
215
|
+
|
219
216
|
if getv(from_object, ['min_items']) is not None:
|
220
217
|
setv(to_object, ['minItems'], getv(from_object, ['min_items']))
|
221
218
|
|
219
|
+
if getv(from_object, ['minimum']) is not None:
|
220
|
+
setv(to_object, ['minimum'], getv(from_object, ['minimum']))
|
221
|
+
|
222
222
|
if getv(from_object, ['nullable']) is not None:
|
223
223
|
setv(to_object, ['nullable'], getv(from_object, ['nullable']))
|
224
224
|
|
@@ -253,15 +253,9 @@ def _Schema_to_vertex(
|
|
253
253
|
if getv(from_object, ['pattern']) is not None:
|
254
254
|
setv(to_object, ['pattern'], getv(from_object, ['pattern']))
|
255
255
|
|
256
|
-
if getv(from_object, ['minimum']) is not None:
|
257
|
-
setv(to_object, ['minimum'], getv(from_object, ['minimum']))
|
258
|
-
|
259
256
|
if getv(from_object, ['default']) is not None:
|
260
257
|
setv(to_object, ['default'], getv(from_object, ['default']))
|
261
258
|
|
262
|
-
if getv(from_object, ['any_of']) is not None:
|
263
|
-
setv(to_object, ['anyOf'], getv(from_object, ['any_of']))
|
264
|
-
|
265
259
|
if getv(from_object, ['max_length']) is not None:
|
266
260
|
setv(to_object, ['maxLength'], getv(from_object, ['max_length']))
|
267
261
|
|
@@ -274,12 +268,12 @@ def _Schema_to_vertex(
|
|
274
268
|
if getv(from_object, ['min_properties']) is not None:
|
275
269
|
setv(to_object, ['minProperties'], getv(from_object, ['min_properties']))
|
276
270
|
|
277
|
-
if getv(from_object, ['maximum']) is not None:
|
278
|
-
setv(to_object, ['maximum'], getv(from_object, ['maximum']))
|
279
|
-
|
280
271
|
if getv(from_object, ['max_properties']) is not None:
|
281
272
|
setv(to_object, ['maxProperties'], getv(from_object, ['max_properties']))
|
282
273
|
|
274
|
+
if getv(from_object, ['any_of']) is not None:
|
275
|
+
setv(to_object, ['anyOf'], getv(from_object, ['any_of']))
|
276
|
+
|
283
277
|
if getv(from_object, ['description']) is not None:
|
284
278
|
setv(to_object, ['description'], getv(from_object, ['description']))
|
285
279
|
|
@@ -295,9 +289,15 @@ def _Schema_to_vertex(
|
|
295
289
|
if getv(from_object, ['max_items']) is not None:
|
296
290
|
setv(to_object, ['maxItems'], getv(from_object, ['max_items']))
|
297
291
|
|
292
|
+
if getv(from_object, ['maximum']) is not None:
|
293
|
+
setv(to_object, ['maximum'], getv(from_object, ['maximum']))
|
294
|
+
|
298
295
|
if getv(from_object, ['min_items']) is not None:
|
299
296
|
setv(to_object, ['minItems'], getv(from_object, ['min_items']))
|
300
297
|
|
298
|
+
if getv(from_object, ['minimum']) is not None:
|
299
|
+
setv(to_object, ['minimum'], getv(from_object, ['minimum']))
|
300
|
+
|
301
301
|
if getv(from_object, ['nullable']) is not None:
|
302
302
|
setv(to_object, ['nullable'], getv(from_object, ['nullable']))
|
303
303
|
|
@@ -1176,10 +1176,7 @@ class Caches(_api_module.BaseModule):
|
|
1176
1176
|
model: str,
|
1177
1177
|
config: Optional[types.CreateCachedContentConfigOrDict] = None,
|
1178
1178
|
) -> types.CachedContent:
|
1179
|
-
"""Creates cached
|
1180
|
-
|
1181
|
-
content in the data storage, and users need to pay for the cache data
|
1182
|
-
storage.
|
1179
|
+
"""Creates a cached contents resource.
|
1183
1180
|
|
1184
1181
|
Usage:
|
1185
1182
|
|
@@ -1562,10 +1559,7 @@ class AsyncCaches(_api_module.BaseModule):
|
|
1562
1559
|
model: str,
|
1563
1560
|
config: Optional[types.CreateCachedContentConfigOrDict] = None,
|
1564
1561
|
) -> types.CachedContent:
|
1565
|
-
"""Creates cached
|
1566
|
-
|
1567
|
-
content in the data storage, and users need to pay for the cache data
|
1568
|
-
storage.
|
1562
|
+
"""Creates a cached contents resource.
|
1569
1563
|
|
1570
1564
|
Usage:
|
1571
1565
|
|