google-genai 1.11.0__py3-none-any.whl → 1.12.1__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/types.py CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Google LLC
1
+ # Copyright 2025 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@ import logging
23
23
  import sys
24
24
  import types as builtin_types
25
25
  import typing
26
- from typing import Any, Callable, Literal, Optional, Union, _UnionGenericAlias # type: ignore
26
+ from typing import Any, Callable, Literal, Optional, Sequence, Union, _UnionGenericAlias # type: ignore
27
27
  import pydantic
28
28
  from pydantic import Field
29
29
  from typing_extensions import TypedDict
@@ -40,6 +40,7 @@ else:
40
40
 
41
41
  _is_pillow_image_imported = False
42
42
  if typing.TYPE_CHECKING:
43
+ from ._api_client import BaseApiClient
43
44
  import PIL.Image
44
45
 
45
46
  PIL_Image = PIL.Image.Image
@@ -139,6 +140,7 @@ class FinishReason(_common.CaseInSensitiveEnum):
139
140
  MAX_TOKENS = 'MAX_TOKENS'
140
141
  SAFETY = 'SAFETY'
141
142
  RECITATION = 'RECITATION'
143
+ LANGUAGE = 'LANGUAGE'
142
144
  OTHER = 'OTHER'
143
145
  BLOCKLIST = 'BLOCKLIST'
144
146
  PROHIBITED_CONTENT = 'PROHIBITED_CONTENT'
@@ -641,7 +643,22 @@ class Part(_common.BaseModel):
641
643
  )
642
644
 
643
645
  @classmethod
644
- def from_uri(cls, *, file_uri: str, mime_type: str) -> 'Part':
646
+ def from_uri(
647
+ cls, *, file_uri: str, mime_type: Optional[str] = None
648
+ ) -> 'Part':
649
+ """Creates a Part from a file uri.
650
+
651
+ Args:
652
+ file_uri (str): The uri of the file
653
+ mime_type (str): mime_type: The MIME type of the image. If not provided,
654
+ the MIME type will be automatically determined.
655
+ """
656
+ if mime_type is None:
657
+ import mimetypes
658
+
659
+ mime_type, _ = mimetypes.guess_type(file_uri)
660
+ if not mime_type:
661
+ raise ValueError(f'Failed to determine mime type for file: {file_uri}')
645
662
  file_data = FileData(file_uri=file_uri, mime_type=mime_type)
646
663
  return cls(file_data=file_data)
647
664
 
@@ -1172,6 +1189,288 @@ class Schema(_common.BaseModel):
1172
1189
 
1173
1190
  return convert_schema(self)
1174
1191
 
