google-genai 1.8.0__py3-none-any.whl → 1.9.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.
@@ -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.
@@ -26,7 +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 # type: ignore[attr-defined]
29
+ from typing import Any, GenericAlias, Optional, Sequence, Union # type: ignore[attr-defined]
30
30
 
31
31
  if typing.TYPE_CHECKING:
32
32
  import PIL.Image
@@ -251,6 +251,62 @@ def pil_to_blob(img) -> types.Blob:
251
251
  return types.Blob(mime_type=mime_type, data=data)
252
252
 
253
253
 
254
+ def t_function_response(
255
+ function_response: types.FunctionResponseOrDict,
256
+ ) -> types.FunctionResponse:
257
+ if not function_response:
258
+ raise ValueError('function_response is required.')
259
+ if isinstance(function_response, dict):
260
+ return types.FunctionResponse.model_validate(function_response)
261
+ elif isinstance(function_response, types.FunctionResponse):
262
+ return function_response
263
+ else:
264
+ raise TypeError(
265
+ f'Could not parse input as FunctionResponse. Unsupported'
266
+ f' function_response type: {type(function_response)}'
267
+ )
268
+
269
+ def t_function_responses(
270
+ function_responses: Union[
271
+ types.FunctionResponseOrDict,
272
+ Sequence[types.FunctionResponseOrDict],
273
+ ],
274
+ ) -> list[types.FunctionResponse]:
275
+ if not function_responses:
276
+ raise ValueError('function_responses are required.')
277
+ if isinstance(function_responses, Sequence):
278
+ return [t_function_response(response) for response in function_responses]
279
+ else:
280
+ return [t_function_response(function_responses)]
281
+
282
+
283
+ BlobUnion = Union[types.Blob, types.BlobDict, 'PIL.Image.Image']
284
+
285
+ def t_blob(blob: BlobUnion) -> types.Blob:
286
+ try:
287
+ import PIL.Image
288
+
289
+ PIL_Image = PIL.Image.Image
290
+ except ImportError:
291
+ PIL_Image = None
292
+
293
+ if not blob:
294
+ raise ValueError('blob is required.')
295
+
296
+ if isinstance(blob, types.Blob):
297
+ return blob
298
+
299
+ if isinstance(blob, dict):
300
+ return types.Blob.model_validate(blob)
301
+
302
+ if PIL_Image is not None and isinstance(blob, PIL_Image):
303
+ return pil_to_blob(blob)
304
+
305
+ raise TypeError(
306
+ f'Could not parse input as Blob. Unsupported blob type: {type(blob)}'
307
+ )
308
+
309
+
254
310
  def t_part(part: Optional[types.PartUnionDict]) -> types.Part:
255
311
  try:
256
312
  import PIL.Image
google/genai/batches.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.
google/genai/caches.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.
google/genai/errors.py CHANGED
@@ -36,7 +36,7 @@ class APIError(Exception):
36
36
  self,
37
37
  code: int,
38
38
  response_json: Any,
39
- response: Union['ReplayResponse', httpx.Response],
39
+ response: Optional[Union['ReplayResponse', httpx.Response]] = None,
40
40
  ):
41
41
  self.response = response
42
42
  self.details = response_json
google/genai/files.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.
google/genai/live.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.
@@ -21,6 +21,7 @@ import contextlib
21
21
  import json
22
22
  import logging
23
23
  from typing import Any, AsyncIterator, Dict, Optional, Sequence, Union, get_args
24
+ import warnings
24
25
 
25
26
  import google.auth
26
27
  import pydantic
@@ -30,7 +31,6 @@ from . import _api_module
30
31
  from . import _common
31
32
  from . import _transformers as t
32
33
  from . import client
33
- from . import errors
34
34
  from . import types
35
35
  from ._api_client import BaseApiClient
36
36
  from ._common import experimental_warning
@@ -65,6 +65,59 @@ _FUNCTION_RESPONSE_REQUIRES_ID = (
65
65
  )
66
66
 
67
67
 
68
+ def _ClientContent_to_mldev(
69
+ api_client: BaseApiClient,
70
+ from_object: types.LiveClientContent,
71
+ ) -> dict:
72
+ client_content = from_object.model_dump(exclude_none=True, mode='json')
73
+ if 'turns' in client_content:
74
+ client_content['turns'] = [
75
+ _Content_to_mldev(api_client=api_client, from_object=item)
76
+ for item in client_content['turns']
77
+ ]
78
+ return client_content
79
+
80
+
81
+ def _ClientContent_to_vertex(
82
+ api_client: BaseApiClient,
83
+ from_object: types.LiveClientContent,
84
+ ) -> dict:
85
+ client_content = from_object.model_dump(exclude_none=True, mode='json')
86
+ if 'turns' in client_content:
87
+ client_content['turns'] = [
88
+ _Content_to_vertex(api_client=api_client, from_object=item)
89
+ for item in client_content['turns']
90
+ ]
91
+ return client_content
92
+
93
+
94
+ def _ToolResponse_to_mldev(
95
+ api_client: BaseApiClient,
96
+ from_object: types.LiveClientToolResponse,
97
+ ) -> dict:
98
+ tool_response = from_object.model_dump(exclude_none=True, mode='json')
99
+ for response in tool_response.get('function_responses', []):
100
+ if response.get('id') is None:
101
+ raise ValueError(_FUNCTION_RESPONSE_REQUIRES_ID)
102
+ return tool_response
103
+
104
+
105
+ def _ToolResponse_to_vertex(
106
+ api_client: BaseApiClient,
107
+ from_object: types.LiveClientToolResponse,
108
+ ) -> dict:
109
+ tool_response = from_object.model_dump(exclude_none=True, mode='json')
110
+ return tool_response
111
+
112
+
113
+ def _AudioTranscriptionConfig_to_vertex(
114
+ api_client: BaseApiClient,
115
+ from_object: types.AudioTranscriptionConfig,
116
+ ) -> dict:
117
+ audio_transcription: dict[str, Any] = {}
118
+ return audio_transcription
119
+
120
+
68
121
  class AsyncSession:
69
122
  """AsyncSession. The live module is experimental."""
70
123
 
@@ -112,6 +165,208 @@ class AsyncSession:
112
165
  client_message = self._parse_client_message(input, end_of_turn)
113
166
  await self._ws.send(json.dumps(client_message))
114
167
 
168
+ async def send_client_content(
169
+ self,
170
+ *,
171
+ turns: Optional[
172
+ Union[
173
+ types.Content,
174
+ types.ContentDict,
175
+ list[Union[types.Content, types.ContentDict]]
176
+ ]
177
+ ] = None,
178
+ turn_complete: bool = True,
179
+ ):
180
+ """Send non-realtime, turn based content to the model.
181
+
182
+ There are two ways to send messages to the live API:
183
+ `send_client_content` and `send_realtime_input`.
184
+
185
+ `send_client_content` messages are added to the model context **in order**.
186
+ Having a conversation using `send_client_content` messages is roughly
187
+ equivalent to using the `Chat.send_message_stream` method, except that the
188
+ state of the `chat` history is stored on the API server.
189
+
190
+ Because of `send_client_content`'s order guarantee, the model cannot
191
+ respond as quickly to `send_client_content` messages as to
192
+ `send_realtime_input` messages. This makes the biggest difference when
193
+ sending objects that have significant preprocessing time (typically images).
194
+
195
+ The `send_client_content` message sends a list of `Content` objects,
196
+ which has more options than the `media:Blob` sent by `send_realtime_input`.
197
+
198
+ The main use-cases for `send_client_content` over `send_realtime_input` are:
199
+
200
+ - Prefilling a conversation context (including sending anything that can't
201
+ be represented as a realtime message), before starting a realtime
202
+ conversation.
203
+ - Conducting a non-realtime conversation, similar to `client.chat`, using
204
+ the live api.
205
+
206
+ Caution: Interleaving `send_client_content` and `send_realtime_input`
207
+ in the same conversation is not recommended and can lead to unexpected
208
+ results.
209
+
210
+ Args:
211
+ turns: A `Content` object or list of `Content` objects (or equivalent
212
+ dicts).
213
+ turn_complete: if true (the default) the model will reply immediately. If
214
+ false, the model will wait for you to send additional client_content,
215
+ and will not return until you send `turn_complete=True`.
216
+
217
+ Example:
218
+ ```
219
+ import google.genai
220
+ from google.genai import types
221
+
222
+ client = genai.Client(http_options={'api_version': 'v1alpha'})
223
+ async with client.aio.live.connect(
224
+ model=MODEL_NAME,
225
+ config={"response_modalities": ["TEXT"]}
226
+ ) as session:
227
+ await session.send_client_content(
228
+ turns=types.Content(
229
+ role='user',
230
+ parts=[types.Part(text="Hello world!")]))
231
+ async for msg in session.receive():
232
+ if msg.text:
233
+ print(msg.text)
234
+ ```
235
+ """
236
+ client_content = _t_client_content(turns, turn_complete)
237
+
238
+ if self._api_client.vertexai:
239
+ client_content_dict = _ClientContent_to_vertex(
240
+ api_client=self._api_client, from_object=client_content
241
+ )
242
+ else:
243
+ client_content_dict = _ClientContent_to_mldev(
244
+ api_client=self._api_client, from_object=client_content
245
+ )
246
+
247
+ await self._ws.send(json.dumps({'client_content': client_content_dict}))
248
+
249
+ async def send_realtime_input(self, *, media: t.BlobUnion):
250
+ """Send realtime media chunks to the model.
251
+
252
+ Use `send_realtime_input` for realtime audio chunks and video
253
+ frames(images).
254
+
255
+ With `send_realtime_input` the api will respond to audio automatically
256
+ based on voice activity detection (VAD).
257
+
258
+ `send_realtime_input` is optimized for responsivness at the expense of
259
+ deterministic ordering. Audio and video tokens are added to the
260
+ context when they become available.
261
+
262
+ Args:
263
+ media: A `Blob`-like object, the realtime media to send.
264
+
265
+ Example:
266
+ ```
267
+ from pathlib import Path
268
+
269
+ from google import genai
270
+ from google.genai import types
271
+
272
+ import PIL.Image
273
+
274
+ client = genai.Client(http_options= {'api_version': 'v1alpha'})
275
+
276
+ async with client.aio.live.connect(
277
+ model=MODEL_NAME,
278
+ config={"response_modalities": ["TEXT"]},
279
+ ) as session:
280
+ await session.send_realtime_input(
281
+ media=PIL.Image.open('image.jpg'))
282
+
283
+ audio_bytes = Path('audio.pcm').read_bytes()
284
+ await session.send_realtime_input(
285
+ media=types.Blob(data=audio_bytes, mime_type='audio/pcm;rate=16000'))
286
+
287
+ async for msg in session.receive():
288
+ if msg.text is not None:
289
+ print(f'{msg.text}')
290
+ ```
291
+ """
292
+ realtime_input = _t_realtime_input(media)
293
+ realtime_input_dict = realtime_input.model_dump(
294
+ exclude_none=True, mode='json'
295
+ )
296
+ await self._ws.send(json.dumps({'realtime_input': realtime_input_dict}))
297
+
298
+ async def send_tool_response(
299
+ self,
300
+ *,
301
+ function_responses: Union[
302
+ types.FunctionResponseOrDict,
303
+ Sequence[types.FunctionResponseOrDict],
304
+ ],
305
+ ):
306
+ """Send a tool response to the session.
307
+
308
+ Use `send_tool_response` to reply to `LiveServerToolCall` messages
309
+ from the server.
310
+
311
+ To set the available tools, use the `config.tools` argument
312
+ when you connect to the session (`client.live.connect`).
313
+
314
+ Args:
315
+ function_responses: A `FunctionResponse`-like object or list of
316
+ `FunctionResponse`-like objects.
317
+
318
+ Example:
319
+ ```
320
+ from google import genai
321
+ from google.genai import types
322
+
323
+ client = genai.Client(http_options={'api_version': 'v1alpha'})
324
+
325
+ tools = [{'function_declarations': [{'name': 'turn_on_the_lights'}]}]
326
+ config = {
327
+ "tools": tools,
328
+ "response_modalities": ['TEXT']
329
+ }
330
+
331
+ async with client.aio.live.connect(
332
+ model='gemini-2.0-flash-exp',
333
+ config=config
334
+ ) as session:
335
+ prompt = "Turn on the lights please"
336
+ await session.send_client_content(
337
+ turns=prompt,
338
+ turn_complete=True)
339
+
340
+ async for chunk in session.receive():
341
+ if chunk.server_content:
342
+ if chunk.text is not None:
343
+ print(chunk.text)
344
+ elif chunk.tool_call:
345
+ print(chunk.tool_call)
346
+ print('_'*80)
347
+ function_response=types.FunctionResponse(
348
+ name='turn_on_the_lights',
349
+ response={'result': 'ok'},
350
+ id=chunk.tool_call.function_calls[0].id,
351
+ )
352
+ print(function_response)
353
+ await session.send_tool_response(
354
+ function_responses=function_response
355
+ )
356
+
357
+ print('_'*80)
358
+ """
359
+ tool_response = _t_tool_response(function_responses)
360
+ if self._api_client.vertexai:
361
+ tool_response_dict = _ToolResponse_to_vertex(
362
+ api_client=self._api_client, from_object=tool_response
363
+ )
364
+ else:
365
+ tool_response_dict = _ToolResponse_to_mldev(
366
+ api_client=self._api_client, from_object=tool_response
367
+ )
368
+ await self._ws.send(json.dumps({'tool_response': tool_response_dict}))
369
+
115
370
  async def receive(self) -> AsyncIterator[types.LiveServerMessage]:
116
371
  """Receive model responses from the server.
117
372
 
@@ -207,7 +462,10 @@ class AsyncSession:
207
462
 
208
463
  async def _receive(self) -> types.LiveServerMessage:
209
464
  parameter_model = types.LiveServerMessage()
210
- raw_response = await self._ws.recv(decode=False)
465
+ try:
466
+ raw_response = await self._ws.recv(decode=False)
467
+ except TypeError:
468
+ raw_response = await self._ws.recv()
211
469
  if raw_response:
212
470
  try:
213
471
  response = json.loads(raw_response)
@@ -258,6 +516,12 @@ class AsyncSession:
258
516
  setv(to_object, ['turn_complete'], getv(from_object, ['turnComplete']))
259
517
  if getv(from_object, ['interrupted']) is not None:
260
518
  setv(to_object, ['interrupted'], getv(from_object, ['interrupted']))
519
+ if getv(from_object, ['generationComplete']) is not None:
520
+ setv(
521
+ to_object,
522
+ ['generation_complete'],
523
+ getv(from_object, ['generationComplete']),
524
+ )
261
525
  return to_object
262
526
 
263
527
  def _LiveToolCall_from_mldev(
@@ -329,6 +593,25 @@ class AsyncSession:
329
593
  )
330
594
  if getv(from_object, ['turnComplete']) is not None:
331
595
  setv(to_object, ['turn_complete'], getv(from_object, ['turnComplete']))
596
+ if getv(from_object, ['generationComplete']) is not None:
597
+ setv(
598
+ to_object,
599
+ ['generation_complete'],
600
+ getv(from_object, ['generationComplete']),
601
+ )
602
+ # Vertex supports transcription.
603
+ if getv(from_object, ['inputTranscription']) is not None:
604
+ setv(
605
+ to_object,
606
+ ['input_transcription'],
607
+ getv(from_object, ['inputTranscription']),
608
+ )
609
+ if getv(from_object, ['outputTranscription']) is not None:
610
+ setv(
611
+ to_object,
612
+ ['output_transcription'],
613
+ getv(from_object, ['outputTranscription']),
614
+ )
332
615
  if getv(from_object, ['interrupted']) is not None:
333
616
  setv(to_object, ['interrupted'], getv(from_object, ['interrupted']))
334
617
  return to_object
@@ -669,6 +952,79 @@ class AsyncSession:
669
952
  await self._ws.close()
670
953
 
671
954
 
955
+ def _t_content_strict(content: types.ContentOrDict):
956
+ if isinstance(content, dict):
957
+ return types.Content.model_validate(content)
958
+ elif isinstance(content, types.Content):
959
+ return content
960
+ else:
961
+ raise ValueError(
962
+ f'Could not convert input (type "{type(content)}") to '
963
+ '`types.Content`'
964
+ )
965
+
966
+
967
+ def _t_contents_strict(
968
+ contents: Union[Sequence[types.ContentOrDict], types.ContentOrDict]):
969
+ if isinstance(contents, Sequence):
970
+ return [_t_content_strict(content) for content in contents]
971
+ else:
972
+ return [_t_content_strict(contents)]
973
+
974
+
975
+ def _t_client_content(
976
+ turns: Optional[
977
+ Union[Sequence[types.ContentOrDict], types.ContentOrDict]
978
+ ] = None,
979
+ turn_complete: bool = True,
980
+ ) -> types.LiveClientContent:
981
+ if turns is None:
982
+ return types.LiveClientContent(turn_complete=turn_complete)
983
+
984
+ try:
985
+ return types.LiveClientContent(
986
+ turns=_t_contents_strict(contents=turns),
987
+ turn_complete=turn_complete,
988
+ )
989
+ except Exception as e:
990
+ raise ValueError(
991
+ f'Could not convert input (type "{type(turns)}") to '
992
+ '`types.LiveClientContent`'
993
+ ) from e
994
+
995
+
996
+ def _t_realtime_input(
997
+ media: t.BlobUnion,
998
+ ) -> types.LiveClientRealtimeInput:
999
+ try:
1000
+ return types.LiveClientRealtimeInput(media_chunks=[t.t_blob(blob=media)])
1001
+ except Exception as e:
1002
+ raise ValueError(
1003
+ f'Could not convert input (type "{type(input)}") to '
1004
+ '`types.LiveClientRealtimeInput`'
1005
+ ) from e
1006
+
1007
+
1008
+ def _t_tool_response(
1009
+ input: Union[
1010
+ types.FunctionResponseOrDict,
1011
+ Sequence[types.FunctionResponseOrDict],
1012
+ ],
1013
+ ) -> types.LiveClientToolResponse:
1014
+ if not input:
1015
+ raise ValueError(f'A tool response is required, got: \n{input}')
1016
+
1017
+ try:
1018
+ return types.LiveClientToolResponse(
1019
+ function_responses=t.t_function_responses(function_responses=input)
1020
+ )
1021
+ except Exception as e:
1022
+ raise ValueError(
1023
+ f'Could not convert input (type "{type(input)}") to '
1024
+ '`types.LiveClientToolResponse`'
1025
+ ) from e
1026
+
1027
+
672
1028
  class AsyncLive(_api_module.BaseModule):
673
1029
  """AsyncLive. The live module is experimental."""
674
1030
 
@@ -715,7 +1071,39 @@ class AsyncLive(_api_module.BaseModule):
715
1071
  to_object,
716
1072
  )
717
1073
  }
718
-
1074
+ if getv(config, ['temperature']) is not None:
1075
+ if getv(to_object, ['generationConfig']) is not None:
1076
+ to_object['generationConfig']['temperature'] = getv(
1077
+ config, ['temperature']
1078
+ )
1079
+ else:
1080
+ to_object['generationConfig'] = {
1081
+ 'temperature': getv(config, ['temperature'])
1082
+ }
1083
+ if getv(config, ['top_p']) is not None:
1084
+ if getv(to_object, ['generationConfig']) is not None:
1085
+ to_object['generationConfig']['topP'] = getv(config, ['top_p'])
1086
+ else:
1087
+ to_object['generationConfig'] = {'topP': getv(config, ['top_p'])}
1088
+ if getv(config, ['top_k']) is not None:
1089
+ if getv(to_object, ['generationConfig']) is not None:
1090
+ to_object['generationConfig']['topK'] = getv(config, ['top_k'])
1091
+ else:
1092
+ to_object['generationConfig'] = {'topK': getv(config, ['top_k'])}
1093
+ if getv(config, ['max_output_tokens']) is not None:
1094
+ if getv(to_object, ['generationConfig']) is not None:
1095
+ to_object['generationConfig']['maxOutputTokens'] = getv(
1096
+ config, ['max_output_tokens']
1097
+ )
1098
+ else:
1099
+ to_object['generationConfig'] = {
1100
+ 'maxOutputTokens': getv(config, ['max_output_tokens'])
1101
+ }
1102
+ if getv(config, ['seed']) is not None:
1103
+ if getv(to_object, ['generationConfig']) is not None:
1104
+ to_object['generationConfig']['seed'] = getv(config, ['seed'])
1105
+ else:
1106
+ to_object['generationConfig'] = {'seed': getv(config, ['seed'])}
719
1107
  if getv(config, ['system_instruction']) is not None:
720
1108
  setv(
721
1109
  to_object,
@@ -796,6 +1184,39 @@ class AsyncLive(_api_module.BaseModule):
796
1184
  to_object,
797
1185
  )
798
1186
  }
1187
+ if getv(config, ['temperature']) is not None:
1188
+ if getv(to_object, ['generationConfig']) is not None:
1189
+ to_object['generationConfig']['temperature'] = getv(
1190
+ config, ['temperature']
1191
+ )
1192
+ else:
1193
+ to_object['generationConfig'] = {
1194
+ 'temperature': getv(config, ['temperature'])
1195
+ }
1196
+ if getv(config, ['top_p']) is not None:
1197
+ if getv(to_object, ['generationConfig']) is not None:
1198
+ to_object['generationConfig']['topP'] = getv(config, ['top_p'])
1199
+ else:
1200
+ to_object['generationConfig'] = {'topP': getv(config, ['top_p'])}
1201
+ if getv(config, ['top_k']) is not None:
1202
+ if getv(to_object, ['generationConfig']) is not None:
1203
+ to_object['generationConfig']['topK'] = getv(config, ['top_k'])
1204
+ else:
1205
+ to_object['generationConfig'] = {'topK': getv(config, ['top_k'])}
1206
+ if getv(config, ['max_output_tokens']) is not None:
1207
+ if getv(to_object, ['generationConfig']) is not None:
1208
+ to_object['generationConfig']['maxOutputTokens'] = getv(
1209
+ config, ['max_output_tokens']
1210
+ )
1211
+ else:
1212
+ to_object['generationConfig'] = {
1213
+ 'maxOutputTokens': getv(config, ['max_output_tokens'])
1214
+ }
1215
+ if getv(config, ['seed']) is not None:
1216
+ if getv(to_object, ['generationConfig']) is not None:
1217
+ to_object['generationConfig']['seed'] = getv(config, ['seed'])
1218
+ else:
1219
+ to_object['generationConfig'] = {'seed': getv(config, ['seed'])}
799
1220
  if getv(config, ['system_instruction']) is not None:
800
1221
  setv(
801
1222
  to_object,
@@ -819,6 +1240,24 @@ class AsyncLive(_api_module.BaseModule):
819
1240
  for item in t.t_tools(self._api_client, getv(config, ['tools']))
820
1241
  ],
821
1242
  )
1243
+ if getv(config, ['input_audio_transcription']) is not None:
1244
+ setv(
1245
+ to_object,
1246
+ ['inputAudioTranscription'],
1247
+ _AudioTranscriptionConfig_to_vertex(
1248
+ self._api_client,
1249
+ getv(config, ['input_audio_transcription']),
1250
+ ),
1251
+ )
1252
+ if getv(config, ['output_audio_transcription']) is not None:
1253
+ setv(
1254
+ to_object,
1255
+ ['outputAudioTranscription'],
1256
+ _AudioTranscriptionConfig_to_vertex(
1257
+ self._api_client,
1258
+ getv(config, ['output_audio_transcription']),
1259
+ ),
1260
+ )
822
1261
 
823
1262
  return_value = {'setup': {'model': model}}
824
1263
  return_value['setup'].update(to_object)
@@ -865,8 +1304,15 @@ class AsyncLive(_api_module.BaseModule):
865
1304
  generation_config=config.get('generation_config'),
866
1305
  response_modalities=config.get('response_modalities'),
867
1306
  speech_config=config.get('speech_config'),
1307
+ temperature=config.get('temperature'),
1308
+ top_p=config.get('top_p'),
1309
+ top_k=config.get('top_k'),
1310
+ max_output_tokens=config.get('max_output_tokens'),
1311
+ seed=config.get('seed'),
868
1312
  system_instruction=system_instruction,
869
1313
  tools=config.get('tools'),
1314
+ input_audio_transcription=config.get('input_audio_transcription'),
1315
+ output_audio_transcription=config.get('output_audio_transcription'),
870
1316
  )
871
1317
  else:
872
1318
  parameter_model = config
@@ -915,8 +1361,16 @@ class AsyncLive(_api_module.BaseModule):
915
1361
  )
916
1362
  request = json.dumps(request_dict)
917
1363
 
918
- async with connect(uri, additional_headers=headers) as ws:
919
- await ws.send(request)
920
- logger.info(await ws.recv(decode=False))
1364
+ try:
1365
+ async with connect(uri, additional_headers=headers) as ws:
1366
+ await ws.send(request)
1367
+ logger.info(await ws.recv(decode=False))
1368
+
1369
+ yield AsyncSession(api_client=self._api_client, websocket=ws)
1370
+ except TypeError:
1371
+ # Try with the older websockets API
1372
+ async with connect(uri, extra_headers=headers) as ws:
1373
+ await ws.send(request)
1374
+ logger.info(await ws.recv())
921
1375
 
922
- yield AsyncSession(api_client=self._api_client, websocket=ws)
1376
+ yield AsyncSession(api_client=self._api_client, websocket=ws)
google/genai/models.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.
@@ -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.
google/genai/tunings.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.
google/genai/types.py CHANGED
@@ -708,7 +708,7 @@ class Content(_common.BaseModel):
708
708
  default=None,
709
709
  description="""Optional. The producer of the content. Must be either 'user' or
710
710
  'model'. Useful to set for multi-turn conversations, otherwise can be
711
- left blank or unset. If role is not specified, SDK will determine the role.""",
711
+ empty. If role is not specified, SDK will determine the role.""",
712
712
  )
713
713
 
714
714
 
@@ -783,7 +783,7 @@ class ContentDict(TypedDict, total=False):
783
783
  role: Optional[str]
784
784
  """Optional. The producer of the content. Must be either 'user' or
785
785
  'model'. Useful to set for multi-turn conversations, otherwise can be
786
- left blank or unset. If role is not specified, SDK will determine the role."""
786
+ empty. If role is not specified, SDK will determine the role."""
787
787
 
788
788
 
789
789
  ContentOrDict = Union[Content, ContentDict]
@@ -8774,6 +8774,36 @@ LiveServerSetupCompleteOrDict = Union[
8774
8774
  ]
8775
8775
 
8776
8776
 
8777
+ class Transcription(_common.BaseModel):
8778
+ """Audio transcription in Server Conent."""
8779
+
8780
+ text: Optional[str] = Field(
8781
+ default=None,
8782
+ description="""Transcription text.
8783
+ """,
8784
+ )
8785
+ finished: Optional[bool] = Field(
8786
+ default=None,
8787
+ description="""The bool indicates the end of the transcription.
8788
+ """,
8789
+ )
8790
+
8791
+
8792
+ class TranscriptionDict(TypedDict, total=False):
8793
+ """Audio transcription in Server Conent."""
8794
+
8795
+ text: Optional[str]
8796
+ """Transcription text.
8797
+ """
8798
+
8799
+ finished: Optional[bool]
8800
+ """The bool indicates the end of the transcription.
8801
+ """
8802
+
8803
+
8804
+ TranscriptionOrDict = Union[Transcription, TranscriptionDict]
8805
+
8806
+
8777
8807
  class LiveServerContent(_common.BaseModel):
8778
8808
  """Incremental server update generated by the model in response to client messages.
8779
8809
 
@@ -8793,6 +8823,30 @@ class LiveServerContent(_common.BaseModel):
8793
8823
  default=None,
8794
8824
  description="""If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue.""",
8795
8825
  )
8826
+ generation_complete: Optional[bool] = Field(
8827
+ default=None,
8828
+ description="""If true, indicates that the model is done generating. When model is
8829
+ interrupted while generating there will be no generation_complete message
8830
+ in interrupted turn, it will go through interrupted > turn_complete.
8831
+ When model assumes realtime playback there will be delay between
8832
+ generation_complete and turn_complete that is caused by model
8833
+ waiting for playback to finish. If true, indicates that the model
8834
+ has finished generating all content. This is a signal to the client
8835
+ that it can stop sending messages.""",
8836
+ )
8837
+ input_transcription: Optional[Transcription] = Field(
8838
+ default=None,
8839
+ description="""Input transcription. The transcription is independent to the model
8840
+ turn which means it doesn’t imply any ordering between transcription and
8841
+ model turn.""",
8842
+ )
8843
+ output_transcription: Optional[Transcription] = Field(
8844
+ default=None,
8845
+ description="""Output transcription. The transcription is independent to the model
8846
+ turn which means it doesn’t imply any ordering between transcription and
8847
+ model turn.
8848
+ """,
8849
+ )
8796
8850
 
8797
8851
 
8798
8852
  class LiveServerContentDict(TypedDict, total=False):
@@ -8811,6 +8865,27 @@ class LiveServerContentDict(TypedDict, total=False):
8811
8865
  interrupted: Optional[bool]
8812
8866
  """If true, indicates that a client message has interrupted current model generation. If the client is playing out the content in realtime, this is a good signal to stop and empty the current queue."""
8813
8867
 
