google-genai 1.29.0__py3-none-any.whl → 1.31.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/batches.py CHANGED
@@ -30,6 +30,7 @@ from ._common import get_value_by_path as getv
30
30
  from ._common import set_value_by_path as setv
31
31
  from .pagers import AsyncPager, Pager
32
32
 
33
+
33
34
  logger = logging.getLogger('google_genai.batches')
34
35
 
35
36
 
@@ -338,6 +339,11 @@ def _GoogleSearch_to_mldev(
338
339
  _Interval_to_mldev(getv(from_object, ['time_range_filter']), to_object),
339
340
  )
340
341
 
342
+ if getv(from_object, ['exclude_domains']) is not None:
343
+ raise ValueError(
344
+ 'exclude_domains parameter is not supported in Gemini API.'
345
+ )
346
+
341
347
  return to_object
342
348
 
343
349
 
@@ -385,6 +391,17 @@ def _UrlContext_to_mldev(
385
391
  return to_object
386
392
 
387
393
 
394
+ def _ToolComputerUse_to_mldev(
395
+ from_object: Union[dict[str, Any], object],
396
+ parent_object: Optional[dict[str, Any]] = None,
397
+ ) -> dict[str, Any]:
398
+ to_object: dict[str, Any] = {}
399
+ if getv(from_object, ['environment']) is not None:
400
+ setv(to_object, ['environment'], getv(from_object, ['environment']))
401
+
402
+ return to_object
403
+
404
+
388
405
  def _Tool_to_mldev(
389
406
  from_object: Union[dict[str, Any], object],
390
407
  parent_object: Optional[dict[str, Any]] = None,
@@ -434,12 +451,18 @@ def _Tool_to_mldev(
434
451
  _UrlContext_to_mldev(getv(from_object, ['url_context']), to_object),
435
452
  )
436
453
 
454
+ if getv(from_object, ['computer_use']) is not None:
455
+ setv(
456
+ to_object,
457
+ ['computerUse'],
458
+ _ToolComputerUse_to_mldev(
459
+ getv(from_object, ['computer_use']), to_object
460
+ ),
461
+ )
462
+
437
463
  if getv(from_object, ['code_execution']) is not None:
438
464
  setv(to_object, ['codeExecution'], getv(from_object, ['code_execution']))
439
465
 
440
- if getv(from_object, ['computer_use']) is not None:
441
- setv(to_object, ['computerUse'], getv(from_object, ['computer_use']))
442
-
443
466
  return to_object
444
467
 
445
468
 
@@ -2235,6 +2258,17 @@ class Batches(_api_module.BaseModule):
2235
2258
  )
2236
2259
  print(batch_job.state)
2237
2260
  """
2261
+ parameter_model = types._CreateBatchJobParameters(
2262
+ model=model,
2263
+ src=src,
2264
+ config=config,
2265
+ )
2266
+ http_options: Optional[types.HttpOptions] = None
2267
+ if (
2268
+ parameter_model.config is not None
2269
+ and parameter_model.config.http_options is not None
2270
+ ):
2271
+ http_options = parameter_model.config.http_options
2238
2272
  if self._api_client.vertexai:
2239
2273
  if isinstance(src, list):
2240
2274
  raise ValueError(
@@ -2243,6 +2277,65 @@ class Batches(_api_module.BaseModule):
2243
2277
  )
2244
2278
 
2245
2279
  config = _extra_utils.format_destination(src, config)
2280
+ else:
2281
+ if isinstance(parameter_model.src, list) or (
2282
+ not isinstance(parameter_model.src, str)
2283
+ and parameter_model.src
2284
+ and parameter_model.src.inlined_requests
2285
+ ):
2286
+ # Handle system instruction in InlinedRequests.
2287
+ request_url_dict: Optional[dict[str, str]]
2288
+ request_dict: dict[str, Any] = _CreateBatchJobParameters_to_mldev(
2289
+ self._api_client, parameter_model
2290
+ )
2291
+ request_url_dict = request_dict.get('_url')
2292
+ if request_url_dict:
2293
+ path = '{model}:batchGenerateContent'.format_map(request_url_dict)
2294
+ else:
2295
+ path = '{model}:batchGenerateContent'
2296
+ query_params = request_dict.get('_query')
2297
+ if query_params:
2298
+ path = f'{path}?{urlencode(query_params)}'
2299
+ request_dict.pop('config', None)
2300
+
2301
+ request_dict = _common.convert_to_dict(request_dict)
2302
+ request_dict = _common.encode_unserializable_types(request_dict)
2303
+ # Move system instruction to 'request':
2304
+ # {'systemInstruction': system_instruction}
2305
+ requests = []
2306
+ batch_dict = request_dict.get('batch')
2307
+ if batch_dict and isinstance(batch_dict, dict):
2308
+ input_config_dict = batch_dict.get('inputConfig')
2309
+ if input_config_dict and isinstance(input_config_dict, dict):
2310
+ requests_dict = input_config_dict.get('requests')
2311
+ if requests_dict and isinstance(requests_dict, dict):
2312
+ requests = requests_dict.get('requests')
2313
+ new_requests = []
2314
+ if requests:
2315
+ for req in requests:
2316
+ if req.get('systemInstruction'):
2317
+ value = req.pop('systemInstruction')
2318
+ req['request'].update({'systemInstruction': value})
2319
+ new_requests.append(req)
2320
+ request_dict['batch']['inputConfig']['requests'][ # type: ignore
2321
+ 'requests'
2322
+ ] = new_requests
2323
+
2324
+ response = self._api_client.request(
2325
+ 'post', path, request_dict, http_options
2326
+ )
2327
+
2328
+ response_dict = '' if not response.body else json.loads(response.body)
2329
+
2330
+ response_dict = _BatchJob_from_mldev(response_dict)
2331
+
2332
+ return_value = types.BatchJob._from_response(
2333
+ response=response_dict, kwargs=parameter_model.model_dump()
2334
+ )
2335
+
2336
+ self._api_client._verify_response(return_value)
2337
+ return return_value
2338
+
2246
2339
  return self._create(model=model, src=src, config=config)
2247
2340
 
2248
2341
  def list(
@@ -2669,6 +2762,17 @@ class AsyncBatches(_api_module.BaseModule):
2669
2762
  src="gs://path/to/input/data",
2670
2763
  )
2671
2764
  """
2765
+ parameter_model = types._CreateBatchJobParameters(
2766
+ model=model,
2767
+ src=src,
2768
+ config=config,
2769
+ )
2770
+ http_options: Optional[types.HttpOptions] = None
2771
+ if (
2772
+ parameter_model.config is not None
2773
+ and parameter_model.config.http_options is not None
2774
+ ):
2775
+ http_options = parameter_model.config.http_options
2672
2776
  if self._api_client.vertexai:
2673
2777
  if isinstance(src, list):
2674
2778
  raise ValueError(
@@ -2677,6 +2781,65 @@ class AsyncBatches(_api_module.BaseModule):
2677
2781
  )
2678
2782
 
2679
2783
  config = _extra_utils.format_destination(src, config)
2784
+ else:
2785
+ if isinstance(parameter_model.src, list) or (
2786
+ not isinstance(parameter_model.src, str)
2787
+ and parameter_model.src
2788
+ and parameter_model.src.inlined_requests
2789
+ ):
2790
+ # Handle system instruction in InlinedRequests.
2791
+ request_url_dict: Optional[dict[str, str]]
2792
+ request_dict: dict[str, Any] = _CreateBatchJobParameters_to_mldev(
2793
+ self._api_client, parameter_model
2794
+ )
2795
+ request_url_dict = request_dict.get('_url')
2796
+ if request_url_dict:
2797
+ path = '{model}:batchGenerateContent'.format_map(request_url_dict)
2798
+ else:
2799
+ path = '{model}:batchGenerateContent'
2800
+ query_params = request_dict.get('_query')
2801
+ if query_params:
2802
+ path = f'{path}?{urlencode(query_params)}'
2803
+ request_dict.pop('config', None)
2804
+
2805
+ request_dict = _common.convert_to_dict(request_dict)
2806
+ request_dict = _common.encode_unserializable_types(request_dict)
2807
+ # Move system instruction to 'request':
2808
+ # {'systemInstruction': system_instruction}
2809
+ requests = []
2810
+ batch_dict = request_dict.get('batch')
2811
+ if batch_dict and isinstance(batch_dict, dict):
2812
+ input_config_dict = batch_dict.get('inputConfig')
2813
+ if input_config_dict and isinstance(input_config_dict, dict):
2814
+ requests_dict = input_config_dict.get('requests')
2815
+ if requests_dict and isinstance(requests_dict, dict):
2816
+ requests = requests_dict.get('requests')
2817
+ new_requests = []
2818
+ if requests:
2819
+ for req in requests:
2820
+ if req.get('systemInstruction'):
2821
+ value = req.pop('systemInstruction')
2822
+ req['request'].update({'systemInstruction': value})
2823
+ new_requests.append(req)
2824
+ request_dict['batch']['inputConfig']['requests'][ # type: ignore
2825
+ 'requests'
2826
+ ] = new_requests
2827
+
2828
+ response = await self._api_client.async_request(
2829
+ 'post', path, request_dict, http_options
2830
+ )
2831
+
2832
+ response_dict = '' if not response.body else json.loads(response.body)
2833
+
2834
+ response_dict = _BatchJob_from_mldev(response_dict)
2835
+
2836
+ return_value = types.BatchJob._from_response(
2837
+ response=response_dict, kwargs=parameter_model.model_dump()
2838
+ )
2839
+
2840
+ self._api_client._verify_response(return_value)
2841
+ return return_value
2842
+
2680
2843
  return await self._create(model=model, src=src, config=config)
2681
2844
 
2682
2845
  async def list(
google/genai/caches.py CHANGED
@@ -29,6 +29,7 @@ from ._common import get_value_by_path as getv
29
29
  from ._common import set_value_by_path as setv
30
30
  from .pagers import AsyncPager, Pager
31
31
 
32
+
32
33
  logger = logging.getLogger('google_genai.caches')
33
34
 
34
35
 
@@ -231,6 +232,11 @@ def _GoogleSearch_to_mldev(
231
232
  _Interval_to_mldev(getv(from_object, ['time_range_filter']), to_object),
232
233
  )
233
234
 
235
+ if getv(from_object, ['exclude_domains']) is not None:
236
+ raise ValueError(
237
+ 'exclude_domains parameter is not supported in Gemini API.'
238
+ )
239
+
234
240
  return to_object
235
241
 
236
242
 
@@ -278,6 +284,17 @@ def _UrlContext_to_mldev(
278
284
  return to_object
279
285
 
280
286
 
287
+ def _ToolComputerUse_to_mldev(
288
+ from_object: Union[dict[str, Any], object],
289
+ parent_object: Optional[dict[str, Any]] = None,
290
+ ) -> dict[str, Any]:
291
+ to_object: dict[str, Any] = {}
292
+ if getv(from_object, ['environment']) is not None:
293
+ setv(to_object, ['environment'], getv(from_object, ['environment']))
294
+
295
+ return to_object
296
+
297
+
281
298
  def _Tool_to_mldev(
282
299
  from_object: Union[dict[str, Any], object],
283
300
  parent_object: Optional[dict[str, Any]] = None,
@@ -327,12 +344,18 @@ def _Tool_to_mldev(
327
344
  _UrlContext_to_mldev(getv(from_object, ['url_context']), to_object),
328
345
  )
329
346
 
347
+ if getv(from_object, ['computer_use']) is not None:
348
+ setv(
349
+ to_object,
350
+ ['computerUse'],
351
+ _ToolComputerUse_to_mldev(
352
+ getv(from_object, ['computer_use']), to_object
353
+ ),
354
+ )
355
+
330
356
  if getv(from_object, ['code_execution']) is not None:
331
357
  setv(to_object, ['codeExecution'], getv(from_object, ['code_execution']))
332
358
 
333
- if getv(from_object, ['computer_use']) is not None:
334
- setv(to_object, ['computerUse'], getv(from_object, ['computer_use']))
335
-
336
359
  return to_object
337
360
 
338
361
 
@@ -811,6 +834,9 @@ def _GoogleSearch_to_vertex(
811
834
  ),
812
835
  )
813
836
 
837
+ if getv(from_object, ['exclude_domains']) is not None:
838
+ setv(to_object, ['excludeDomains'], getv(from_object, ['exclude_domains']))
839
+
814
840
  return to_object
815
841
 
816
842
 
@@ -854,6 +880,8 @@ def _EnterpriseWebSearch_to_vertex(
854
880
  parent_object: Optional[dict[str, Any]] = None,
855
881
  ) -> dict[str, Any]:
856
882
  to_object: dict[str, Any] = {}
883
+ if getv(from_object, ['exclude_domains']) is not None:
884
+ setv(to_object, ['excludeDomains'], getv(from_object, ['exclude_domains']))
857
885
 
858
886
  return to_object
859
887
 
@@ -933,6 +961,17 @@ def _UrlContext_to_vertex(
933
961
  return to_object
934
962
 
935
963
 
964
+ def _ToolComputerUse_to_vertex(
965
+ from_object: Union[dict[str, Any], object],
966
+ parent_object: Optional[dict[str, Any]] = None,
967
+ ) -> dict[str, Any]:
968
+ to_object: dict[str, Any] = {}
969
+ if getv(from_object, ['environment']) is not None:
970
+ setv(to_object, ['environment'], getv(from_object, ['environment']))
971
+
972
+ return to_object
973
+
974
+
936
975
  def _Tool_to_vertex(
937
976
  from_object: Union[dict[str, Any], object],
938
977
  parent_object: Optional[dict[str, Any]] = None,
@@ -992,12 +1031,18 @@ def _Tool_to_vertex(
992
1031
  _UrlContext_to_vertex(getv(from_object, ['url_context']), to_object),
993
1032
  )
994
1033
 
1034
+ if getv(from_object, ['computer_use']) is not None:
1035
+ setv(
1036
+ to_object,
1037
+ ['computerUse'],
1038
+ _ToolComputerUse_to_vertex(
1039
+ getv(from_object, ['computer_use']), to_object
1040
+ ),
1041
+ )
1042
+
995
1043
  if getv(from_object, ['code_execution']) is not None:
996
1044
  setv(to_object, ['codeExecution'], getv(from_object, ['code_execution']))
997
1045
 
998
- if getv(from_object, ['computer_use']) is not None:
999
- setv(to_object, ['computerUse'], getv(from_object, ['computer_use']))
1000
-
1001
1046
  return to_object
1002
1047
 
1003
1048
 
google/genai/chats.py CHANGED
@@ -454,6 +454,7 @@ class AsyncChat(_BaseChat):
454
454
  Usage:
455
455
 
456
456
  .. code-block:: python
457
+
457
458
  chat = client.aio.chats.create(model='gemini-2.0-flash')
458
459
  async for chunk in await chat.send_message_stream('tell me a story'):
459
460
  print(chunk.text)
google/genai/files.py CHANGED
@@ -31,6 +31,7 @@ from ._common import get_value_by_path as getv
31
31
  from ._common import set_value_by_path as setv
32
32
  from .pagers import AsyncPager, Pager
33
33
 
34
+
34
35
  logger = logging.getLogger('google_genai.files')
35
36
 
36
37
 
google/genai/live.py CHANGED
@@ -187,29 +187,30 @@ class AsyncSession:
187
187
  and will not return until you send `turn_complete=True`.
188
188
 
189
189
  Example:
190
- ```
191
- import google.genai
192
- from google.genai import types
193
- import os
194
190
 
195
- if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI'):
196
- MODEL_NAME = 'gemini-2.0-flash-live-preview-04-09'
197
- else:
198
- MODEL_NAME = 'gemini-live-2.5-flash-preview';
199
-
200
- client = genai.Client()
201
- async with client.aio.live.connect(
202
- model=MODEL_NAME,
203
- config={"response_modalities": ["TEXT"]}
204
- ) as session:
205
- await session.send_client_content(
206
- turns=types.Content(
207
- role='user',
208
- parts=[types.Part(text="Hello world!")]))
209
- async for msg in session.receive():
210
- if msg.text:
211
- print(msg.text)
212
- ```
191
+ .. code-block:: python
192
+
193
+ import google.genai
194
+ from google.genai import types
195
+ import os
196
+
197
+ if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI'):
198
+ MODEL_NAME = 'gemini-2.0-flash-live-preview-04-09'
199
+ else:
200
+ MODEL_NAME = 'gemini-live-2.5-flash-preview';
201
+
202
+ client = genai.Client()
203
+ async with client.aio.live.connect(
204
+ model=MODEL_NAME,
205
+ config={"response_modalities": ["TEXT"]}
206
+ ) as session:
207
+ await session.send_client_content(
208
+ turns=types.Content(
209
+ role='user',
210
+ parts=[types.Part(text="Hello world!")]))
211
+ async for msg in session.receive():
212
+ if msg.text:
213
+ print(msg.text)
213
214
  """
214
215
  client_content = t.t_client_content(turns, turn_complete).model_dump(
215
216
  mode='json', exclude_none=True
@@ -253,39 +254,40 @@ class AsyncSession:
253
254
  media: A `Blob`-like object, the realtime media to send.
254
255
 
255
256
  Example:
256
- ```
257
- from pathlib import Path
258
257
 
259
- from google import genai
260
- from google.genai import types
258
+ .. code-block:: python
261
259
 
262
- import PIL.Image
260
+ from pathlib import Path
263
261
 
264
- import os
262
+ from google import genai
263
+ from google.genai import types
265
264
 
266
- if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI'):
267
- MODEL_NAME = 'gemini-2.0-flash-live-preview-04-09'
268
- else:
269
- MODEL_NAME = 'gemini-live-2.5-flash-preview';
265
+ import PIL.Image
270
266
 
267
+ import os
271
268
 
272
- client = genai.Client()
269
+ if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI'):
270
+ MODEL_NAME = 'gemini-2.0-flash-live-preview-04-09'
271
+ else:
272
+ MODEL_NAME = 'gemini-live-2.5-flash-preview';
273
273
 
274
- async with client.aio.live.connect(
275
- model=MODEL_NAME,
276
- config={"response_modalities": ["TEXT"]},
277
- ) as session:
278
- await session.send_realtime_input(
279
- media=PIL.Image.open('image.jpg'))
280
274
 
281
- audio_bytes = Path('audio.pcm').read_bytes()
282
- await session.send_realtime_input(
283
- media=types.Blob(data=audio_bytes, mime_type='audio/pcm;rate=16000'))
275
+ client = genai.Client()
284
276
 
285
- async for msg in session.receive():
286
- if msg.text is not None:
287
- print(f'{msg.text}')
288
- ```
277
+ async with client.aio.live.connect(
278
+ model=MODEL_NAME,
279
+ config={"response_modalities": ["TEXT"]},
280
+ ) as session:
281
+ await session.send_realtime_input(
282
+ media=PIL.Image.open('image.jpg'))
283
+
284
+ audio_bytes = Path('audio.pcm').read_bytes()
285
+ await session.send_realtime_input(
286
+ media=types.Blob(data=audio_bytes, mime_type='audio/pcm;rate=16000'))
287
+
288
+ async for msg in session.receive():
289
+ if msg.text is not None:
290
+ print(f'{msg.text}')
289
291
  """
290
292
  kwargs: _common.StringDict = {}
291
293
  if media is not None:
@@ -351,52 +353,54 @@ class AsyncSession:
351
353
  `FunctionResponse`-like objects.
352
354
 
353
355
  Example:
354
- ```
355
- from google import genai
356
- from google.genai import types
357
356
 
358
- import os
357
+ .. code-block:: python
359
358
 
360
- if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI'):
361
- MODEL_NAME = 'gemini-2.0-flash-live-preview-04-09'
362
- else:
363
- MODEL_NAME = 'gemini-live-2.5-flash-preview';
364
-
365
- client = genai.Client()
366
-
367
- tools = [{'function_declarations': [{'name': 'turn_on_the_lights'}]}]
368
- config = {
369
- "tools": tools,
370
- "response_modalities": ['TEXT']
371
- }
372
-
373
- async with client.aio.live.connect(
374
- model='models/gemini-live-2.5-flash-preview',
375
- config=config
376
- ) as session:
377
- prompt = "Turn on the lights please"
378
- await session.send_client_content(
379
- turns={"parts": [{'text': prompt}]}
380
- )
359
+ from google import genai
360
+ from google.genai import types
381
361
 
382
- async for chunk in session.receive():
383
- if chunk.server_content:
384
- if chunk.text is not None:
385
- print(chunk.text)
386
- elif chunk.tool_call:
387
- print(chunk.tool_call)
388
- print('_'*80)
389
- function_response=types.FunctionResponse(
390
- name='turn_on_the_lights',
391
- response={'result': 'ok'},
392
- id=chunk.tool_call.function_calls[0].id,
393
- )
394
- print(function_response)
395
- await session.send_tool_response(
396
- function_responses=function_response
397
- )
362
+ import os
363
+
364
+ if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI'):
365
+ MODEL_NAME = 'gemini-2.0-flash-live-preview-04-09'
366
+ else:
367
+ MODEL_NAME = 'gemini-live-2.5-flash-preview';
368
+
369
+ client = genai.Client()
370
+
371
+ tools = [{'function_declarations': [{'name': 'turn_on_the_lights'}]}]
372
+ config = {
373
+ "tools": tools,
374
+ "response_modalities": ['TEXT']
375
+ }
376
+
377
+ async with client.aio.live.connect(
378
+ model='models/gemini-live-2.5-flash-preview',
379
+ config=config
380
+ ) as session:
381
+ prompt = "Turn on the lights please"
382
+ await session.send_client_content(
383
+ turns={"parts": [{'text': prompt}]}
384
+ )
385
+
386
+ async for chunk in session.receive():
387
+ if chunk.server_content:
388
+ if chunk.text is not None:
389
+ print(chunk.text)
390
+ elif chunk.tool_call:
391
+ print(chunk.tool_call)
392
+ print('_'*80)
393
+ function_response=types.FunctionResponse(
394
+ name='turn_on_the_lights',
395
+ response={'result': 'ok'},
396
+ id=chunk.tool_call.function_calls[0].id,
397
+ )
398
+ print(function_response)
399
+ await session.send_tool_response(
400
+ function_responses=function_response
401
+ )
398
402
 
399
- print('_'*80)
403
+ print('_'*80)
400
404
  """
401
405
  tool_response = t.t_tool_response(function_responses)
402
406
  if self._api_client.vertexai: