google-genai 0.5.0__py3-none-any.whl → 0.6.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 +164 -55
- google/genai/_common.py +37 -6
- google/genai/_extra_utils.py +3 -3
- google/genai/_replay_api_client.py +44 -32
- google/genai/_transformers.py +167 -38
- google/genai/batches.py +10 -10
- google/genai/caches.py +10 -10
- google/genai/client.py +2 -1
- google/genai/errors.py +1 -1
- google/genai/files.py +239 -40
- google/genai/live.py +5 -1
- google/genai/models.py +102 -30
- google/genai/tunings.py +8 -8
- google/genai/types.py +546 -348
- google/genai/version.py +1 -1
- google_genai-0.6.0.dist-info/METADATA +973 -0
- google_genai-0.6.0.dist-info/RECORD +25 -0
- google_genai-0.5.0.dist-info/METADATA +0 -888
- google_genai-0.5.0.dist-info/RECORD +0 -25
- {google_genai-0.5.0.dist-info → google_genai-0.6.0.dist-info}/LICENSE +0 -0
- {google_genai-0.5.0.dist-info → google_genai-0.6.0.dist-info}/WHEEL +0 -0
- {google_genai-0.5.0.dist-info → google_genai-0.6.0.dist-info}/top_level.txt +0 -0
google/genai/files.py
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
# Code generated by the Google Gen AI SDK generator DO NOT EDIT.
|
17
17
|
|
18
|
+
import io
|
18
19
|
import mimetypes
|
19
20
|
import os
|
20
21
|
import pathlib
|
@@ -176,9 +177,15 @@ def _File_to_mldev(
|
|
176
177
|
if getv(from_object, ['uri']) is not None:
|
177
178
|
setv(to_object, ['uri'], getv(from_object, ['uri']))
|
178
179
|
|
180
|
+
if getv(from_object, ['download_uri']) is not None:
|
181
|
+
setv(to_object, ['downloadUri'], getv(from_object, ['download_uri']))
|
182
|
+
|
179
183
|
if getv(from_object, ['state']) is not None:
|
180
184
|
setv(to_object, ['state'], getv(from_object, ['state']))
|
181
185
|
|
186
|
+
if getv(from_object, ['source']) is not None:
|
187
|
+
setv(to_object, ['source'], getv(from_object, ['source']))
|
188
|
+
|
182
189
|
if getv(from_object, ['video_metadata']) is not None:
|
183
190
|
setv(to_object, ['videoMetadata'], getv(from_object, ['video_metadata']))
|
184
191
|
|
@@ -227,9 +234,15 @@ def _File_to_vertex(
|
|
227
234
|
if getv(from_object, ['uri']) is not None:
|
228
235
|
raise ValueError('uri parameter is not supported in Vertex AI.')
|
229
236
|
|
237
|
+
if getv(from_object, ['download_uri']) is not None:
|
238
|
+
raise ValueError('download_uri parameter is not supported in Vertex AI.')
|
239
|
+
|
230
240
|
if getv(from_object, ['state']) is not None:
|
231
241
|
raise ValueError('state parameter is not supported in Vertex AI.')
|
232
242
|
|
243
|
+
if getv(from_object, ['source']) is not None:
|
244
|
+
raise ValueError('source parameter is not supported in Vertex AI.')
|
245
|
+
|
233
246
|
if getv(from_object, ['video_metadata']) is not None:
|
234
247
|
raise ValueError('video_metadata parameter is not supported in Vertex AI.')
|
235
248
|
|
@@ -492,9 +505,15 @@ def _File_from_mldev(
|
|
492
505
|
if getv(from_object, ['uri']) is not None:
|
493
506
|
setv(to_object, ['uri'], getv(from_object, ['uri']))
|
494
507
|
|
508
|
+
if getv(from_object, ['downloadUri']) is not None:
|
509
|
+
setv(to_object, ['download_uri'], getv(from_object, ['downloadUri']))
|
510
|
+
|
495
511
|
if getv(from_object, ['state']) is not None:
|
496
512
|
setv(to_object, ['state'], getv(from_object, ['state']))
|
497
513
|
|
514
|
+
if getv(from_object, ['source']) is not None:
|
515
|
+
setv(to_object, ['source'], getv(from_object, ['source']))
|
516
|
+
|
498
517
|
if getv(from_object, ['videoMetadata']) is not None:
|
499
518
|
setv(to_object, ['video_metadata'], getv(from_object, ['videoMetadata']))
|
500
519
|
|
@@ -633,7 +652,7 @@ class Files(_common.BaseModule):
|
|
633
652
|
config = request_dict.pop('config', None)
|
634
653
|
http_options = config.pop('httpOptions', None) if config else None
|
635
654
|
request_dict = _common.convert_to_dict(request_dict)
|
636
|
-
request_dict = _common.
|
655
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
637
656
|
|
638
657
|
response_dict = self._api_client.request(
|
639
658
|
'get', path, request_dict, http_options
|
@@ -680,7 +699,7 @@ class Files(_common.BaseModule):
|
|
680
699
|
config = request_dict.pop('config', None)
|
681
700
|
http_options = config.pop('httpOptions', None) if config else None
|
682
701
|
request_dict = _common.convert_to_dict(request_dict)
|
683
|
-
request_dict = _common.
|
702
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
684
703
|
|
685
704
|
response_dict = self._api_client.request(
|
686
705
|
'post', path, request_dict, http_options
|
@@ -741,7 +760,7 @@ class Files(_common.BaseModule):
|
|
741
760
|
config = request_dict.pop('config', None)
|
742
761
|
http_options = config.pop('httpOptions', None) if config else None
|
743
762
|
request_dict = _common.convert_to_dict(request_dict)
|
744
|
-
request_dict = _common.
|
763
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
745
764
|
|
746
765
|
response_dict = self._api_client.request(
|
747
766
|
'get', path, request_dict, http_options
|
@@ -795,7 +814,7 @@ class Files(_common.BaseModule):
|
|
795
814
|
config = request_dict.pop('config', None)
|
796
815
|
http_options = config.pop('httpOptions', None) if config else None
|
797
816
|
request_dict = _common.convert_to_dict(request_dict)
|
798
|
-
request_dict = _common.
|
817
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
799
818
|
|
800
819
|
response_dict = self._api_client.request(
|
801
820
|
'delete', path, request_dict, http_options
|
@@ -819,13 +838,16 @@ class Files(_common.BaseModule):
|
|
819
838
|
def upload(
|
820
839
|
self,
|
821
840
|
*,
|
822
|
-
path: str
|
841
|
+
path: Union[str, pathlib.Path, os.PathLike, io.IOBase],
|
823
842
|
config: Optional[types.UploadFileConfigOrDict] = None,
|
824
843
|
) -> types.File:
|
825
844
|
"""Calls the API to upload a file using a supported file service.
|
826
845
|
|
827
846
|
Args:
|
828
|
-
path: The path
|
847
|
+
path: The path to the file or an `IOBase` object to be uploaded. If it's
|
848
|
+
an IOBase object, it must be opened in blocking mode and binary mode. In
|
849
|
+
other words, do not use non-blocking mode or text mode. The given stream
|
850
|
+
must be seekable, that is, it must be able to call seek() on 'path'.
|
829
851
|
config: Optional parameters to set `diplay_name`, `mime_type`, and `name`.
|
830
852
|
"""
|
831
853
|
if self._api_client.vertexai:
|
@@ -849,17 +871,31 @@ class Files(_common.BaseModule):
|
|
849
871
|
if file.name is not None and not file.name.startswith('files/'):
|
850
872
|
file.name = f'files/{file.name}'
|
851
873
|
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
'
|
861
|
-
|
862
|
-
)
|
874
|
+
if isinstance(path, io.IOBase):
|
875
|
+
if file.mime_type is None:
|
876
|
+
raise ValueError(
|
877
|
+
'Unknown mime type: Could not determine the mimetype for your'
|
878
|
+
' file\n please set the `mime_type` argument'
|
879
|
+
)
|
880
|
+
if hasattr(path, 'mode'):
|
881
|
+
if 'b' not in path.mode:
|
882
|
+
raise ValueError('The file must be opened in binary mode.')
|
883
|
+
offset = path.tell()
|
884
|
+
path.seek(0, os.SEEK_END)
|
885
|
+
file.size_bytes = path.tell() - offset
|
886
|
+
path.seek(offset, os.SEEK_SET)
|
887
|
+
else:
|
888
|
+
fs_path = os.fspath(path)
|
889
|
+
if not fs_path or not os.path.isfile(fs_path):
|
890
|
+
raise FileNotFoundError(f'{path} is not a valid file path.')
|
891
|
+
file.size_bytes = os.path.getsize(fs_path)
|
892
|
+
if file.mime_type is None:
|
893
|
+
file.mime_type, _ = mimetypes.guess_type(fs_path)
|
894
|
+
if file.mime_type is None:
|
895
|
+
raise ValueError(
|
896
|
+
'Unknown mime type: Could not determine the mimetype for your'
|
897
|
+
' file\n please set the `mime_type` argument'
|
898
|
+
)
|
863
899
|
response = {}
|
864
900
|
if config_model and config_model.http_options:
|
865
901
|
http_options = config_model.http_options
|
@@ -876,6 +912,7 @@ class Files(_common.BaseModule):
|
|
876
912
|
'response_payload': response,
|
877
913
|
}
|
878
914
|
self._create(file=file, config={'http_options': http_options})
|
915
|
+
|
879
916
|
if (
|
880
917
|
'headers' not in response
|
881
918
|
or 'X-Goog-Upload-URL' not in response['headers']
|
@@ -886,9 +923,14 @@ class Files(_common.BaseModule):
|
|
886
923
|
)
|
887
924
|
upload_url = response['headers']['X-Goog-Upload-URL']
|
888
925
|
|
889
|
-
|
890
|
-
|
891
|
-
|
926
|
+
if isinstance(path, io.IOBase):
|
927
|
+
return_file = self._api_client.upload_file(
|
928
|
+
path, upload_url, file.size_bytes
|
929
|
+
)
|
930
|
+
else:
|
931
|
+
return_file = self._api_client.upload_file(
|
932
|
+
fs_path, upload_url, file.size_bytes
|
933
|
+
)
|
892
934
|
|
893
935
|
return types.File._from_response(
|
894
936
|
_File_from_mldev(self._api_client, return_file['file']), None
|
@@ -904,6 +946,74 @@ class Files(_common.BaseModule):
|
|
904
946
|
config,
|
905
947
|
)
|
906
948
|
|
949
|
+
def download(
|
950
|
+
self,
|
951
|
+
*,
|
952
|
+
file: Union[str, types.File],
|
953
|
+
config: Optional[types.DownloadFileConfigOrDict] = None,
|
954
|
+
) -> bytes:
|
955
|
+
"""Downloads a file's data from storage.
|
956
|
+
|
957
|
+
Files created by `upload` can't be downloaded. You can tell which files are
|
958
|
+
downloadable by checking the `source` or `download_uri` property.
|
959
|
+
|
960
|
+
Args:
|
961
|
+
file (str): A file name, uri, or file object. Identifying which file to
|
962
|
+
download.
|
963
|
+
config (DownloadFileConfigOrDict): Optional, configuration for the get
|
964
|
+
method.
|
965
|
+
|
966
|
+
Returns:
|
967
|
+
File: The file data as bytes.
|
968
|
+
|
969
|
+
Usage:
|
970
|
+
|
971
|
+
.. code-block:: python
|
972
|
+
|
973
|
+
for file client.files.list():
|
974
|
+
if file.download_uri is not None:
|
975
|
+
break
|
976
|
+
else:
|
977
|
+
raise ValueError('No files found with a `download_uri`.')
|
978
|
+
data = client.files.download(file=file)
|
979
|
+
# data = client.files.download(file=file.name)
|
980
|
+
# data = client.files.download(file=file.download_uri)
|
981
|
+
"""
|
982
|
+
if self._api_client.vertexai:
|
983
|
+
raise ValueError(
|
984
|
+
'Vertex AI does not support the Files API. Use GCS files instead.'
|
985
|
+
)
|
986
|
+
|
987
|
+
config_model = None
|
988
|
+
if config:
|
989
|
+
if isinstance(config, dict):
|
990
|
+
config_model = types.DownloadFileConfig(**config)
|
991
|
+
else:
|
992
|
+
config_model = config
|
993
|
+
|
994
|
+
if isinstance(file, types.File) and file.download_uri is None:
|
995
|
+
raise ValueError(
|
996
|
+
"Only generated files can be downloaded, uploaded files can't be "
|
997
|
+
'downloaded. You can tell which files are downloadable by checking '
|
998
|
+
'the `source` or `download_uri` property.'
|
999
|
+
)
|
1000
|
+
name = t.t_file_name(self, file)
|
1001
|
+
|
1002
|
+
path = f'files/{name}:download'
|
1003
|
+
|
1004
|
+
query_params = {'alt': 'media'}
|
1005
|
+
path = f'{path}?{urlencode(query_params)}'
|
1006
|
+
http_options = None
|
1007
|
+
if getv(config_model, ['http_options']) is not None:
|
1008
|
+
http_options = getv(config_model, ['http_options'])
|
1009
|
+
|
1010
|
+
data = self._api_client.download_file(
|
1011
|
+
path,
|
1012
|
+
http_options,
|
1013
|
+
)
|
1014
|
+
|
1015
|
+
return data
|
1016
|
+
|
907
1017
|
|
908
1018
|
class AsyncFiles(_common.BaseModule):
|
909
1019
|
|
@@ -946,7 +1056,7 @@ class AsyncFiles(_common.BaseModule):
|
|
946
1056
|
config = request_dict.pop('config', None)
|
947
1057
|
http_options = config.pop('httpOptions', None) if config else None
|
948
1058
|
request_dict = _common.convert_to_dict(request_dict)
|
949
|
-
request_dict = _common.
|
1059
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
950
1060
|
|
951
1061
|
response_dict = await self._api_client.async_request(
|
952
1062
|
'get', path, request_dict, http_options
|
@@ -993,7 +1103,7 @@ class AsyncFiles(_common.BaseModule):
|
|
993
1103
|
config = request_dict.pop('config', None)
|
994
1104
|
http_options = config.pop('httpOptions', None) if config else None
|
995
1105
|
request_dict = _common.convert_to_dict(request_dict)
|
996
|
-
request_dict = _common.
|
1106
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
997
1107
|
|
998
1108
|
response_dict = await self._api_client.async_request(
|
999
1109
|
'post', path, request_dict, http_options
|
@@ -1054,7 +1164,7 @@ class AsyncFiles(_common.BaseModule):
|
|
1054
1164
|
config = request_dict.pop('config', None)
|
1055
1165
|
http_options = config.pop('httpOptions', None) if config else None
|
1056
1166
|
request_dict = _common.convert_to_dict(request_dict)
|
1057
|
-
request_dict = _common.
|
1167
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
1058
1168
|
|
1059
1169
|
response_dict = await self._api_client.async_request(
|
1060
1170
|
'get', path, request_dict, http_options
|
@@ -1108,7 +1218,7 @@ class AsyncFiles(_common.BaseModule):
|
|
1108
1218
|
config = request_dict.pop('config', None)
|
1109
1219
|
http_options = config.pop('httpOptions', None) if config else None
|
1110
1220
|
request_dict = _common.convert_to_dict(request_dict)
|
1111
|
-
request_dict = _common.
|
1221
|
+
request_dict = _common.encode_unserializable_types(request_dict)
|
1112
1222
|
|
1113
1223
|
response_dict = await self._api_client.async_request(
|
1114
1224
|
'delete', path, request_dict, http_options
|
@@ -1132,13 +1242,16 @@ class AsyncFiles(_common.BaseModule):
|
|
1132
1242
|
async def upload(
|
1133
1243
|
self,
|
1134
1244
|
*,
|
1135
|
-
path: str
|
1245
|
+
path: Union[str, pathlib.Path, os.PathLike, io.IOBase],
|
1136
1246
|
config: Optional[types.UploadFileConfigOrDict] = None,
|
1137
1247
|
) -> types.File:
|
1138
1248
|
"""Calls the API to upload a file asynchronously using a supported file service.
|
1139
1249
|
|
1140
1250
|
Args:
|
1141
|
-
path: The path
|
1251
|
+
path: The path to the file or an `IOBase` object to be uploaded. If it's
|
1252
|
+
an IOBase object, it must be opened in blocking mode and binary mode. In
|
1253
|
+
other words, do not use non-blocking mode or text mode. The given stream
|
1254
|
+
must be seekable, that is, it must be able to call seek() on 'path'.
|
1142
1255
|
config: Optional parameters to set `diplay_name`, `mime_type`, and `name`.
|
1143
1256
|
"""
|
1144
1257
|
if self._api_client.vertexai:
|
@@ -1162,17 +1275,32 @@ class AsyncFiles(_common.BaseModule):
|
|
1162
1275
|
if file.name is not None and not file.name.startswith('files/'):
|
1163
1276
|
file.name = f'files/{file.name}'
|
1164
1277
|
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
'
|
1174
|
-
|
1175
|
-
)
|
1278
|
+
if isinstance(path, io.IOBase):
|
1279
|
+
if file.mime_type is None:
|
1280
|
+
raise ValueError(
|
1281
|
+
'Unknown mime type: Could not determine the mimetype for your'
|
1282
|
+
' file\n please set the `mime_type` argument'
|
1283
|
+
)
|
1284
|
+
if hasattr(path, 'mode'):
|
1285
|
+
if 'b' not in path.mode:
|
1286
|
+
raise ValueError('The file must be opened in binary mode.')
|
1287
|
+
offset = path.tell()
|
1288
|
+
path.seek(0, os.SEEK_END)
|
1289
|
+
file.size_bytes = path.tell() - offset
|
1290
|
+
path.seek(offset, os.SEEK_SET)
|
1291
|
+
else:
|
1292
|
+
fs_path = os.fspath(path)
|
1293
|
+
if not fs_path or not os.path.isfile(fs_path):
|
1294
|
+
raise FileNotFoundError(f'{path} is not a valid file path.')
|
1295
|
+
file.size_bytes = os.path.getsize(fs_path)
|
1296
|
+
if file.mime_type is None:
|
1297
|
+
file.mime_type, _ = mimetypes.guess_type(fs_path)
|
1298
|
+
if file.mime_type is None:
|
1299
|
+
raise ValueError(
|
1300
|
+
'Unknown mime type: Could not determine the mimetype for your'
|
1301
|
+
' file\n please set the `mime_type` argument'
|
1302
|
+
)
|
1303
|
+
|
1176
1304
|
response = {}
|
1177
1305
|
if config_model and config_model.http_options:
|
1178
1306
|
http_options = config_model.http_options
|
@@ -1199,9 +1327,14 @@ class AsyncFiles(_common.BaseModule):
|
|
1199
1327
|
)
|
1200
1328
|
upload_url = response['headers']['X-Goog-Upload-URL']
|
1201
1329
|
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1330
|
+
if isinstance(path, io.IOBase):
|
1331
|
+
return_file = await self._api_client.async_upload_file(
|
1332
|
+
path, upload_url, file.size_bytes
|
1333
|
+
)
|
1334
|
+
else:
|
1335
|
+
return_file = await self._api_client.async_upload_file(
|
1336
|
+
fs_path, upload_url, file.size_bytes
|
1337
|
+
)
|
1205
1338
|
|
1206
1339
|
return types.File._from_response(
|
1207
1340
|
_File_from_mldev(self._api_client, return_file['file']), None
|
@@ -1216,3 +1349,69 @@ class AsyncFiles(_common.BaseModule):
|
|
1216
1349
|
await self._list(config=config),
|
1217
1350
|
config,
|
1218
1351
|
)
|
1352
|
+
|
1353
|
+
async def download(
|
1354
|
+
self,
|
1355
|
+
*,
|
1356
|
+
file: Union[str, types.File],
|
1357
|
+
config: Optional[types.DownloadFileConfigOrDict] = None,
|
1358
|
+
) -> bytes:
|
1359
|
+
"""Downloads a file's data from the file service.
|
1360
|
+
|
1361
|
+
The Vertex-AI implementation of the API foes not include the file service.
|
1362
|
+
|
1363
|
+
Files created by `upload` can't be downloaded. You can tell which files are
|
1364
|
+
downloadable by checking the `download_uri` property.
|
1365
|
+
|
1366
|
+
Args:
|
1367
|
+
File (str): A file name, uri, or file object. Identifying which file to
|
1368
|
+
download.
|
1369
|
+
config (DownloadFileConfigOrDict): Optional, configuration for the get
|
1370
|
+
method.
|
1371
|
+
|
1372
|
+
Returns:
|
1373
|
+
File: The file data as bytes.
|
1374
|
+
|
1375
|
+
Usage:
|
1376
|
+
|
1377
|
+
.. code-block:: python
|
1378
|
+
|
1379
|
+
for file client.files.list():
|
1380
|
+
if file.download_uri is not None:
|
1381
|
+
break
|
1382
|
+
else:
|
1383
|
+
raise ValueError('No files found with a `download_uri`.')
|
1384
|
+
data = client.files.download(file=file)
|
1385
|
+
# data = client.files.download(file=file.name)
|
1386
|
+
# data = client.files.download(file=file.uri)
|
1387
|
+
"""
|
1388
|
+
if self._api_client.vertexai:
|
1389
|
+
raise ValueError(
|
1390
|
+
'Vertex AI does not support the Files API. Use GCS files instead.'
|
1391
|
+
)
|
1392
|
+
|
1393
|
+
config_model = None
|
1394
|
+
if config:
|
1395
|
+
if isinstance(config, dict):
|
1396
|
+
config_model = types.DownloadFileConfig(**config)
|
1397
|
+
else:
|
1398
|
+
config_model = config
|
1399
|
+
|
1400
|
+
name = t.t_file_name(self, file)
|
1401
|
+
|
1402
|
+
path = f'files/{name}:download'
|
1403
|
+
|
1404
|
+
http_options = None
|
1405
|
+
if getv(config_model, ['http_options']) is not None:
|
1406
|
+
http_options = getv(config_model, ['http_options'])
|
1407
|
+
|
1408
|
+
query_params = {'alt': 'media'}
|
1409
|
+
if query_params:
|
1410
|
+
path = f'{path}?{urlencode(query_params)}'
|
1411
|
+
|
1412
|
+
data = await self._api_client.async_download_file(
|
1413
|
+
path,
|
1414
|
+
http_options,
|
1415
|
+
)
|
1416
|
+
|
1417
|
+
return data
|
google/genai/live.py
CHANGED
@@ -108,7 +108,7 @@ class AsyncSession:
|
|
108
108
|
|
109
109
|
The method will yield the model responses from the server. The returned
|
110
110
|
responses will represent a complete model turn. When the returned message
|
111
|
-
is
|
111
|
+
is function call, user must call `send` with the function response to
|
112
112
|
continue the turn.
|
113
113
|
|
114
114
|
Yields:
|
@@ -380,6 +380,10 @@ class AsyncSession:
|
|
380
380
|
isinstance(c, dict) and 'name' in c and 'response' in c for c in input
|
381
381
|
):
|
382
382
|
# ToolResponse.FunctionResponse
|
383
|
+
if not (self._api_client.vertexai):
|
384
|
+
for item in input:
|
385
|
+
if 'id' not in item:
|
386
|
+
raise ValueError(_FUNCTION_RESPONSE_REQUIRES_ID)
|
383
387
|
client_message = {'tool_response': {'function_responses': input}}
|
384
388
|
elif isinstance(input, Sequence) and any(isinstance(c, str) for c in input):
|
385
389
|
to_object = {}
|