8868
+ generation_complete: Optional[bool]
8869
+ """If true, indicates that the model is done generating. When model is
8870
+ interrupted while generating there will be no generation_complete message
8871
+ in interrupted turn, it will go through interrupted > turn_complete.
8872
+ When model assumes realtime playback there will be delay between
8873
+ generation_complete and turn_complete that is caused by model
8874
+ waiting for playback to finish. If true, indicates that the model
8875
+ has finished generating all content. This is a signal to the client
8876
+ that it can stop sending messages."""
8877
+
8878
+ input_transcription: Optional[TranscriptionDict]
8879
+ """Input transcription. The transcription is independent to the model
8880
+ turn which means it doesn’t imply any ordering between transcription and
8881
+ model turn."""
8882
+
8883
+ output_transcription: Optional[TranscriptionDict]
8884
+ """Output transcription. The transcription is independent to the model
8885
+ turn which means it doesn’t imply any ordering between transcription and
8886
+ model turn.
8887
+ """
8888
+
8814
8889
 
8815
8890
  LiveServerContentOrDict = Union[LiveServerContent, LiveServerContentDict]
8816
8891
 
@@ -8950,15 +9025,7 @@ class LiveClientSetup(_common.BaseModel):
8950
9025
  generation_config: Optional[GenerationConfig] = Field(
8951
9026
  default=None,
8952
9027
  description="""The generation configuration for the session.
8953
-
8954
- The following fields are supported:
8955
- - `response_logprobs`
8956
- - `response_mime_type`
8957
- - `logprobs`
8958
- - `response_schema`
8959
- - `stop_sequence`
8960
- - `routing_config`
8961
- - `audio_timestamp`
9028
+ Note: only a subset of fields are supported.
8962
9029
  """,
8963
9030
  )