1192
+ @classmethod
1193
+ def from_json_schema(
1194
+ cls,
1195
+ *,
1196
+ json_schema: JSONSchema,
1197
+ api_option: Literal['VERTEX_AI', 'GEMINI_API'] = 'GEMINI_API',
1198
+ raise_error_on_unsupported_field: bool = False,
1199
+ ) -> 'Schema':
1200
+ """Converts a JSONSchema object to a Schema object.
1201
+
1202
+ The JSONSchema is compatible with 2020-12 JSON Schema draft, specified by
1203
+ OpenAPI 3.1.
1204
+
1205
+ Args:
1206
+ json_schema: JSONSchema object to be converted.
1207
+ api_option: API option to be used. If set to 'VERTEX_AI', the JSONSchema
1208
+ will be converted to a Schema object that is compatible with Vertex AI
1209
+ API. If set to 'GEMINI_API', the JSONSchema will be converted to a
1210
+ Schema object that is compatible with Gemini API. Default is
1211
+ 'GEMINI_API'.
1212
+ raise_error_on_unsupported_field: If set to True, an error will be
1213
+ raised if the JSONSchema contains any unsupported fields. Default is
1214
+ False.
1215
+
1216
+ Returns:
1217
+ Schema object that is compatible with the specified API option.
1218
+ Raises:
1219
+ ValueError: If the JSONSchema contains any unsupported fields and
1220
+ raise_error_on_unsupported_field is set to True. Or if the JSONSchema
1221
+ is not compatible with the specified API option.
1222
+ """
1223
+ google_schema_field_names: set[str] = set(cls.model_fields.keys())
1224
+ schema_field_names: tuple[str, ...] = (
1225
+ 'items',
1226
+ ) # 'additional_properties' to come
1227
+ list_schema_field_names: tuple[str, ...] = (
1228
+ 'any_of', # 'one_of', 'all_of', 'not' to come
1229
+ )
1230
+ dict_schema_field_names: tuple[str, ...] = ('properties',) # 'defs' to come
1231
+
1232
+ number_integer_related_field_names: tuple[str, ...] = (
1233
+ 'description',
1234
+ 'enum',
1235
+ 'format',
1236
+ 'maximum',
1237
+ 'minimum',
1238
+ 'title',
1239
+ )
1240
+ string_related_field_names: tuple[str, ...] = (
1241
+ 'description',
1242
+ 'enum',
1243
+ 'format',
1244
+ 'max_length',
1245
+ 'min_length',
1246
+ 'pattern',
1247
+ 'title',
1248
+ )
1249
+ object_related_field_names: tuple[str, ...] = (
1250
+ 'any_of',
1251
+ 'description',
1252
+ 'max_properties',
1253
+ 'min_properties',
1254
+ 'properties',
1255
+ 'required',
1256
+ 'title',
1257
+ )
1258
+ array_related_field_names: tuple[str, ...] = (
1259
+ 'description',
1260
+ 'items',
1261
+ 'max_items',
1262
+ 'min_items',
1263
+ 'title',
1264
+ )
1265
+ boolean_related_field_names: tuple[str, ...] = (
1266
+ 'description',
1267
+ 'title',
1268
+ )
1269
+ # placeholder for potential gemini api unsupported fields
1270
+ gemini_api_unsupported_field_names: tuple[str, ...] = ()
1271
+
1272
+ def normalize_json_schema_type(
1273
+ json_schema_type: Optional[
1274
+ Union[JSONSchemaType, Sequence[JSONSchemaType], str, Sequence[str]]
1275
+ ],
1276
+ ) -> tuple[list[str], bool]:
1277
+ """Returns (non_null_types, nullable)"""
1278
+ if json_schema_type is None:
1279
+ return [], False
1280
+ if isinstance(json_schema_type, str):
1281
+ if json_schema_type == JSONSchemaType.NULL.value:
1282
+ return [], True
1283
+ return [json_schema_type], False
1284
+ if isinstance(json_schema_type, JSONSchemaType):
1285
+ if json_schema_type == JSONSchemaType.NULL:
1286
+ return [], True
1287
+ return [json_schema_type.value], False
1288
+ non_null_types = []
1289
+ nullable = False
1290
+ for type_value in json_schema_type:
1291
+ if isinstance(type_value, JSONSchemaType):
1292
+ type_value = type_value.value
1293
+ if type_value == JSONSchemaType.NULL.value:
1294
+ nullable = True
1295
+ else:
1296
+ non_null_types.append(type_value)
1297
+ return non_null_types, nullable
1298
+
1299
+ def raise_error_if_cannot_convert(
1300
+ json_schema_dict: dict[str, Any],
1301
+ api_option: Literal['VERTEX_AI', 'GEMINI_API'],
1302
+ raise_error_on_unsupported_field: bool,
1303
+ ) -> None:
1304
+ """Raises an error if the JSONSchema cannot be converted to the specified Schema object."""
1305
+ if not raise_error_on_unsupported_field:
1306
+ return
1307
+ for field_name, field_value in json_schema_dict.items():
1308
+ if field_value is None:
1309
+ continue
1310
+ if field_name not in google_schema_field_names:
1311
+ raise ValueError((
1312
+ f'JSONSchema field "{field_name}" is not supported by the '
1313
+ 'Schema object. And the "raise_error_on_unsupported_field" '
1314
+ 'argument is set to True. If you still want to convert '
1315
+ 'it into the Schema object, please either remove the field '
1316
+ f'"{field_name}" from the JSONSchema object, or leave the '
1317
+ '"raise_error_on_unsupported_field" unset.'
1318
+ ))
1319
+ if (
1320
+ field_name in gemini_api_unsupported_field_names
1321
+ and api_option == 'GEMINI_API'
1322
+ ):
1323
+ raise ValueError((
1324
+ f'The "{field_name}" field is not supported by the Schema '
1325
+ 'object for GEMINI_API.'
1326
+ ))
1327
+
1328
+ def copy_schema_fields(
1329
+ json_schema_dict: dict[str, Any],
1330
+ related_fields_to_copy: tuple[str, ...],
1331
+ sub_schema_in_any_of: dict[str, Any],
1332
+ ) -> None:
1333
+ """Copies the fields from json_schema_dict to sub_schema_in_any_of."""
1334
+ for field_name in related_fields_to_copy:
1335
+ sub_schema_in_any_of[field_name] = json_schema_dict.get(
1336
+ field_name, None
1337
+ )
1338
+
1339
+ def convert_json_schema(
1340
+ json_schema: JSONSchema,
1341
+ api_option: Literal['VERTEX_AI', 'GEMINI_API'],
1342
+ raise_error_on_unsupported_field: bool,
1343
+ ) -> 'Schema':
1344
+ schema = Schema()
1345
+ json_schema_dict = json_schema.model_dump()
1346
+ raise_error_if_cannot_convert(
1347
+ json_schema_dict=json_schema_dict,
1348
+ api_option=api_option,
1349
+ raise_error_on_unsupported_field=raise_error_on_unsupported_field,
1350
+ )
1351
+
1352
+ # At the highest level of the logic, there are two passes:
1353
+ # Pass 1: the JSONSchema.type is union-like,
1354
+ # e.g. ['null', 'string', 'array'].
1355
+ # for this case, we need to split the JSONSchema into multiple
1356
+ # sub-schemas, and copy them into the any_of field of the Schema.
1357
+ # And when we copy the non-type fields into any_of field,
1358
+ # we only copy the fields related to the specific type.
1359
+ # Detailed logic is commented below with `Pass 1` keyword tag.
1360
+ # Pass 2: the JSONSchema.type is not union-like,
1361
+ # e.g. 'string', ['string'], ['null', 'string'].
1362
+ # for this case, no splitting is needed. Detailed
1363
+ # logic is commented below with `Pass 2` keyword tag.
1364
+ #
1365
+ #
1366
+ # Pass 1: the JSONSchema.type is union-like
1367
+ # e.g. ['null', 'string', 'array'].
1368
+ non_null_types, nullable = normalize_json_schema_type(
1369
+ json_schema_dict.get('type', None)
1370
+ )
1371
+ if len(non_null_types) > 1:
1372
+ logger.warning(
1373
+ 'JSONSchema type is union-like, e.g. ["null", "string", "array"]. '
1374
+ 'Converting it into multiple sub-schemas, and copying them into '
1375
+ 'the any_of field of the Schema. The value of `default` field is '
1376
+ 'ignored because it is ambiguous to tell which sub-schema it '
1377
+ 'belongs to.'
1378
+ )
1379
+ reformed_json_schema = JSONSchema()
1380
+ # start splitting the JSONSchema into multiple sub-schemas
1381
+ any_of = []
1382
+ if nullable:
1383
+ schema.nullable = True
1384
+ for normalized_type in non_null_types:
1385
+ sub_schema_in_any_of = {'type': normalized_type}
1386
+ if normalized_type == JSONSchemaType.BOOLEAN.value:
1387
+ copy_schema_fields(
1388
+ json_schema_dict=json_schema_dict,
1389
+ related_fields_to_copy=boolean_related_field_names,
1390
+ sub_schema_in_any_of=sub_schema_in_any_of,
1391
+ )
1392
+ elif normalized_type in (
1393
+ JSONSchemaType.NUMBER.value,
1394
+ JSONSchemaType.INTEGER.value,
1395
+ ):
1396
+ copy_schema_fields(
1397
+ json_schema_dict=json_schema_dict,
1398
+ related_fields_to_copy=number_integer_related_field_names,
1399
+ sub_schema_in_any_of=sub_schema_in_any_of,
1400
+ )
1401
+ elif normalized_type == JSONSchemaType.STRING.value:
1402
+ copy_schema_fields(
1403
+ json_schema_dict=json_schema_dict,
1404
+ related_fields_to_copy=string_related_field_names,
1405
+ sub_schema_in_any_of=sub_schema_in_any_of,
1406
+ )
1407
+ elif normalized_type == JSONSchemaType.ARRAY.value:
1408
+ copy_schema_fields(
1409
+ json_schema_dict=json_schema_dict,
1410
+ related_fields_to_copy=array_related_field_names,
1411
+ sub_schema_in_any_of=sub_schema_in_any_of,
1412
+ )
1413
+ elif normalized_type == JSONSchemaType.OBJECT.value:
1414
+ copy_schema_fields(
1415
+ json_schema_dict=json_schema_dict,
1416
+ related_fields_to_copy=object_related_field_names,
1417
+ sub_schema_in_any_of=sub_schema_in_any_of,
1418
+ )
1419
+ any_of.append(JSONSchema(**sub_schema_in_any_of))
1420
+ reformed_json_schema.any_of = any_of
1421
+ json_schema_dict = reformed_json_schema.model_dump()
1422
+
1423
+ # Pass 2: the JSONSchema.type is not union-like,
1424
+ # e.g. 'string', ['string'], ['null', 'string'].
1425
+ for field_name, field_value in json_schema_dict.items():
1426
+ if field_value is None:
1427
+ continue
1428
+ if field_name in schema_field_names:
1429
+ schema_field_value: 'Schema' = convert_json_schema(
1430
+ json_schema=JSONSchema(**field_value),
1431
+ api_option=api_option,
1432
+ raise_error_on_unsupported_field=raise_error_on_unsupported_field,
1433
+ )
1434
+ setattr(schema, field_name, schema_field_value)
1435
+ elif field_name in list_schema_field_names:
1436
+ list_schema_field_value: list['Schema'] = [
1437
+ convert_json_schema(
1438
+ json_schema=JSONSchema(**this_field_value),
1439
+ api_option=api_option,
1440
+ raise_error_on_unsupported_field=raise_error_on_unsupported_field,
1441
+ )
1442
+ for this_field_value in field_value
1443
+ ]
1444
+ setattr(schema, field_name, list_schema_field_value)
1445
+ elif field_name in dict_schema_field_names:
1446
+ dict_schema_field_value: dict[str, 'Schema'] = {
1447
+ key: convert_json_schema(
1448
+ json_schema=JSONSchema(**value),
1449
+ api_option=api_option,
1450
+ raise_error_on_unsupported_field=raise_error_on_unsupported_field,
1451
+ )
1452
+ for key, value in field_value.items()
1453
+ }
1454
+ setattr(schema, field_name, dict_schema_field_value)
1455
+ elif field_name == 'type':
1456
+ # non_null_types can only be empty or have one element.
1457
+ # because already handled union-like case above.
1458
+ non_null_types, nullable = normalize_json_schema_type(field_value)
1459
+ if nullable:
1460
+ schema.nullable = True
1461
+ if non_null_types:
1462
+ schema.type = Type(non_null_types[0])
1463
+ else:
1464
+ setattr(schema, field_name, field_value)
1465
+
1466
+ return schema
1467
+
1468
+ return convert_json_schema(
1469
+ json_schema=json_schema,
1470
+ api_option=api_option,
1471
+ raise_error_on_unsupported_field=raise_error_on_unsupported_field,
1472
+ )
1473
+
1175
1474
 
1176
1475
  class SchemaDict(TypedDict, total=False):
1177
1476
  """Schema that defines the format of input and output data.
@@ -1331,7 +1630,7 @@ class FunctionDeclaration(_common.BaseModel):
1331
1630
  def from_callable_with_api_option(
1332
1631
  cls,
1333
1632
  *,
1334
- callable: Callable,
1633
+ callable: Callable[..., Any],
1335
1634
  api_option: Literal['VERTEX_AI', 'GEMINI_API'] = 'GEMINI_API',
1336
1635
  ) -> 'FunctionDeclaration':
1337
1636
  """Converts a Callable to a FunctionDeclaration based on the API option.
@@ -1397,8 +1696,8 @@ class FunctionDeclaration(_common.BaseModel):
1397
1696
  def from_callable(
1398
1697
  cls,
1399
1698
  *,
1400
- client,
1401
- callable: Callable,
1699
+ client: 'BaseApiClient',
1700
+ callable: Callable[..., Any],
1402
1701
  ) -> 'FunctionDeclaration':
1403
1702
  """Converts a Callable to a FunctionDeclaration based on the client."""
1404
1703
  if client.vertexai:
@@ -1873,11 +2172,11 @@ class ToolDict(TypedDict, total=False):
1873
2172
 
1874
2173
 
1875
2174
  ToolOrDict = Union[Tool, ToolDict]
1876
- ToolListUnion = list[Union[Tool, Callable]]
1877
- ToolListUnionDict = list[Union[ToolDict, Callable]]
2175
+ ToolListUnion = list[Union[Tool, Callable[..., Any]]]
2176
+ ToolListUnionDict = list[Union[ToolDict, Callable[..., Any]]]
1878
2177
 
1879
2178
  SchemaUnion = Union[
1880
- dict, type, Schema, builtin_types.GenericAlias, VersionedUnionType # type: ignore[valid-type]
2179
+ dict[Any, Any], type, Schema, builtin_types.GenericAlias, VersionedUnionType # type: ignore[valid-type]
1881
2180
  ]
1882
2181
  SchemaUnionDict = Union[SchemaUnion, SchemaDict]
1883
2182
 
@@ -2497,7 +2796,7 @@ class GenerateContentConfig(_common.BaseModel):
2497
2796
 
2498
2797
  @pydantic.field_validator('response_schema', mode='before')
2499
2798
  @classmethod
2500
- def _convert_literal_to_enum(cls, value):
2799
+ def _convert_literal_to_enum(cls, value: Any) -> Union[Any, EnumMeta]:
2501
2800
  if typing.get_origin(value) is typing.Literal:
2502
2801
  enum_vals = typing.get_args(value)
2503
2802
  if not all(isinstance(arg, str) for arg in enum_vals):
@@ -3490,7 +3789,7 @@ class GenerateContentResponse(_common.BaseModel):
3490
3789
  default=None, description="""Usage metadata about the response(s)."""
3491
3790
  )
3492
3791
  automatic_function_calling_history: Optional[list[Content]] = None
3493
- parsed: Optional[Union[pydantic.BaseModel, dict, Enum]] = Field(
3792
+ parsed: Optional[Union[pydantic.BaseModel, dict[Any, Any], Enum]] = Field(
3494
3793
  default=None,
3495
3794
  description="""First candidate from the parsed response if response_schema is provided. Not available for streaming.""",
3496
3795
  )
@@ -4210,7 +4509,7 @@ class Image(_common.BaseModel):
4210
4509
  default=None, description="""The MIME type of the image."""
4211
4510
  )
4212
4511
 
4213
- _loaded_image = None
4512
+ _loaded_image: Optional['PIL_Image'] = None
4214
4513
 
4215
4514
  """Image."""
4216
4515
 
@@ -4256,7 +4555,7 @@ class Image(_common.BaseModel):
4256
4555
  image = cls(image_bytes=image_bytes, mime_type=mime_type)