8964
9031
  system_instruction: Optional[Content] = Field(
@@ -8988,15 +9055,7 @@ class LiveClientSetupDict(TypedDict, total=False):
8988
9055
 
8989
9056
  generation_config: Optional[GenerationConfigDict]
8990
9057
  """The generation configuration for the session.
8991
-
8992
- The following fields are supported:
8993
- - `response_logprobs`
8994
- - `response_mime_type`
8995
- - `logprobs`
8996
- - `response_schema`
8997
- - `stop_sequence`
8998
- - `routing_config`
8999
- - `audio_timestamp`
9058
+ Note: only a subset of fields are supported.
9000
9059
  """
9001
9060
 
9002
9061
  system_instruction: Optional[ContentDict]
@@ -9070,11 +9129,11 @@ LiveClientContentOrDict = Union[LiveClientContent, LiveClientContentDict]
9070
9129
  class LiveClientRealtimeInput(_common.BaseModel):
9071
9130
  """User input that is sent in real time.
9072
9131
 
9073
- This is different from `ClientContentUpdate` in a few ways:
9132
+ This is different from `LiveClientContent` in a few ways:
9074
9133
 
9075
9134
  - Can be sent continuously without interruption to model generation.
9076
9135
  - If there is a need to mix data interleaved across the
9077
- `ClientContentUpdate` and the `RealtimeUpdate`, server attempts to
9136
+ `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to
9078
9137
  optimize for best response, but there are no guarantees.
9079
9138
  - End of turn is not explicitly specified, but is rather derived from user
9080
9139
  activity (for example, end of speech).
@@ -9092,11 +9151,11 @@ class LiveClientRealtimeInput(_common.BaseModel):
9092
9151
  class LiveClientRealtimeInputDict(TypedDict, total=False):
9093
9152
  """User input that is sent in real time.
9094
9153
 
9095
- This is different from `ClientContentUpdate` in a few ways:
9154
+ This is different from `LiveClientContent` in a few ways:
9096
9155
 
9097
9156
  - Can be sent continuously without interruption to model generation.
9098
9157
  - If there is a need to mix data interleaved across the
9099
- `ClientContentUpdate` and the `RealtimeUpdate`, server attempts to
9158
+ `LiveClientContent` and the `LiveClientRealtimeInput`, server attempts to
9100
9159
  optimize for best response, but there are no guarantees.
9101
9160
  - End of turn is not explicitly specified, but is rather derived from user
9102
9161
  activity (for example, end of speech).
@@ -9192,6 +9251,23 @@ class LiveClientMessageDict(TypedDict, total=False):
9192
9251
  LiveClientMessageOrDict = Union[LiveClientMessage, LiveClientMessageDict]
9193
9252
 
9194
9253
 
9254
+ class AudioTranscriptionConfig(_common.BaseModel):
9255
+ """The audio transcription configuration in Setup."""
9256
+
9257
+ pass
9258
+
9259
+
9260
+ class AudioTranscriptionConfigDict(TypedDict, total=False):
9261
+ """The audio transcription configuration in Setup."""
9262
+
9263
+ pass
9264
+
9265
+
9266
+ AudioTranscriptionConfigOrDict = Union[
9267
+ AudioTranscriptionConfig, AudioTranscriptionConfigDict
9268
+ ]
9269
+
9270
+
9195
9271
  class LiveConnectConfig(_common.BaseModel):
9196
9272
  """Session config for the API connection."""
9197
9273
 
@@ -9205,6 +9281,42 @@ class LiveConnectConfig(_common.BaseModel):
9205
9281
  modalities that the model can return. Defaults to AUDIO if not specified.
9206
9282
  """,
9207
9283
  )
9284
+ temperature: Optional[float] = Field(
9285
+ default=None,
9286
+ description="""Value that controls the degree of randomness in token selection.
9287
+ Lower temperatures are good for prompts that require a less open-ended or
9288
+ creative response, while higher temperatures can lead to more diverse or
9289
+ creative results.
9290
+ """,
9291
+ )
9292
+ top_p: Optional[float] = Field(
9293
+ default=None,
9294
+ description="""Tokens are selected from the most to least probable until the sum
9295
+ of their probabilities equals this value. Use a lower value for less
9296
+ random responses and a higher value for more random responses.
9297
+ """,
9298
+ )
9299
+ top_k: Optional[float] = Field(
9300
+ default=None,
9301
+ description="""For each token selection step, the ``top_k`` tokens with the
9302
+ highest probabilities are sampled. Then tokens are further filtered based
9303
+ on ``top_p`` with the final token selected using temperature sampling. Use
9304
+ a lower number for less random responses and a higher number for more
9305
+ random responses.
9306
+ """,
9307
+ )
9308
+ max_output_tokens: Optional[int] = Field(
9309
+ default=None,
9310
+ description="""Maximum number of tokens that can be generated in the response.
9311
+ """,
9312
+ )
9313
+ seed: Optional[int] = Field(
9314
+ default=None,
9315
+ description="""When ``seed`` is fixed to a specific number, the model makes a best
9316
+ effort to provide the same response for repeated requests. By default, a
9317
+ random number is used.
9318
+ """,
9319
+ )
9208
9320
  speech_config: Optional[SpeechConfig] = Field(
9209
9321
  default=None,
9210
9322
  description="""The speech generation configuration.
@@ -9224,6 +9336,17 @@ class LiveConnectConfig(_common.BaseModel):
9224
9336
  external systems to perform an action, or set of actions, outside of
9225
9337
  knowledge and scope of the model.""",
9226
9338
  )
9339
+ input_audio_transcription: Optional[AudioTranscriptionConfig] = Field(
9340
+ default=None,
9341
+ description="""The transcription of the input aligns with the input audio language.
9342
+ """,
9343
+ )
9344
+ output_audio_transcription: Optional[AudioTranscriptionConfig] = Field(
9345
+ default=None,
9346
+ description="""The transcription of the output aligns with the language code
9347
+ specified for the output audio.
9348
+ """,
9349
+ )
9227
9350
 
9228
9351
 
9229
9352
  class LiveConnectConfigDict(TypedDict, total=False):
@@ -9237,6 +9360,37 @@ class LiveConnectConfigDict(TypedDict, total=False):
9237
9360
  modalities that the model can return. Defaults to AUDIO if not specified.
9238
9361
  """
9239
9362
 
9363
+ temperature: Optional[float]
9364
+ """Value that controls the degree of randomness in token selection.
9365
+ Lower temperatures are good for prompts that require a less open-ended or
9366
+ creative response, while higher temperatures can lead to more diverse or
9367
+ creative results.
9368
+ """
9369
+
9370
+ top_p: Optional[float]
9371
+ """Tokens are selected from the most to least probable until the sum
9372
+ of their probabilities equals this value. Use a lower value for less
9373
+ random responses and a higher value for more random responses.
9374
+ """
9375
+
9376
+ top_k: Optional[float]
9377
+ """For each token selection step, the ``top_k`` tokens with the
9378
+ highest probabilities are sampled. Then tokens are further filtered based
9379
+ on ``top_p`` with the final token selected using temperature sampling. Use
9380
+ a lower number for less random responses and a higher number for more
9381
+ random responses.
9382
+ """
9383
+
9384
+ max_output_tokens: Optional[int]
9385
+ """Maximum number of tokens that can be generated in the response.
9386
+ """
9387
+
9388
+ seed: Optional[int]
9389
+ """When ``seed`` is fixed to a specific number, the model makes a best
9390
+ effort to provide the same response for repeated requests. By default, a
9391
+ random number is used.
9392
+ """
9393
+
9240
9394
  speech_config: Optional[SpeechConfigDict]
9241
9395
  """The speech generation configuration.
9242
9396
  """
@@ -9253,5 +9407,14 @@ class LiveConnectConfigDict(TypedDict, total=False):
9253
9407
  external systems to perform an action, or set of actions, outside of
9254
9408
  knowledge and scope of the model."""
9255
9409
 
9410
+ input_audio_transcription: Optional[AudioTranscriptionConfigDict]
9411
+ """The transcription of the input aligns with the input audio language.
9412
+ """
9413
+
9414
+ output_audio_transcription: Optional[AudioTranscriptionConfigDict]
9415
+ """The transcription of the output aligns with the language code
9416
+ specified for the output audio.
9417
+ """
9418
+
9256
9419
 
9257
9420
  LiveConnectConfigOrDict = Union[LiveConnectConfig, LiveConnectConfigDict]
google/genai/version.py CHANGED
@@ -13,4 +13,4 @@
13
13
  # limitations under the License.
14
14
  #
15
15
 
16
- __version__ = '1.8.0' # x-release-please-version
16
+ __version__ = '1.9.0' # x-release-please-version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-genai
3
- Version: 1.8.0
3
+ Version: 1.9.0
4
4
  Summary: GenAI Python SDK
5
5
  Author-email: Google LLC <googleapis-packages@google.com>
6
6
  License: Apache-2.0
@@ -0,0 +1,27 @@
1
+ google/genai/__init__.py,sha256=IYw-PcsdgjSpS1mU_ZcYkTfPocsJ4aVmrDxP7vX7c6Y,709
2
+ google/genai/_api_client.py,sha256=1KojMpO3mkvbQ07g-xCETKR1yiM7j9ct-2hv4by7KMg,31726
3
+ google/genai/_api_module.py,sha256=66FsFq9N8PdTegDyx3am3NHpI0Bw7HBmifUMCrZsx_Q,902
4
+ google/genai/_automatic_function_calling_util.py,sha256=xAH-96LIEmC-yefEIae8TrBPZZAI1UJrn0bAIZsISDE,10899
5
+ google/genai/_common.py,sha256=PNwxVUKCD93ICHJlwCTAItGH3Wjva5xHC7_7mc-p8oA,10153
6
+ google/genai/_extra_utils.py,sha256=l9U0uaq4TWdfY7fOpGR3LcsA6-TMEblfQlEXdC0IGPY,12462
7
+ google/genai/_replay_api_client.py,sha256=vvtcgngZMvhebrubhClVeW16UjE2nMUHQbtyBRmM4ko,18942
8
+ google/genai/_test_api_client.py,sha256=XNOWq8AkYbqInv1aljNGlFXsv8slQIWTYy_hdcCetD0,4797
9
+ google/genai/_transformers.py,sha256=VFJw6yacWnQsc8_9mhW8CxPg-IfzIgPoNrizSNL51yI,31575
10
+ google/genai/batches.py,sha256=-LJGF4iCwvw0Uafr2EEVt2EsOFPl0S2-y5QBFGDw_m0,34485
11
+ google/genai/caches.py,sha256=pjFuuVOy3RWifhxNR6Al97S5jZX7NwghqX5M5NMKSOM,57320
12
+ google/genai/chats.py,sha256=4tg04v16WMth_FMeteUuAchLtPt-y3ydOLMksSRAyJM,16676
13
+ google/genai/client.py,sha256=uctarMTXcp6iC7XGH2lR5wDUqy17hy4-6CMi7seBlvo,10043
14
+ google/genai/errors.py,sha256=2YriqMtGA1V3iNtPernOjEOlMMAAEmBjSUoukDMgVqU,4725
15
+ google/genai/files.py,sha256=8fvbdPWYfZvUg9w-ijz9fKCWXlNTrTWCZQ0meJmKzjw,38290
16
+ google/genai/live.py,sha256=LDxCSaU6KNuwG1t9Oe1sE1hWxx8YTNbZf2hz50pPvt4,47489
17
+ google/genai/models.py,sha256=VjB0IHKAe_6ncEacl2BmDPa4KS4-CzWPwJwWjH5jKC0,204310
18
+ google/genai/operations.py,sha256=AxoO9v15b_K0w2MRCBFLD80bztgGwjVCaiXTp7wm07M,19890
19
+ google/genai/pagers.py,sha256=1jxDjre7M_Udt0ntgOr_79iR0-axjdr_Q6tZZzVRli8,6784
20
+ google/genai/tunings.py,sha256=hJkJtibBoySbjdzxOUvQR2hVYTslmaWwt0xUw0h1v2o,47010
21
+ google/genai/types.py,sha256=mfIIHpb1wi9wTqy9wJrFypAPClXo3J2Hld3CiW9hy54,312574
22
+ google/genai/version.py,sha256=bmTGYxkYSqQOLgKnH5GxOGSQ05pPupy2P_ts3hTwHMU,626
23
+ google_genai-1.9.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
24
+ google_genai-1.9.0.dist-info/METADATA,sha256=HD9pOaC7dLEwRyBZnCp5dHn0J347l_KPdKP1lQgERlE,32890
25
+ google_genai-1.9.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
26
+ google_genai-1.9.0.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7
27
+ google_genai-1.9.0.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- google/genai/__init__.py,sha256=IYw-PcsdgjSpS1mU_ZcYkTfPocsJ4aVmrDxP7vX7c6Y,709
2
- google/genai/_api_client.py,sha256=1KojMpO3mkvbQ07g-xCETKR1yiM7j9ct-2hv4by7KMg,31726
3
- google/genai/_api_module.py,sha256=66FsFq9N8PdTegDyx3am3NHpI0Bw7HBmifUMCrZsx_Q,902
4
- google/genai/_automatic_function_calling_util.py,sha256=xAH-96LIEmC-yefEIae8TrBPZZAI1UJrn0bAIZsISDE,10899
5
- google/genai/_common.py,sha256=PNwxVUKCD93ICHJlwCTAItGH3Wjva5xHC7_7mc-p8oA,10153
6
- google/genai/_extra_utils.py,sha256=l9U0uaq4TWdfY7fOpGR3LcsA6-TMEblfQlEXdC0IGPY,12462
7
- google/genai/_replay_api_client.py,sha256=vvtcgngZMvhebrubhClVeW16UjE2nMUHQbtyBRmM4ko,18942
8
- google/genai/_test_api_client.py,sha256=XNOWq8AkYbqInv1aljNGlFXsv8slQIWTYy_hdcCetD0,4797
9
- google/genai/_transformers.py,sha256=XDbatGrYs4fIxfnJEW_MA_tz9i_Mub8b7Y5ejxXMMOE,29963
10
- google/genai/batches.py,sha256=1gdwy5Tcd4kZGYulfwywqooOGv8Ozp8uk9kjes6rIgg,34485
11
- google/genai/caches.py,sha256=uAhoZ1xm7nuHfHE9k17Ric9LCHDTPpcTMAkq0XI65ew,57320
12
- google/genai/chats.py,sha256=4tg04v16WMth_FMeteUuAchLtPt-y3ydOLMksSRAyJM,16676
13
- google/genai/client.py,sha256=uctarMTXcp6iC7XGH2lR5wDUqy17hy4-6CMi7seBlvo,10043
14
- google/genai/errors.py,sha256=U48LRaXeSeJlhZ1t0sDDmbrebs7l0KohTMlKg8Nc_X4,4708
15
- google/genai/files.py,sha256=Pt-ACLayO6_cE_ZrqzsjUkiuh3drZN6AIjqNp6x4IyE,38290
16
- google/genai/live.py,sha256=S4HZs7VLae4cqWt6f8USh9ifShoUOSyGPFpREAHAFUk,32021
17
- google/genai/models.py,sha256=oq5DHCT3ZZsZ_pvP9q4UDzH4MNl04sWl5jB1DrEZRsI,204310
18
- google/genai/operations.py,sha256=ad3vU-xouT2E1pv2WN5L0qehFYSZ0rCEr1XQqqy5vbQ,19890
19
- google/genai/pagers.py,sha256=1jxDjre7M_Udt0ntgOr_79iR0-axjdr_Q6tZZzVRli8,6784
20
- google/genai/tunings.py,sha256=Aep8EDLsKXlBryLQNR8psVSybgy968LFZOsiyOI1JBM,47010
21
- google/genai/types.py,sha256=QUT17RAmUy7Jqg_nyDeWg3FQrBbhT4ahLSgz06munNE,306100
22
- google/genai/version.py,sha256=Xs4MLsO0MFRJxpS-X5D1EEWcnL72FdqoLyny7PKF548,626
23
- google_genai-1.8.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
24
- google_genai-1.8.0.dist-info/METADATA,sha256=rqPx2YUyy6rYTMzndxDnL_XDsbcYlm1gr2WbePC2-Ao,32890
25
- google_genai-1.8.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
26
- google_genai-1.8.0.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7
27
- google_genai-1.8.0.dist-info/RECORD,,