4257
4556
  return image
4258
4557
 
4259
- def show(self):
4558
+ def show(self) -> None:
4260
4559
  """Shows the image.
4261
4560
 
4262
4561
  This method only works in a notebook environment.
@@ -4270,7 +4569,7 @@ class Image(_common.BaseModel):
4270
4569
  IPython_display.display(self._pil_image)
4271
4570
 
4272
4571
  @property
4273
- def _pil_image(self) -> 'PIL_Image':
4572
+ def _pil_image(self) -> Optional['PIL_Image']:
4274
4573
  PIL_Image: Optional[builtin_types.ModuleType]
4275
4574
  try:
4276
4575
  from PIL import Image as PIL_Image
@@ -4289,7 +4588,7 @@ class Image(_common.BaseModel):
4289
4588
  self._loaded_image = PIL_Image.open(io.BytesIO(self.image_bytes))
4290
4589
  return self._loaded_image
4291
4590
 
4292
- def save(self, location: str):
4591
+ def save(self, location: str) -> None:
4293
4592
  """Saves the image to a file.
4294
4593
 
4295
4594
  Args:
@@ -5840,7 +6139,7 @@ class Video(_common.BaseModel):
5840
6139
 
5841
6140
  pathlib.Path(path).write_bytes(self.video_bytes)
5842
6141
 
5843
- def show(self):
6142
+ def show(self) -> None:
5844
6143
  """Shows the video.
5845
6144
 
5846
6145
  If the video has no mime_type, it is assumed to be video/mp4.
@@ -5848,9 +6147,9 @@ class Video(_common.BaseModel):
5848
6147
  This method only works in a notebook environment.
5849
6148
  """
5850
6149
  if self.uri and not self.video_bytes:
5851
- return ValueError('Showing remote videos is not supported.')
6150
+ raise ValueError('Showing remote videos is not supported.')
5852
6151
  if not self.video_bytes:
5853
- return ValueError('Video has no bytes.')
6152
+ raise ValueError('Video has no bytes.')
5854
6153
 
5855
6154
  mime_type = self.mime_type or 'video/mp4'
5856
6155
 
@@ -5866,7 +6165,7 @@ class Video(_common.BaseModel):
5866
6165
  )
5867
6166
  )
5868
6167
 
5869
- def __repr__(self):
6168
+ def __repr__(self) -> str:
5870
6169
  video_bytes = '<video_bytes>' if self.video_bytes else 'None'
5871
6170
  return (
5872
6171
  f'Video(uri={self.uri}, video_bytes={video_bytes},'
@@ -8930,7 +9229,7 @@ class RawReferenceImage(_common.BaseModel):
8930
9229
 
8931
9230
  @pydantic.model_validator(mode='before')
8932
9231
  @classmethod
8933
- def _validate_mask_image_config(self, values):
9232
+ def _validate_mask_image_config(self, values: Any) -> Any:
8934
9233
  if 'reference_type' in values:
8935
9234
  raise ValueError('Cannot set internal reference_type field directly.')
8936
9235
  values['reference_type'] = 'REFERENCE_TYPE_RAW'
@@ -8992,7 +9291,7 @@ class MaskReferenceImage(_common.BaseModel):
8992
9291
 
8993
9292
  @pydantic.model_validator(mode='before')
8994
9293
  @classmethod
8995
- def _validate_mask_image_config(self, values):
9294
+ def _validate_mask_image_config(self, values: Any) -> Any:
8996
9295
  config = values.get('config', None)
8997
9296
  values['mask_image_config'] = config
8998
9297
  if 'reference_type' in values:
@@ -9063,7 +9362,7 @@ class ControlReferenceImage(_common.BaseModel):
9063
9362
 
9064
9363
  @pydantic.model_validator(mode='before')
9065
9364
  @classmethod
9066
- def _validate_mask_image_config(self, values):
9365
+ def _validate_mask_image_config(self, values: Any) -> Any:
9067
9366
  config = values.get('config', None)
9068
9367
  values['control_image_config'] = config
9069
9368
  if 'reference_type' in values:
@@ -9134,7 +9433,7 @@ class StyleReferenceImage(_common.BaseModel):
9134
9433
 
9135
9434
  @pydantic.model_validator(mode='before')
9136
9435
  @classmethod
9137
- def _validate_mask_image_config(self, values):
9436
+ def _validate_mask_image_config(self, values: Any) -> Any:
9138
9437
  config = values.get('config', None)
9139
9438
  values['style_image_config'] = config
9140
9439
  if 'reference_type' in values:
@@ -9201,7 +9500,7 @@ class SubjectReferenceImage(_common.BaseModel):
9201
9500
 
9202
9501
  @pydantic.model_validator(mode='before')
9203
9502
  @classmethod
9204
- def _validate_mask_image_config(self, values):
9503
+ def _validate_mask_image_config(self, values: Any) -> Any:
9205
9504
  config = values.get('config', None)
9206
9505
  values['subject_image_config'] = config
9207
9506
  if 'reference_type' in values:
@@ -10079,6 +10378,33 @@ class LiveClientRealtimeInput(_common.BaseModel):
10079
10378
  media_chunks: Optional[list[Blob]] = Field(
10080
10379
  default=None, description="""Inlined bytes data for media input."""
10081
10380
  )
10381
+ audio: Optional[Blob] = Field(
10382
+ default=None, description="""The realtime audio input stream."""
10383
+ )
10384
+ audio_stream_end: Optional[bool] = Field(
10385
+ default=None,
10386
+ description="""
10387
+ Indicates that the audio stream has ended, e.g. because the microphone was
10388
+ turned off.
10389
+
10390
+ This should only be sent when automatic activity detection is enabled
10391
+ (which is the default).
10392
+
10393
+ The client can reopen the stream by sending an audio message.
10394
+ """,
10395
+ )
10396
+ video: Optional[Blob] = Field(
10397
+ default=None, description="""The realtime video input stream."""
10398
+ )
10399
+ text: Optional[str] = Field(
10400
+ default=None, description="""The realtime text input stream."""
10401
+ )
10402
+ activity_start: Optional[ActivityStart] = Field(
10403
+ default=None, description="""Marks the start of user activity."""
10404
+ )
10405
+ activity_end: Optional[ActivityEnd] = Field(
10406
+ default=None, description="""Marks the end of user activity."""
10407
+ )
10082
10408
 
10083
10409
 
10084
10410
  class LiveClientRealtimeInputDict(TypedDict, total=False):
@@ -10101,6 +10427,32 @@ class LiveClientRealtimeInputDict(TypedDict, total=False):
10101
10427
  media_chunks: Optional[list[BlobDict]]
10102
10428
  """Inlined bytes data for media input."""
10103
10429
 
10430
+ audio: Optional[BlobDict]
10431
+ """The realtime audio input stream."""
10432
+
10433
+ audio_stream_end: Optional[bool]
10434
+ """
10435
+ Indicates that the audio stream has ended, e.g. because the microphone was
10436
+ turned off.
10437
+
10438
+ This should only be sent when automatic activity detection is enabled
10439
+ (which is the default).
10440
+
10441
+ The client can reopen the stream by sending an audio message.
10442
+ """
10443
+
10444
+ video: Optional[BlobDict]
10445
+ """The realtime video input stream."""
10446
+
10447
+ text: Optional[str]
10448
+ """The realtime text input stream."""
10449
+
10450
+ activity_start: Optional[ActivityStartDict]
10451
+ """Marks the start of user activity."""
10452
+
10453
+ activity_end: Optional[ActivityEndDict]
10454
+ """Marks the end of user activity."""
10455
+
10104
10456
 
10105
10457
  LiveClientRealtimeInputOrDict = Union[
10106
10458
  LiveClientRealtimeInput, LiveClientRealtimeInputDict
@@ -10404,3 +10756,83 @@ class LiveConnectParametersDict(TypedDict, total=False):
10404
10756
  LiveConnectParametersOrDict = Union[
10405
10757
  LiveConnectParameters, LiveConnectParametersDict
10406
10758
  ]
10759
+
10760
+ if _is_pillow_image_imported:
10761
+ BlobImageUnion = Union[Blob, PIL_Image]
10762
+ else:
10763
+ BlobImageUnion = Blob # type: ignore[misc]
10764
+
10765
+ BlobImageUnionDict = Union[BlobImageUnion, BlobDict]
10766
+
10767
+
10768
+ class LiveSendRealtimeInputParameters(_common.BaseModel):
10769
+ """Parameters for sending realtime input to the live API."""
10770
+
10771
+ media: Optional[BlobImageUnion] = Field(
10772
+ default=None, description="""Realtime input to send to the session."""
10773
+ )
10774
+ audio: Optional[Blob] = Field(
10775
+ default=None, description="""The realtime audio input stream."""
10776
+ )
10777
+ audio_stream_end: Optional[bool] = Field(
10778
+ default=None,
10779
+ description="""
10780
+ Indicates that the audio stream has ended, e.g. because the microphone was
10781
+ turned off.
10782
+
10783
+ This should only be sent when automatic activity detection is enabled
10784
+ (which is the default).
10785
+
10786
+ The client can reopen the stream by sending an audio message.
10787
+ """,
10788
+ )
10789
+ video: Optional[BlobImageUnion] = Field(
10790
+ default=None, description="""The realtime video input stream."""
10791
+ )
10792
+ text: Optional[str] = Field(
10793
+ default=None, description="""The realtime text input stream."""
10794
+ )
10795
+ activity_start: Optional[ActivityStart] = Field(
10796
+ default=None, description="""Marks the start of user activity."""
10797
+ )
10798
+ activity_end: Optional[ActivityEnd] = Field(
10799
+ default=None, description="""Marks the end of user activity."""
10800
+ )
10801
+
10802
+
10803
+ class LiveSendRealtimeInputParametersDict(TypedDict, total=False):
10804
+ """Parameters for sending realtime input to the live API."""
10805
+
10806
+ media: Optional[BlobImageUnionDict]
10807
+ """Realtime input to send to the session."""
10808
+
10809
+ audio: Optional[BlobDict]
10810
+ """The realtime audio input stream."""
10811
+
10812
+ audio_stream_end: Optional[bool]
10813
+ """
10814
+ Indicates that the audio stream has ended, e.g. because the microphone was
10815
+ turned off.
10816
+
10817
+ This should only be sent when automatic activity detection is enabled
10818
+ (which is the default).
10819
+
10820
+ The client can reopen the stream by sending an audio message.
10821
+ """
10822
+
10823
+ video: Optional[BlobImageUnionDict]
10824
+ """The realtime video input stream."""
10825
+
10826
+ text: Optional[str]
10827
+ """The realtime text input stream."""
10828
+
10829
+ activity_start: Optional[ActivityStartDict]
10830
+ """Marks the start of user activity."""
10831
+
10832
+ activity_end: Optional[ActivityEndDict]
10833
+ """Marks the end of user activity."""
10834
+
10835
+
10836
+ LiveSendRealtimeInputParametersOrDict = Union[
10837
+ LiveSendRealtimeInputParameters, LiveSendRealtimeInputParametersDict
10838
+ ]
google/genai/version.py CHANGED
@@ -13,4 +13,4 @@
13
13
  # limitations under the License.
14
14
  #
15
15
 
16
- __version__ = '1.11.0' # x-release-please-version
16
+ __version__ = '1.12.1' # x-release-please-version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-genai
3
- Version: 1.11.0
3
+ Version: 1.12.1
4
4
  Summary: GenAI Python SDK
5
5
  Author-email: Google LLC <googleapis-packages@google.com>
6
6
  License: Apache-2.0